14d0e5007SSukumar Swaminathan /*
24d0e5007SSukumar Swaminathan  * CDDL HEADER START
34d0e5007SSukumar Swaminathan  *
44d0e5007SSukumar Swaminathan  * The contents of this file are subject to the terms of the
54d0e5007SSukumar Swaminathan  * Common Development and Distribution License (the "License").
64d0e5007SSukumar Swaminathan  * You may not use this file except in compliance with the License.
74d0e5007SSukumar Swaminathan  *
84d0e5007SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d0e5007SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
104d0e5007SSukumar Swaminathan  * See the License for the specific language governing permissions
114d0e5007SSukumar Swaminathan  * and limitations under the License.
124d0e5007SSukumar Swaminathan  *
134d0e5007SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
144d0e5007SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d0e5007SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
164d0e5007SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
174d0e5007SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
184d0e5007SSukumar Swaminathan  *
194d0e5007SSukumar Swaminathan  * CDDL HEADER END
204d0e5007SSukumar Swaminathan  */
214d0e5007SSukumar Swaminathan 
223abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
234d0e5007SSukumar Swaminathan 
244d0e5007SSukumar Swaminathan /*
250dc2366fSVenugopal Iyer  * Source file containing the Receive Path handling
264d0e5007SSukumar Swaminathan  * functions
274d0e5007SSukumar Swaminathan  */
284d0e5007SSukumar Swaminathan #include <oce_impl.h>
294d0e5007SSukumar Swaminathan 
304d0e5007SSukumar Swaminathan 
315b9d3151SSukumar Swaminathan void oce_rx_pool_free(char *arg);
325b9d3151SSukumar Swaminathan static void oce_rqb_dtor(oce_rq_bdesc_t *rqbd);
335b9d3151SSukumar Swaminathan static int oce_rqb_ctor(oce_rq_bdesc_t *rqbd, struct oce_rq *rq,
345b9d3151SSukumar Swaminathan     size_t size, int flags);
355b9d3151SSukumar Swaminathan 
364d0e5007SSukumar Swaminathan static inline mblk_t *oce_rx(struct oce_dev *dev, struct oce_rq *rq,
374d0e5007SSukumar Swaminathan     struct oce_nic_rx_cqe *cqe);
388d738d7dSSukumar Swaminathan static inline mblk_t *oce_rx_bcopy(struct oce_dev *dev,
398d738d7dSSukumar Swaminathan 	struct oce_rq *rq, struct oce_nic_rx_cqe *cqe);
405b9d3151SSukumar Swaminathan static int oce_rq_charge(struct oce_rq *rq, uint32_t nbufs, boolean_t repost);
418d738d7dSSukumar Swaminathan static void oce_rx_insert_tag(mblk_t *mp, uint16_t vtag);
428d738d7dSSukumar Swaminathan static void oce_set_rx_oflags(mblk_t *mp, struct oce_nic_rx_cqe *cqe);
438d738d7dSSukumar Swaminathan static inline void oce_rx_drop_pkt(struct oce_rq *rq,
448d738d7dSSukumar Swaminathan     struct oce_nic_rx_cqe *cqe);
455b9d3151SSukumar Swaminathan static oce_rq_bdesc_t *oce_rqb_alloc(struct oce_rq *rq);
465b9d3151SSukumar Swaminathan static void oce_rqb_free(struct oce_rq *rq, oce_rq_bdesc_t *rqbd);
475b9d3151SSukumar Swaminathan static void oce_rq_post_buffer(struct oce_rq *rq, int nbufs);
485b9d3151SSukumar Swaminathan 
495b9d3151SSukumar Swaminathan #pragma	inline(oce_rx)
505b9d3151SSukumar Swaminathan #pragma	inline(oce_rx_bcopy)
515b9d3151SSukumar Swaminathan #pragma	inline(oce_rq_charge)
525b9d3151SSukumar Swaminathan #pragma	inline(oce_rx_insert_tag)
535b9d3151SSukumar Swaminathan #pragma	inline(oce_set_rx_oflags)
545b9d3151SSukumar Swaminathan #pragma	inline(oce_rx_drop_pkt)
555b9d3151SSukumar Swaminathan #pragma	inline(oce_rqb_alloc)
565b9d3151SSukumar Swaminathan #pragma	inline(oce_rqb_free)
575b9d3151SSukumar Swaminathan #pragma inline(oce_rq_post_buffer)
585b9d3151SSukumar Swaminathan 
595b9d3151SSukumar Swaminathan static ddi_dma_attr_t oce_rx_buf_attr = {
605b9d3151SSukumar Swaminathan 	DMA_ATTR_V0,		/* version number */
615b9d3151SSukumar Swaminathan 	0x0000000000000000ull,	/* low address */
625b9d3151SSukumar Swaminathan 	0xFFFFFFFFFFFFFFFFull,	/* high address */
635b9d3151SSukumar Swaminathan 	0x00000000FFFFFFFFull,	/* dma counter max */
645b9d3151SSukumar Swaminathan 	OCE_DMA_ALIGNMENT,	/* alignment */
655b9d3151SSukumar Swaminathan 	0x000007FF,		/* burst sizes */
665b9d3151SSukumar Swaminathan 	0x00000001,		/* minimum transfer size */
675b9d3151SSukumar Swaminathan 	0x00000000FFFFFFFFull,	/* maximum transfer size */
685b9d3151SSukumar Swaminathan 	0xFFFFFFFFFFFFFFFFull,	/* maximum segment size */
695b9d3151SSukumar Swaminathan 	1,			/* scatter/gather list length */
705b9d3151SSukumar Swaminathan 	0x00000001,		/* granularity */
715b9d3151SSukumar Swaminathan 	DDI_DMA_FLAGERR|DDI_DMA_RELAXED_ORDERING		/* DMA flags */
725b9d3151SSukumar Swaminathan };
734d0e5007SSukumar Swaminathan 
744d0e5007SSukumar Swaminathan /*
754d0e5007SSukumar Swaminathan  * function to create a DMA buffer pool for RQ
764d0e5007SSukumar Swaminathan  *
774d0e5007SSukumar Swaminathan  * dev - software handle to the device
784d0e5007SSukumar Swaminathan  * num_items - number of buffers in the pool
794d0e5007SSukumar Swaminathan  * item_size - size of each buffer
804d0e5007SSukumar Swaminathan  *
814d0e5007SSukumar Swaminathan  * return DDI_SUCCESS => success, DDI_FAILURE otherwise
824d0e5007SSukumar Swaminathan  */
834d0e5007SSukumar Swaminathan int
oce_rqb_cache_create(struct oce_rq * rq,size_t buf_size)844d0e5007SSukumar Swaminathan oce_rqb_cache_create(struct oce_rq *rq, size_t buf_size)
854d0e5007SSukumar Swaminathan {
864d0e5007SSukumar Swaminathan 	int size;
874d0e5007SSukumar Swaminathan 	int cnt;
884d0e5007SSukumar Swaminathan 	int ret;
895b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
904d0e5007SSukumar Swaminathan 
915b9d3151SSukumar Swaminathan 	_NOTE(ARGUNUSED(buf_size));
925b9d3151SSukumar Swaminathan 	rqbd = rq->rq_bdesc_array;
935b9d3151SSukumar Swaminathan 	size = rq->cfg.frag_size + OCE_RQE_BUF_HEADROOM;
945b9d3151SSukumar Swaminathan 	for (cnt = 0; cnt < rq->cfg.nbufs; cnt++, rqbd++) {
955b9d3151SSukumar Swaminathan 		rq->rqb_freelist[cnt] = rqbd;
965b9d3151SSukumar Swaminathan 		ret = oce_rqb_ctor(rqbd, rq,
975b9d3151SSukumar Swaminathan 		    size, (DDI_DMA_RDWR|DDI_DMA_STREAMING));
984d0e5007SSukumar Swaminathan 		if (ret != DDI_SUCCESS) {
994d0e5007SSukumar Swaminathan 			goto rqb_fail;
1004d0e5007SSukumar Swaminathan 		}
1014d0e5007SSukumar Swaminathan 	}
1025b9d3151SSukumar Swaminathan 	rq->rqb_free = rq->cfg.nbufs;
1035b9d3151SSukumar Swaminathan 	rq->rqb_rc_head = 0;
1045b9d3151SSukumar Swaminathan 	rq->rqb_next_free = 0;
1054d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
1064d0e5007SSukumar Swaminathan 
1074d0e5007SSukumar Swaminathan rqb_fail:
1084d0e5007SSukumar Swaminathan 	oce_rqb_cache_destroy(rq);
1094d0e5007SSukumar Swaminathan 	return (DDI_FAILURE);
1104d0e5007SSukumar Swaminathan } /* oce_rqb_cache_create */
1114d0e5007SSukumar Swaminathan 
1124d0e5007SSukumar Swaminathan /*
1134d0e5007SSukumar Swaminathan  * function to Destroy RQ DMA buffer cache
1144d0e5007SSukumar Swaminathan  *
1154d0e5007SSukumar Swaminathan  * rq - pointer to rq structure
1164d0e5007SSukumar Swaminathan  *
1174d0e5007SSukumar Swaminathan  * return none
1184d0e5007SSukumar Swaminathan  */
1194d0e5007SSukumar Swaminathan void
oce_rqb_cache_destroy(struct oce_rq * rq)1204d0e5007SSukumar Swaminathan oce_rqb_cache_destroy(struct oce_rq *rq)
1214d0e5007SSukumar Swaminathan {
1224d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd = NULL;
1235b9d3151SSukumar Swaminathan 	int cnt;
1244d0e5007SSukumar Swaminathan 
1255b9d3151SSukumar Swaminathan 	rqbd = rq->rq_bdesc_array;
1265b9d3151SSukumar Swaminathan 	for (cnt = 0; cnt < rq->cfg.nbufs; cnt++, rqbd++) {
1274d0e5007SSukumar Swaminathan 		oce_rqb_dtor(rqbd);
1284d0e5007SSukumar Swaminathan 	}
1294d0e5007SSukumar Swaminathan } /* oce_rqb_cache_destroy */
1304d0e5007SSukumar Swaminathan 
1314d0e5007SSukumar Swaminathan /*
1324d0e5007SSukumar Swaminathan  * RQ buffer destructor function
1334d0e5007SSukumar Swaminathan  *
1344d0e5007SSukumar Swaminathan  * rqbd - pointer to rq buffer descriptor
1354d0e5007SSukumar Swaminathan  *
1364d0e5007SSukumar Swaminathan  * return none
1374d0e5007SSukumar Swaminathan  */
1384d0e5007SSukumar Swaminathan static	void
oce_rqb_dtor(oce_rq_bdesc_t * rqbd)1394d0e5007SSukumar Swaminathan oce_rqb_dtor(oce_rq_bdesc_t *rqbd)
1404d0e5007SSukumar Swaminathan {
1414d0e5007SSukumar Swaminathan 	if ((rqbd == NULL) || (rqbd->rq == NULL)) {
1424d0e5007SSukumar Swaminathan 		return;
1434d0e5007SSukumar Swaminathan 	}
1444d0e5007SSukumar Swaminathan 	if (rqbd->mp != NULL) {
1454d0e5007SSukumar Swaminathan 		rqbd->fr_rtn.free_arg = NULL;
1465b9d3151SSukumar Swaminathan 		freemsg(rqbd->mp);
1475b9d3151SSukumar Swaminathan 		rqbd->mp = NULL;
1484d0e5007SSukumar Swaminathan 	}
1495b9d3151SSukumar Swaminathan 	oce_free_dma_buffer(rqbd->rq->parent, rqbd->rqb);
1504d0e5007SSukumar Swaminathan } /* oce_rqb_dtor */
1514d0e5007SSukumar Swaminathan 
1524d0e5007SSukumar Swaminathan /*
1534d0e5007SSukumar Swaminathan  * RQ buffer constructor function
1544d0e5007SSukumar Swaminathan  *
1554d0e5007SSukumar Swaminathan  * rqbd - pointer to rq buffer descriptor
1564d0e5007SSukumar Swaminathan  * rq - pointer to RQ structure
1574d0e5007SSukumar Swaminathan  * size - size of the buffer
1584d0e5007SSukumar Swaminathan  * flags - KM_SLEEP OR KM_NOSLEEP
1594d0e5007SSukumar Swaminathan  *
1604d0e5007SSukumar Swaminathan  * return DDI_SUCCESS => success, DDI_FAILURE otherwise
1614d0e5007SSukumar Swaminathan  */
1624d0e5007SSukumar Swaminathan static int
oce_rqb_ctor(oce_rq_bdesc_t * rqbd,struct oce_rq * rq,size_t size,int flags)1634d0e5007SSukumar Swaminathan oce_rqb_ctor(oce_rq_bdesc_t *rqbd, struct oce_rq *rq, size_t size, int flags)
1644d0e5007SSukumar Swaminathan {
1654d0e5007SSukumar Swaminathan 	struct oce_dev *dev;
1664d0e5007SSukumar Swaminathan 	oce_dma_buf_t *dbuf;
1674d0e5007SSukumar Swaminathan 
1684d0e5007SSukumar Swaminathan 	dev = rq->parent;
1694d0e5007SSukumar Swaminathan 
1705b9d3151SSukumar Swaminathan 	dbuf  = oce_alloc_dma_buffer(dev, size, &oce_rx_buf_attr, flags);
1714d0e5007SSukumar Swaminathan 	if (dbuf == NULL) {
1724d0e5007SSukumar Swaminathan 		return (DDI_FAILURE);
1734d0e5007SSukumar Swaminathan 	}
1744d0e5007SSukumar Swaminathan 
1755b9d3151SSukumar Swaminathan 	/* Set the call back function parameters */
1765b9d3151SSukumar Swaminathan 	rqbd->fr_rtn.free_func = (void (*)())oce_rx_pool_free;
1775b9d3151SSukumar Swaminathan 	rqbd->fr_rtn.free_arg = (caddr_t)(void *)rqbd;
1785b9d3151SSukumar Swaminathan 	rqbd->mp = desballoc((uchar_t *)(dbuf->base),
1795b9d3151SSukumar Swaminathan 	    dbuf->size, 0, &rqbd->fr_rtn);
1805b9d3151SSukumar Swaminathan 	if (rqbd->mp == NULL) {
1815b9d3151SSukumar Swaminathan 		oce_free_dma_buffer(dev, dbuf);
1825b9d3151SSukumar Swaminathan 		return (DDI_FAILURE);
1835b9d3151SSukumar Swaminathan 	}
1844d0e5007SSukumar Swaminathan 	rqbd->rqb = dbuf;
1854d0e5007SSukumar Swaminathan 	rqbd->rq = rq;
1864d0e5007SSukumar Swaminathan 	rqbd->frag_addr.dw.addr_lo = ADDR_LO(dbuf->addr + OCE_RQE_BUF_HEADROOM);
1874d0e5007SSukumar Swaminathan 	rqbd->frag_addr.dw.addr_hi = ADDR_HI(dbuf->addr + OCE_RQE_BUF_HEADROOM);
1884d0e5007SSukumar Swaminathan 	rqbd->mp->b_rptr = (uchar_t *)rqbd->rqb->base + OCE_RQE_BUF_HEADROOM;
1894d0e5007SSukumar Swaminathan 
1904d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
1914d0e5007SSukumar Swaminathan } /* oce_rqb_ctor */
1924d0e5007SSukumar Swaminathan 
1934d0e5007SSukumar Swaminathan /*
1944d0e5007SSukumar Swaminathan  * RQ buffer allocator function
1954d0e5007SSukumar Swaminathan  *
1964d0e5007SSukumar Swaminathan  * rq - pointer to RQ structure
1974d0e5007SSukumar Swaminathan  *
1984d0e5007SSukumar Swaminathan  * return pointer to RQ buffer descriptor
1994d0e5007SSukumar Swaminathan  */
2004d0e5007SSukumar Swaminathan static inline oce_rq_bdesc_t *
oce_rqb_alloc(struct oce_rq * rq)2014d0e5007SSukumar Swaminathan oce_rqb_alloc(struct oce_rq *rq)
2024d0e5007SSukumar Swaminathan {
2034d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
2045b9d3151SSukumar Swaminathan 	uint32_t free_index;
2055b9d3151SSukumar Swaminathan 	free_index = rq->rqb_next_free;
2065b9d3151SSukumar Swaminathan 	rqbd = rq->rqb_freelist[free_index];
2075b9d3151SSukumar Swaminathan 	rq->rqb_freelist[free_index] = NULL;
2085b9d3151SSukumar Swaminathan 	rq->rqb_next_free = GET_Q_NEXT(free_index, 1, rq->cfg.nbufs);
2094d0e5007SSukumar Swaminathan 	return (rqbd);
2104d0e5007SSukumar Swaminathan } /* oce_rqb_alloc */
2114d0e5007SSukumar Swaminathan 
2124d0e5007SSukumar Swaminathan /*
2134d0e5007SSukumar Swaminathan  * function to free the RQ buffer
2144d0e5007SSukumar Swaminathan  *
2154d0e5007SSukumar Swaminathan  * rq - pointer to RQ structure
2164d0e5007SSukumar Swaminathan  * rqbd - pointer to recieve buffer descriptor
2174d0e5007SSukumar Swaminathan  *
2184d0e5007SSukumar Swaminathan  * return none
2194d0e5007SSukumar Swaminathan  */
2204d0e5007SSukumar Swaminathan static inline void
oce_rqb_free(struct oce_rq * rq,oce_rq_bdesc_t * rqbd)2214d0e5007SSukumar Swaminathan oce_rqb_free(struct oce_rq *rq, oce_rq_bdesc_t *rqbd)
2224d0e5007SSukumar Swaminathan {
2235b9d3151SSukumar Swaminathan 	uint32_t free_index;
2245b9d3151SSukumar Swaminathan 	mutex_enter(&rq->rc_lock);
2255b9d3151SSukumar Swaminathan 	free_index = rq->rqb_rc_head;
2265b9d3151SSukumar Swaminathan 	rq->rqb_freelist[free_index] = rqbd;
2275b9d3151SSukumar Swaminathan 	rq->rqb_rc_head = GET_Q_NEXT(free_index, 1, rq->cfg.nbufs);
2285b9d3151SSukumar Swaminathan 	mutex_exit(&rq->rc_lock);
229*1a5e258fSJosef 'Jeff' Sipek 	atomic_inc_32(&rq->rqb_free);
2304d0e5007SSukumar Swaminathan } /* oce_rqb_free */
2314d0e5007SSukumar Swaminathan 
2324d0e5007SSukumar Swaminathan 
2335b9d3151SSukumar Swaminathan 
2345b9d3151SSukumar Swaminathan 
oce_rq_post_buffer(struct oce_rq * rq,int nbufs)2355b9d3151SSukumar Swaminathan static void oce_rq_post_buffer(struct oce_rq *rq, int nbufs)
2365b9d3151SSukumar Swaminathan {
2375b9d3151SSukumar Swaminathan 	pd_rxulp_db_t rxdb_reg;
2385b9d3151SSukumar Swaminathan 	int count;
2395b9d3151SSukumar Swaminathan 	struct oce_dev *dev =  rq->parent;
2405b9d3151SSukumar Swaminathan 
2415b9d3151SSukumar Swaminathan 
2425b9d3151SSukumar Swaminathan 	rxdb_reg.dw0 = 0;
2435b9d3151SSukumar Swaminathan 	rxdb_reg.bits.qid = rq->rq_id & DB_RQ_ID_MASK;
2445b9d3151SSukumar Swaminathan 
2455b9d3151SSukumar Swaminathan 	for (count = nbufs/OCE_MAX_RQ_POSTS; count > 0; count--) {
2465b9d3151SSukumar Swaminathan 		rxdb_reg.bits.num_posted = OCE_MAX_RQ_POSTS;
2475b9d3151SSukumar Swaminathan 		OCE_DB_WRITE32(dev, PD_RXULP_DB, rxdb_reg.dw0);
2485b9d3151SSukumar Swaminathan 		rq->buf_avail += OCE_MAX_RQ_POSTS;
2495b9d3151SSukumar Swaminathan 		nbufs -= OCE_MAX_RQ_POSTS;
2505b9d3151SSukumar Swaminathan 	}
2515b9d3151SSukumar Swaminathan 	if (nbufs > 0) {
2525b9d3151SSukumar Swaminathan 		rxdb_reg.bits.num_posted = nbufs;
2535b9d3151SSukumar Swaminathan 		OCE_DB_WRITE32(dev, PD_RXULP_DB, rxdb_reg.dw0);
2545b9d3151SSukumar Swaminathan 		rq->buf_avail += nbufs;
2555b9d3151SSukumar Swaminathan 	}
2565b9d3151SSukumar Swaminathan }
2574d0e5007SSukumar Swaminathan /*
2584d0e5007SSukumar Swaminathan  * function to charge a given rq with buffers from a pool's free list
2594d0e5007SSukumar Swaminathan  *
2604d0e5007SSukumar Swaminathan  * dev - software handle to the device
2614d0e5007SSukumar Swaminathan  * rq - pointer to the RQ to charge
2624d0e5007SSukumar Swaminathan  * nbufs - numbers of buffers to be charged
2634d0e5007SSukumar Swaminathan  *
2644d0e5007SSukumar Swaminathan  * return number of rqe's charges.
2654d0e5007SSukumar Swaminathan  */
2664d0e5007SSukumar Swaminathan static inline int
oce_rq_charge(struct oce_rq * rq,uint32_t nbufs,boolean_t repost)2675b9d3151SSukumar Swaminathan oce_rq_charge(struct oce_rq *rq, uint32_t nbufs, boolean_t repost)
2684d0e5007SSukumar Swaminathan {
2694d0e5007SSukumar Swaminathan 	struct oce_nic_rqe *rqe;
2704d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
2715b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t **shadow_rq;
2725b9d3151SSukumar Swaminathan 	int cnt;
2735b9d3151SSukumar Swaminathan 	int cur_index;
2745b9d3151SSukumar Swaminathan 	oce_ring_buffer_t *ring;
2754d0e5007SSukumar Swaminathan 
2764d0e5007SSukumar Swaminathan 	shadow_rq = rq->shadow_ring;
2775b9d3151SSukumar Swaminathan 	ring = rq->ring;
2785b9d3151SSukumar Swaminathan 	cur_index = ring->cidx;
2794d0e5007SSukumar Swaminathan 
2805b9d3151SSukumar Swaminathan 	for (cnt = 0; cnt < nbufs; cnt++) {
2815b9d3151SSukumar Swaminathan 		if (!repost) {
2825b9d3151SSukumar Swaminathan 			rqbd = oce_rqb_alloc(rq);
2835b9d3151SSukumar Swaminathan 		} else {
2845b9d3151SSukumar Swaminathan 			/* just repost the buffers from shadow ring */
2855b9d3151SSukumar Swaminathan 			rqbd = shadow_rq[cur_index];
2865b9d3151SSukumar Swaminathan 			cur_index = GET_Q_NEXT(cur_index, 1, ring->num_items);
2874d0e5007SSukumar Swaminathan 		}
2884d0e5007SSukumar Swaminathan 		/* fill the rqes */
2894d0e5007SSukumar Swaminathan 		rqe = RING_GET_PRODUCER_ITEM_VA(rq->ring,
2904d0e5007SSukumar Swaminathan 		    struct oce_nic_rqe);
2914d0e5007SSukumar Swaminathan 		rqe->u0.s.frag_pa_lo = rqbd->frag_addr.dw.addr_lo;
2924d0e5007SSukumar Swaminathan 		rqe->u0.s.frag_pa_hi = rqbd->frag_addr.dw.addr_hi;
2935b9d3151SSukumar Swaminathan 		shadow_rq[rq->ring->pidx] = rqbd;
2944d0e5007SSukumar Swaminathan 		DW_SWAP(u32ptr(rqe), sizeof (struct oce_nic_rqe));
2954d0e5007SSukumar Swaminathan 		RING_PUT(rq->ring, 1);
2964d0e5007SSukumar Swaminathan 	}
2974d0e5007SSukumar Swaminathan 
2985b9d3151SSukumar Swaminathan 	return (cnt);
2994d0e5007SSukumar Swaminathan } /* oce_rq_charge */
3004d0e5007SSukumar Swaminathan 
3014d0e5007SSukumar Swaminathan /*
3024d0e5007SSukumar Swaminathan  * function to release the posted buffers
3034d0e5007SSukumar Swaminathan  *
3044d0e5007SSukumar Swaminathan  * rq - pointer to the RQ to charge
3054d0e5007SSukumar Swaminathan  *
3064d0e5007SSukumar Swaminathan  * return none
3074d0e5007SSukumar Swaminathan  */
3084d0e5007SSukumar Swaminathan void
oce_rq_discharge(struct oce_rq * rq)3094d0e5007SSukumar Swaminathan oce_rq_discharge(struct oce_rq *rq)
3104d0e5007SSukumar Swaminathan {
3114d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
3125b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t **shadow_rq;
3134d0e5007SSukumar Swaminathan 
3144d0e5007SSukumar Swaminathan 	shadow_rq = rq->shadow_ring;
3154d0e5007SSukumar Swaminathan 	/* Free the posted buffer since RQ is destroyed already */
3164d0e5007SSukumar Swaminathan 	while ((int32_t)rq->buf_avail > 0) {
3175b9d3151SSukumar Swaminathan 		rqbd = shadow_rq[rq->ring->cidx];
3184d0e5007SSukumar Swaminathan 		oce_rqb_free(rq, rqbd);
3194d0e5007SSukumar Swaminathan 		RING_GET(rq->ring, 1);
3204d0e5007SSukumar Swaminathan 		rq->buf_avail--;
3214d0e5007SSukumar Swaminathan 	}
3224d0e5007SSukumar Swaminathan }
3234d0e5007SSukumar Swaminathan /*
3244d0e5007SSukumar Swaminathan  * function to process a single packet
3254d0e5007SSukumar Swaminathan  *
3264d0e5007SSukumar Swaminathan  * dev - software handle to the device
3274d0e5007SSukumar Swaminathan  * rq - pointer to the RQ to charge
3284d0e5007SSukumar Swaminathan  * cqe - Pointer to Completion Q entry
3294d0e5007SSukumar Swaminathan  *
3304d0e5007SSukumar Swaminathan  * return mblk pointer =>  success, NULL  => error
3314d0e5007SSukumar Swaminathan  */
3324d0e5007SSukumar Swaminathan static inline mblk_t *
oce_rx(struct oce_dev * dev,struct oce_rq * rq,struct oce_nic_rx_cqe * cqe)3334d0e5007SSukumar Swaminathan oce_rx(struct oce_dev *dev, struct oce_rq *rq, struct oce_nic_rx_cqe *cqe)
3344d0e5007SSukumar Swaminathan {
3354d0e5007SSukumar Swaminathan 	mblk_t *mp;
3364d0e5007SSukumar Swaminathan 	int pkt_len;
3374d0e5007SSukumar Swaminathan 	int32_t frag_cnt = 0;
3385b9d3151SSukumar Swaminathan 	mblk_t **mblk_tail;
3395b9d3151SSukumar Swaminathan 	mblk_t	*mblk_head;
3404d0e5007SSukumar Swaminathan 	int frag_size;
3414d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
3425b9d3151SSukumar Swaminathan 	uint16_t cur_index;
3435b9d3151SSukumar Swaminathan 	oce_ring_buffer_t *ring;
3445b9d3151SSukumar Swaminathan 	int i;
3455b9d3151SSukumar Swaminathan 
3465b9d3151SSukumar Swaminathan 	frag_cnt  = cqe->u0.s.num_fragments & 0x7;
3475b9d3151SSukumar Swaminathan 	mblk_head = NULL;
3485b9d3151SSukumar Swaminathan 	mblk_tail = &mblk_head;
3495b9d3151SSukumar Swaminathan 
3505b9d3151SSukumar Swaminathan 	ring = rq->ring;
3515b9d3151SSukumar Swaminathan 	cur_index = ring->cidx;
3524d0e5007SSukumar Swaminathan 
3534d0e5007SSukumar Swaminathan 	/* Get the relevant Queue pointers */
3544d0e5007SSukumar Swaminathan 	pkt_len = cqe->u0.s.pkt_size;
3555b9d3151SSukumar Swaminathan 	for (i = 0; i < frag_cnt; i++) {
3565b9d3151SSukumar Swaminathan 		rqbd = rq->shadow_ring[cur_index];
3575b9d3151SSukumar Swaminathan 		if (rqbd->mp == NULL) {
3585b9d3151SSukumar Swaminathan 			rqbd->mp = desballoc((uchar_t *)rqbd->rqb->base,
3595b9d3151SSukumar Swaminathan 			    rqbd->rqb->size, 0, &rqbd->fr_rtn);
3605b9d3151SSukumar Swaminathan 			if (rqbd->mp == NULL) {
3615b9d3151SSukumar Swaminathan 				return (NULL);
3625b9d3151SSukumar Swaminathan 			}
3635b9d3151SSukumar Swaminathan 
3645b9d3151SSukumar Swaminathan 			rqbd->mp->b_rptr =
3655b9d3151SSukumar Swaminathan 			    (uchar_t *)rqbd->rqb->base + OCE_RQE_BUF_HEADROOM;
3665b9d3151SSukumar Swaminathan 		}
3675b9d3151SSukumar Swaminathan 
3684d0e5007SSukumar Swaminathan 		mp = rqbd->mp;
3694d0e5007SSukumar Swaminathan 		frag_size  = (pkt_len > rq->cfg.frag_size) ?
3704d0e5007SSukumar Swaminathan 		    rq->cfg.frag_size : pkt_len;
3714d0e5007SSukumar Swaminathan 		mp->b_wptr = mp->b_rptr + frag_size;
3724d0e5007SSukumar Swaminathan 		pkt_len   -= frag_size;
3735b9d3151SSukumar Swaminathan 		mp->b_next = mp->b_cont = NULL;
3744d0e5007SSukumar Swaminathan 		/* Chain the message mblks */
3755b9d3151SSukumar Swaminathan 		*mblk_tail = mp;
3765b9d3151SSukumar Swaminathan 		mblk_tail = &mp->b_cont;
3775b9d3151SSukumar Swaminathan 		(void) DBUF_SYNC(rqbd->rqb, DDI_DMA_SYNC_FORCPU);
3785b9d3151SSukumar Swaminathan 		cur_index = GET_Q_NEXT(cur_index, 1, ring->num_items);
3794d0e5007SSukumar Swaminathan 	}
3804d0e5007SSukumar Swaminathan 
3814d0e5007SSukumar Swaminathan 	if (mblk_head == NULL) {
3824d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_RX, "%s", "oce_rx:no frags?");
3834d0e5007SSukumar Swaminathan 		return (NULL);
3844d0e5007SSukumar Swaminathan 	}
3855b9d3151SSukumar Swaminathan 
3865b9d3151SSukumar Swaminathan 	/* replace the buffer with new ones */
3875b9d3151SSukumar Swaminathan 	(void) oce_rq_charge(rq, frag_cnt, B_FALSE);
3885b9d3151SSukumar Swaminathan 	atomic_add_32(&rq->pending, frag_cnt);
3898d738d7dSSukumar Swaminathan 	return (mblk_head);
3908d738d7dSSukumar Swaminathan } /* oce_rx */
3914d0e5007SSukumar Swaminathan 
3928d738d7dSSukumar Swaminathan static inline mblk_t *
oce_rx_bcopy(struct oce_dev * dev,struct oce_rq * rq,struct oce_nic_rx_cqe * cqe)3938d738d7dSSukumar Swaminathan oce_rx_bcopy(struct oce_dev *dev, struct oce_rq *rq, struct oce_nic_rx_cqe *cqe)
3948d738d7dSSukumar Swaminathan {
3958d738d7dSSukumar Swaminathan 	mblk_t *mp;
3968d738d7dSSukumar Swaminathan 	int pkt_len;
3978d738d7dSSukumar Swaminathan 	int alloc_len;
3988d738d7dSSukumar Swaminathan 	int32_t frag_cnt = 0;
3998d738d7dSSukumar Swaminathan 	int frag_size;
4008d738d7dSSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
4018d738d7dSSukumar Swaminathan 	unsigned char  *rptr;
4025b9d3151SSukumar Swaminathan 	uint32_t cur_index;
4035b9d3151SSukumar Swaminathan 	oce_ring_buffer_t *ring;
4045b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t **shadow_rq;
4055b9d3151SSukumar Swaminathan 	int cnt = 0;
4065b9d3151SSukumar Swaminathan 
4075b9d3151SSukumar Swaminathan 	_NOTE(ARGUNUSED(dev));
4088d738d7dSSukumar Swaminathan 
4098d738d7dSSukumar Swaminathan 	shadow_rq = rq->shadow_ring;
4108d738d7dSSukumar Swaminathan 	pkt_len = cqe->u0.s.pkt_size;
4115b9d3151SSukumar Swaminathan 	alloc_len = pkt_len + OCE_RQE_BUF_HEADROOM;
4125b9d3151SSukumar Swaminathan 	frag_cnt = cqe->u0.s.num_fragments & 0x7;
4134d0e5007SSukumar Swaminathan 
4148d738d7dSSukumar Swaminathan 	mp = allocb(alloc_len, BPRI_HI);
4155b9d3151SSukumar Swaminathan 	if (mp == NULL) {
4164d0e5007SSukumar Swaminathan 		return (NULL);
4178d738d7dSSukumar Swaminathan 	}
4185b9d3151SSukumar Swaminathan 
4195b9d3151SSukumar Swaminathan 	mp->b_rptr += OCE_RQE_BUF_HEADROOM;
4208d738d7dSSukumar Swaminathan 	rptr = mp->b_rptr;
4215b9d3151SSukumar Swaminathan 	mp->b_wptr = mp->b_rptr + pkt_len;
4225b9d3151SSukumar Swaminathan 	ring = rq->ring;
4238d738d7dSSukumar Swaminathan 
4245b9d3151SSukumar Swaminathan 	cur_index = ring->cidx;
4255b9d3151SSukumar Swaminathan 	for (cnt = 0; cnt < frag_cnt; cnt++) {
4265b9d3151SSukumar Swaminathan 		rqbd = shadow_rq[cur_index];
4278d738d7dSSukumar Swaminathan 		frag_size  = (pkt_len > rq->cfg.frag_size) ?
4288d738d7dSSukumar Swaminathan 		    rq->cfg.frag_size : pkt_len;
4295b9d3151SSukumar Swaminathan 		(void) DBUF_SYNC(rqbd->rqb, DDI_DMA_SYNC_FORCPU);
4305b9d3151SSukumar Swaminathan 		bcopy(rqbd->rqb->base + OCE_RQE_BUF_HEADROOM, rptr, frag_size);
4318d738d7dSSukumar Swaminathan 		rptr += frag_size;
4328d738d7dSSukumar Swaminathan 		pkt_len   -= frag_size;
4335b9d3151SSukumar Swaminathan 		cur_index = GET_Q_NEXT(cur_index, 1, ring->num_items);
4344d0e5007SSukumar Swaminathan 	}
4355b9d3151SSukumar Swaminathan 	(void) oce_rq_charge(rq, frag_cnt, B_TRUE);
4368d738d7dSSukumar Swaminathan 	return (mp);
4378d738d7dSSukumar Swaminathan }
4388d738d7dSSukumar Swaminathan 
4398d738d7dSSukumar Swaminathan static inline void
oce_set_rx_oflags(mblk_t * mp,struct oce_nic_rx_cqe * cqe)4408d738d7dSSukumar Swaminathan oce_set_rx_oflags(mblk_t *mp, struct oce_nic_rx_cqe *cqe)
4418d738d7dSSukumar Swaminathan {
4428d738d7dSSukumar Swaminathan 	int csum_flags = 0;
4434d0e5007SSukumar Swaminathan 
4444d0e5007SSukumar Swaminathan 	/* set flags */
4454d0e5007SSukumar Swaminathan 	if (cqe->u0.s.ip_cksum_pass) {
4460dc2366fSVenugopal Iyer 		csum_flags |= HCK_IPV4_HDRCKSUM_OK;
4474d0e5007SSukumar Swaminathan 	}
4484d0e5007SSukumar Swaminathan 
4494d0e5007SSukumar Swaminathan 	if (cqe->u0.s.l4_cksum_pass) {
4504d0e5007SSukumar Swaminathan 		csum_flags |= (HCK_FULLCKSUM | HCK_FULLCKSUM_OK);
4514d0e5007SSukumar Swaminathan 	}
4524d0e5007SSukumar Swaminathan 
4534d0e5007SSukumar Swaminathan 	if (csum_flags) {
4540dc2366fSVenugopal Iyer 		(void) mac_hcksum_set(mp, 0, 0, 0, 0, csum_flags);
4554d0e5007SSukumar Swaminathan 	}
4568d738d7dSSukumar Swaminathan }
4578d738d7dSSukumar Swaminathan 
4588d738d7dSSukumar Swaminathan static inline void
oce_rx_insert_tag(mblk_t * mp,uint16_t vtag)4598d738d7dSSukumar Swaminathan oce_rx_insert_tag(mblk_t *mp, uint16_t vtag)
4608d738d7dSSukumar Swaminathan {
4618d738d7dSSukumar Swaminathan 	struct ether_vlan_header *ehp;
4628d738d7dSSukumar Swaminathan 
4633abb112fSGarrett D'Amore 	(void) memmove(mp->b_rptr - VTAG_SIZE,
4648d738d7dSSukumar Swaminathan 	    mp->b_rptr, 2 * ETHERADDRL);
4653abb112fSGarrett D'Amore 	mp->b_rptr -= VTAG_SIZE;
4668d738d7dSSukumar Swaminathan 	ehp = (struct ether_vlan_header *)voidptr(mp->b_rptr);
4678d738d7dSSukumar Swaminathan 	ehp->ether_tpid = htons(ETHERTYPE_VLAN);
4688d738d7dSSukumar Swaminathan 	ehp->ether_tci = LE_16(vtag);
4698d738d7dSSukumar Swaminathan }
4708d738d7dSSukumar Swaminathan 
4715b9d3151SSukumar Swaminathan static inline void
oce_rx_drop_pkt(struct oce_rq * rq,struct oce_nic_rx_cqe * cqe)4725b9d3151SSukumar Swaminathan oce_rx_drop_pkt(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe)
4735b9d3151SSukumar Swaminathan {
4745b9d3151SSukumar Swaminathan 	int frag_cnt;
4755b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
4765b9d3151SSukumar Swaminathan 	oce_rq_bdesc_t  **shadow_rq;
4775b9d3151SSukumar Swaminathan 	shadow_rq = rq->shadow_ring;
4785b9d3151SSukumar Swaminathan 	for (frag_cnt = 0; frag_cnt < cqe->u0.s.num_fragments; frag_cnt++) {
4795b9d3151SSukumar Swaminathan 		rqbd = shadow_rq[rq->ring->cidx];
4805b9d3151SSukumar Swaminathan 		oce_rqb_free(rq, rqbd);
4815b9d3151SSukumar Swaminathan 		RING_GET(rq->ring, 1);
4825b9d3151SSukumar Swaminathan 	}
4835b9d3151SSukumar Swaminathan }
4844d0e5007SSukumar Swaminathan 
4854d0e5007SSukumar Swaminathan 
4864d0e5007SSukumar Swaminathan /*
4874d0e5007SSukumar Swaminathan  * function to process a Recieve queue
4884d0e5007SSukumar Swaminathan  *
4894d0e5007SSukumar Swaminathan  * arg - pointer to the RQ to charge
4904d0e5007SSukumar Swaminathan  *
4914d0e5007SSukumar Swaminathan  * return number of cqes processed
4924d0e5007SSukumar Swaminathan  */
4934d0e5007SSukumar Swaminathan uint16_t
oce_drain_rq_cq(void * arg)4944d0e5007SSukumar Swaminathan oce_drain_rq_cq(void *arg)
4954d0e5007SSukumar Swaminathan {
4964d0e5007SSukumar Swaminathan 	struct oce_nic_rx_cqe *cqe;
4974d0e5007SSukumar Swaminathan 	struct oce_rq *rq;
4984d0e5007SSukumar Swaminathan 	mblk_t *mp = NULL;
4995b9d3151SSukumar Swaminathan 	mblk_t *mblk_head;
5005b9d3151SSukumar Swaminathan 	mblk_t **mblk_tail;
5014d0e5007SSukumar Swaminathan 	uint16_t num_cqe = 0;
5024d0e5007SSukumar Swaminathan 	struct oce_cq  *cq;
5034d0e5007SSukumar Swaminathan 	struct oce_dev *dev;
5045b9d3151SSukumar Swaminathan 	int32_t frag_cnt;
5055b9d3151SSukumar Swaminathan 	uint32_t nbufs = 0;
5064d0e5007SSukumar Swaminathan 
5074d0e5007SSukumar Swaminathan 	rq = (struct oce_rq *)arg;
5084d0e5007SSukumar Swaminathan 	dev = rq->parent;
5094d0e5007SSukumar Swaminathan 	cq = rq->cq;
5105b9d3151SSukumar Swaminathan 	mblk_head = NULL;
5115b9d3151SSukumar Swaminathan 	mblk_tail = &mblk_head;
5125b9d3151SSukumar Swaminathan 
5134d0e5007SSukumar Swaminathan 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
5144d0e5007SSukumar Swaminathan 
5155b9d3151SSukumar Swaminathan 	(void) DBUF_SYNC(cq->ring->dbuf, DDI_DMA_SYNC_FORKERNEL);
5164d0e5007SSukumar Swaminathan 	/* dequeue till you reach an invalid cqe */
5175b9d3151SSukumar Swaminathan 	while (RQ_CQE_VALID(cqe)) {
5184d0e5007SSukumar Swaminathan 		DW_SWAP(u32ptr(cqe), sizeof (struct oce_nic_rx_cqe));
5195b9d3151SSukumar Swaminathan 		frag_cnt = cqe->u0.s.num_fragments & 0x7;
5208d738d7dSSukumar Swaminathan 		/* if insufficient buffers to charge then do copy */
5215b9d3151SSukumar Swaminathan 		if ((cqe->u0.s.pkt_size < dev->rx_bcopy_limit) ||
5225b9d3151SSukumar Swaminathan 		    (oce_atomic_reserve(&rq->rqb_free, frag_cnt) < 0)) {
5238d738d7dSSukumar Swaminathan 			mp = oce_rx_bcopy(dev, rq, cqe);
5248d738d7dSSukumar Swaminathan 		} else {
5258d738d7dSSukumar Swaminathan 			mp = oce_rx(dev, rq, cqe);
5265b9d3151SSukumar Swaminathan 			if (mp == NULL) {
5275b9d3151SSukumar Swaminathan 				atomic_add_32(&rq->rqb_free, frag_cnt);
5285b9d3151SSukumar Swaminathan 				mp = oce_rx_bcopy(dev, rq, cqe);
5295b9d3151SSukumar Swaminathan 			}
5308d738d7dSSukumar Swaminathan 		}
5314d0e5007SSukumar Swaminathan 		if (mp != NULL) {
5323abb112fSGarrett D'Amore 			if (dev->function_mode & FLEX10_MODE) {
5333abb112fSGarrett D'Amore 				if (cqe->u0.s.vlan_tag_present &&
5343abb112fSGarrett D'Amore 				    cqe->u0.s.qnq) {
5353abb112fSGarrett D'Amore 					oce_rx_insert_tag(mp,
5363abb112fSGarrett D'Amore 					    cqe->u0.s.vlan_tag);
5373abb112fSGarrett D'Amore 				}
5383abb112fSGarrett D'Amore 			} else if (cqe->u0.s.vlan_tag_present) {
5398d738d7dSSukumar Swaminathan 				oce_rx_insert_tag(mp, cqe->u0.s.vlan_tag);
5408d738d7dSSukumar Swaminathan 			}
5418d738d7dSSukumar Swaminathan 			oce_set_rx_oflags(mp, cqe);
5428d738d7dSSukumar Swaminathan 
5435b9d3151SSukumar Swaminathan 			*mblk_tail = mp;
5445b9d3151SSukumar Swaminathan 			mblk_tail = &mp->b_next;
5458d738d7dSSukumar Swaminathan 		} else {
5465b9d3151SSukumar Swaminathan 			(void) oce_rq_charge(rq, frag_cnt, B_TRUE);
5474d0e5007SSukumar Swaminathan 		}
5485b9d3151SSukumar Swaminathan 		RING_GET(rq->ring, frag_cnt);
5495b9d3151SSukumar Swaminathan 		rq->buf_avail -= frag_cnt;
5505b9d3151SSukumar Swaminathan 		nbufs += frag_cnt;
5515b9d3151SSukumar Swaminathan 
5525b9d3151SSukumar Swaminathan 		oce_rq_post_buffer(rq, frag_cnt);
5534d0e5007SSukumar Swaminathan 		RQ_CQE_INVALIDATE(cqe);
5544d0e5007SSukumar Swaminathan 		RING_GET(cq->ring, 1);
5554d0e5007SSukumar Swaminathan 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
5564d0e5007SSukumar Swaminathan 		    struct oce_nic_rx_cqe);
5574d0e5007SSukumar Swaminathan 		num_cqe++;
5585b9d3151SSukumar Swaminathan 		/* process max ring size */
5595b9d3151SSukumar Swaminathan 		if (num_cqe > dev->rx_pkt_per_intr) {
5605b9d3151SSukumar Swaminathan 			break;
5615b9d3151SSukumar Swaminathan 		}
5624d0e5007SSukumar Swaminathan 	} /* for all valid CQEs */
5635b9d3151SSukumar Swaminathan 
5644d0e5007SSukumar Swaminathan 	if (mblk_head) {
5654d0e5007SSukumar Swaminathan 		mac_rx(dev->mac_handle, NULL, mblk_head);
5664d0e5007SSukumar Swaminathan 	}
5674d0e5007SSukumar Swaminathan 	oce_arm_cq(dev, cq->cq_id, num_cqe, B_TRUE);
5684d0e5007SSukumar Swaminathan 	return (num_cqe);
5694d0e5007SSukumar Swaminathan } /* oce_drain_rq_cq */
5704d0e5007SSukumar Swaminathan 
5714d0e5007SSukumar Swaminathan /*
5724d0e5007SSukumar Swaminathan  * function to free mblk databuffer to the RQ pool
5734d0e5007SSukumar Swaminathan  *
5744d0e5007SSukumar Swaminathan  * arg - pointer to the receive buffer descriptor
5754d0e5007SSukumar Swaminathan  *
5764d0e5007SSukumar Swaminathan  * return none
5774d0e5007SSukumar Swaminathan  */
5785b9d3151SSukumar Swaminathan void
oce_rx_pool_free(char * arg)5795b9d3151SSukumar Swaminathan oce_rx_pool_free(char *arg)
5804d0e5007SSukumar Swaminathan {
5814d0e5007SSukumar Swaminathan 	oce_rq_bdesc_t *rqbd;
5824d0e5007SSukumar Swaminathan 	struct oce_rq  *rq;
5834d0e5007SSukumar Swaminathan 
5844d0e5007SSukumar Swaminathan 	/* During destroy, arg will be NULL */
5854d0e5007SSukumar Swaminathan 	if (arg == NULL) {
5864d0e5007SSukumar Swaminathan 		return;
5874d0e5007SSukumar Swaminathan 	}
5884d0e5007SSukumar Swaminathan 
5894d0e5007SSukumar Swaminathan 	/* retrieve the pointers from arg */
5904d0e5007SSukumar Swaminathan 	rqbd = (oce_rq_bdesc_t *)(void *)arg;
5914d0e5007SSukumar Swaminathan 	rq = rqbd->rq;
5925b9d3151SSukumar Swaminathan 	rqbd->mp = desballoc((uchar_t *)rqbd->rqb->base,
5938d738d7dSSukumar Swaminathan 	    rqbd->rqb->size, 0, &rqbd->fr_rtn);
5945b9d3151SSukumar Swaminathan 
5955b9d3151SSukumar Swaminathan 	if (rqbd->mp) {
5965b9d3151SSukumar Swaminathan 		rqbd->mp->b_rptr =
5975b9d3151SSukumar Swaminathan 		    (uchar_t *)rqbd->rqb->base + OCE_RQE_BUF_HEADROOM;
5984d0e5007SSukumar Swaminathan 	}
5995b9d3151SSukumar Swaminathan 
6004d0e5007SSukumar Swaminathan 	oce_rqb_free(rq, rqbd);
601*1a5e258fSJosef 'Jeff' Sipek 	(void) atomic_dec_32(&rq->pending);
6024d0e5007SSukumar Swaminathan } /* rx_pool_free */
6034d0e5007SSukumar Swaminathan 
6044d0e5007SSukumar Swaminathan /*
6054d0e5007SSukumar Swaminathan  * function to stop the RX
6064d0e5007SSukumar Swaminathan  *
6074d0e5007SSukumar Swaminathan  * rq - pointer to RQ structure
6084d0e5007SSukumar Swaminathan  *
6094d0e5007SSukumar Swaminathan  * return none
6104d0e5007SSukumar Swaminathan  */
6114d0e5007SSukumar Swaminathan void
oce_clean_rq(struct oce_rq * rq)6128d738d7dSSukumar Swaminathan oce_clean_rq(struct oce_rq *rq)
6134d0e5007SSukumar Swaminathan {
6148d738d7dSSukumar Swaminathan 	uint16_t num_cqe = 0;
6158d738d7dSSukumar Swaminathan 	struct oce_cq  *cq;
6168d738d7dSSukumar Swaminathan 	struct oce_dev *dev;
6178d738d7dSSukumar Swaminathan 	struct oce_nic_rx_cqe *cqe;
6188d738d7dSSukumar Swaminathan 	int32_t ti = 0;
6194d0e5007SSukumar Swaminathan 
6208d738d7dSSukumar Swaminathan 	dev = rq->parent;
6218d738d7dSSukumar Swaminathan 	cq = rq->cq;
6228d738d7dSSukumar Swaminathan 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
6238d738d7dSSukumar Swaminathan 	/* dequeue till you reach an invalid cqe */
6248d738d7dSSukumar Swaminathan 	for (ti = 0; ti < DEFAULT_DRAIN_TIME; ti++) {
6258d738d7dSSukumar Swaminathan 
6268d738d7dSSukumar Swaminathan 		while (RQ_CQE_VALID(cqe)) {
6278d738d7dSSukumar Swaminathan 			DW_SWAP(u32ptr(cqe), sizeof (struct oce_nic_rx_cqe));
6288d738d7dSSukumar Swaminathan 			oce_rx_drop_pkt(rq, cqe);
6298d738d7dSSukumar Swaminathan 			atomic_add_32(&rq->buf_avail,
6308d738d7dSSukumar Swaminathan 			    -(cqe->u0.s.num_fragments & 0x7));
6318d738d7dSSukumar Swaminathan 			oce_arm_cq(dev, cq->cq_id, 1, B_TRUE);
6328d738d7dSSukumar Swaminathan 			RQ_CQE_INVALIDATE(cqe);
6338d738d7dSSukumar Swaminathan 			RING_GET(cq->ring, 1);
6348d738d7dSSukumar Swaminathan 			cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
6358d738d7dSSukumar Swaminathan 			    struct oce_nic_rx_cqe);
6368d738d7dSSukumar Swaminathan 			num_cqe++;
6378d738d7dSSukumar Swaminathan 		}
6388d738d7dSSukumar Swaminathan 		OCE_MSDELAY(1);
6398d738d7dSSukumar Swaminathan 	}
6408d738d7dSSukumar Swaminathan } /* oce_clean_rq */
6414d0e5007SSukumar Swaminathan 
6424d0e5007SSukumar Swaminathan /*
6434d0e5007SSukumar Swaminathan  * function to start  the RX
6444d0e5007SSukumar Swaminathan  *
6454d0e5007SSukumar Swaminathan  * rq - pointer to RQ structure
6464d0e5007SSukumar Swaminathan  *
6474d0e5007SSukumar Swaminathan  * return number of rqe's charges.
6484d0e5007SSukumar Swaminathan  */
6494d0e5007SSukumar Swaminathan int
oce_start_rq(struct oce_rq * rq)6504d0e5007SSukumar Swaminathan oce_start_rq(struct oce_rq *rq)
6514d0e5007SSukumar Swaminathan {
6524d0e5007SSukumar Swaminathan 	int ret = 0;
6535b9d3151SSukumar Swaminathan 	int to_charge = 0;
6544d0e5007SSukumar Swaminathan 	struct oce_dev *dev = rq->parent;
6555b9d3151SSukumar Swaminathan 	to_charge = rq->cfg.q_len - rq->buf_avail;
6565b9d3151SSukumar Swaminathan 	to_charge = min(to_charge, rq->rqb_free);
6575b9d3151SSukumar Swaminathan 	atomic_add_32(&rq->rqb_free, -to_charge);
6585b9d3151SSukumar Swaminathan 	(void) oce_rq_charge(rq, to_charge, B_FALSE);
6595b9d3151SSukumar Swaminathan 	/* ok to do it here since Rx has not even started */
6605b9d3151SSukumar Swaminathan 	oce_rq_post_buffer(rq, to_charge);
6614d0e5007SSukumar Swaminathan 	oce_arm_cq(dev, rq->cq->cq_id, 0, B_TRUE);
6624d0e5007SSukumar Swaminathan 	return (ret);
6634d0e5007SSukumar Swaminathan } /* oce_start_rq */
6648d738d7dSSukumar Swaminathan 
6658d738d7dSSukumar Swaminathan /* Checks for pending rx buffers with Stack */
6668d738d7dSSukumar Swaminathan int
oce_rx_pending(struct oce_dev * dev,struct oce_rq * rq,int32_t timeout)6675b9d3151SSukumar Swaminathan oce_rx_pending(struct oce_dev *dev, struct oce_rq *rq, int32_t timeout)
6688d738d7dSSukumar Swaminathan {
6698d738d7dSSukumar Swaminathan 	int ti;
6705b9d3151SSukumar Swaminathan 	_NOTE(ARGUNUSED(dev));
6718d738d7dSSukumar Swaminathan 
6725b9d3151SSukumar Swaminathan 	for (ti = 0; ti < timeout; ti++) {
6735b9d3151SSukumar Swaminathan 		if (rq->pending > 0) {
6745b9d3151SSukumar Swaminathan 			OCE_MSDELAY(10);
6758d738d7dSSukumar Swaminathan 			continue;
6768d738d7dSSukumar Swaminathan 		} else {
6775b9d3151SSukumar Swaminathan 			rq->pending = 0;
6788d738d7dSSukumar Swaminathan 			break;
6798d738d7dSSukumar Swaminathan 		}
6808d738d7dSSukumar Swaminathan 	}
6815b9d3151SSukumar Swaminathan 	return (rq->pending);
6828d738d7dSSukumar Swaminathan }
683