oce_rx.c revision 12d61dab3304980e691068219eaaab6398744a2e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Emulex. All rights reserved.
* Use is subject to license terms.
*/
/*
* Source file containing the Receive Path handling
* functions
*/
#include <oce_impl.h>
static void rx_pool_free(char *arg);
struct oce_nic_rx_cqe *cqe);
struct oce_nic_rx_cqe *cqe);
/*
* function to create a DMA buffer pool for RQ
*
* dev - software handle to the device
* num_items - number of buffers in the pool
* item_size - size of each buffer
*
* return DDI_SUCCESS => success, DDI_FAILURE otherwise
*/
int
{
int size;
int cnt;
int ret;
int nitems;
return (DDI_FAILURE);
}
/* Create the free buffer list */
if (ret != DDI_SUCCESS) {
goto rqb_fail;
}
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
} /* oce_rqb_cache_create */
/*
* function to Destroy RQ DMA buffer cache
*
* rq - pointer to rq structure
*
* return none
*/
void
{
!= NULL) {
}
} /* oce_rqb_cache_destroy */
/*
* RQ buffer destructor function
*
* rqbd - pointer to rq buffer descriptor
*
* return none
*/
static void
{
return;
}
/* Buffer is already free */
}
} /* oce_rqb_dtor */
/*
* RQ buffer constructor function
*
* rqbd - pointer to rq buffer descriptor
* rq - pointer to RQ structure
* size - size of the buffer
* flags - KM_SLEEP OR KM_NOSLEEP
*
* return DDI_SUCCESS => success, DDI_FAILURE otherwise
*/
static int
{
return (DDI_FAILURE);
}
/* override usable length */
return (DDI_SUCCESS);
} /* oce_rqb_ctor */
/*
* RQ buffer allocator function
*
* rq - pointer to RQ structure
*
* return pointer to RQ buffer descriptor
*/
static inline oce_rq_bdesc_t *
{
return (rqbd);
} /* oce_rqb_alloc */
/*
* function to free the RQ buffer
*
* rq - pointer to RQ structure
* rqbd - pointer to recieve buffer descriptor
*
* return none
*/
static inline void
{
} /* oce_rqb_free */
/*
* function to charge a given rq with buffers from a pool's free list
*
* dev - software handle to the device
* rq - pointer to the RQ to charge
* nbufs - numbers of buffers to be charged
*
* return number of rqe's charges.
*/
static inline int
{
struct oce_nic_rqe *rqe;
struct rq_shadow_entry *shadow_rq;
int32_t total_bufs = 0;
/* check number of slots free and recharge */
"rqb pool empty @ ticks",
(uint32_t)ddi_get_lbolt());
break;
}
}
/*
* Failed again put back the buffer and continue
* loops for nbufs so its a finite loop
*/
continue;
}
}
/* fill the rqes */
struct oce_nic_rqe);
/* if we have reached the max allowed posts, post */
DDI_FM_OK) {
}
num_bufs = 0;
}
num_bufs++;
total_bufs++;
}
/* post pending bufs */
if (num_bufs) {
DDI_FM_OK) {
}
}
return (total_bufs);
} /* oce_rq_charge */
/*
* function to release the posted buffers
*
* rq - pointer to the RQ to charge
*
* return none
*/
void
{
struct rq_shadow_entry *shadow_rq;
/* Free the posted buffer since RQ is destroyed already */
}
}
/*
* function to process a single packet
*
* dev - software handle to the device
* rq - pointer to the RQ to charge
* cqe - Pointer to Completion Q entry
*
* return mblk pointer => success, NULL => error
*/
static inline mblk_t *
{
int pkt_len;
int frag_size;
struct rq_shadow_entry *shadow_rq;
struct rq_shadow_entry *shadow_rqe;
/* Get the relevant Queue pointers */
return (NULL);
/* Chain the message mblks */
} else {
}
}
return (NULL);
}
return (mblk_head);
} /* oce_rx */
/* ARGSUSED */
static inline mblk_t *
{
int pkt_len;
int alloc_len;
int frag_size;
struct rq_shadow_entry *shadow_rq;
struct rq_shadow_entry *shadow_rqe;
unsigned char *rptr;
/* Hardware always Strips Vlan tag so insert it back */
alloc_len += VLAN_TAGSZ;
}
return (NULL);
if (tag_present) {
/* offset the read pointer by 4 bytes to insert tag */
}
}
return (mp);
}
static inline void
{
int csum_flags = 0;
/* set flags */
}
}
if (csum_flags) {
}
}
static inline void
{
struct ether_vlan_header *ehp;
}
/*
* function to process a Recieve queue
*
* arg - pointer to the RQ to charge
*
* return number of cqes processed
*/
oce_drain_rq_cq(void *arg)
{
struct oce_nic_rx_cqe *cqe;
return (0);
/* dequeue till you reach an invalid cqe */
/* if insufficient buffers to charge then do copy */
} else {
}
}
} else {
}
} else {
}
struct oce_nic_rx_cqe);
num_cqe++;
} /* for all valid CQEs */
if (mblk_head) {
}
return (num_cqe);
} /* oce_drain_rq_cq */
/*
* function to free mblk databuffer to the RQ pool
*
* arg - pointer to the receive buffer descriptor
*
* return none
*/
static void
rx_pool_free(char *arg)
{
/* During destroy, arg will be NULL */
return;
}
/* retrieve the pointers from arg */
}
} /* rx_pool_free */
/*
* function to stop the RX
*
* rq - pointer to RQ structure
*
* return none
*/
void
{
struct oce_nic_rx_cqe *cqe;
/* dequeue till you reach an invalid cqe */
while (RQ_CQE_VALID(cqe)) {
struct oce_nic_rx_cqe);
num_cqe++;
}
OCE_MSDELAY(1);
}
#if 0
if (num_cqe) {
}
/* Drain the Event queue now */
return (num_cqe);
#endif
} /* oce_clean_rq */
/*
* function to start the RX
*
* rq - pointer to RQ structure
*
* return number of rqe's charges.
*/
int
{
int ret = 0;
return (ret);
} /* oce_start_rq */
/* Checks for pending rx buffers with Stack */
int
{
int ti;
OCE_MSDELAY(1);
continue;
} else {
break;
}
}
}
static inline void
{
int frag_cnt;
struct rq_shadow_entry *shadow_rq;
}
}