diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceRx.c')
-rw-r--r-- | drivers/staging/bcm/InterfaceRx.c | 206 |
1 files changed, 131 insertions, 75 deletions
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c index 11008173f915..0f179b9382d3 100644 --- a/drivers/staging/bcm/InterfaceRx.c +++ b/drivers/staging/bcm/InterfaceRx.c @@ -1,5 +1,92 @@ #include "headers.h" +static void handle_control_packet(struct bcm_interface_adapter *interface, + struct bcm_mini_adapter *ad, + struct bcm_leader *leader, + struct sk_buff *skb, + struct urb *urb) +{ + BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, + "Received control pkt..."); + *(PUSHORT)skb->data = leader->Status; + memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + + (sizeof(struct bcm_leader)), leader->PLength); + skb->len = leader->PLength + sizeof(USHORT); + + spin_lock(&ad->control_queue_lock); + ENQUEUEPACKET(ad->RxControlHead, ad->RxControlTail, skb); + spin_unlock(&ad->control_queue_lock); + + atomic_inc(&ad->cntrlpktCnt); + wake_up(&ad->process_rx_cntrlpkt); +} + +static void format_eth_hdr_to_stack(struct bcm_interface_adapter *interface, + struct bcm_mini_adapter *ad, + struct bcm_leader *p_leader, + struct sk_buff *skb, + struct urb *urb, + UINT ui_index, + int queue_index, + bool b_header_supression_endabled) +{ + /* + * Data Packet, Format a proper Ethernet Header + * and give it to the stack + */ + BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA, + DBG_LVL_ALL, "Received Data pkt..."); + skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); + memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + + sizeof(struct bcm_leader), p_leader->PLength); + skb->dev = ad->dev; + + /* currently skb->len has extra ETH_HLEN bytes in the beginning */ + skb_put(skb, p_leader->PLength + ETH_HLEN); + ad->PackInfo[queue_index].uiTotalRxBytes += p_leader->PLength; + ad->PackInfo[queue_index].uiThisPeriodRxBytes += p_leader->PLength; + BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA, + DBG_LVL_ALL, "Received Data pkt of len :0x%X", + p_leader->PLength); + + if (netif_running(ad->dev)) { + /* Moving ahead by ETH_HLEN to the data ptr as received from FW */ + skb_pull(skb, ETH_HLEN); + PHSReceive(ad, p_leader->Vcid, skb, &skb->len, + NULL, b_header_supression_endabled); + + if (!ad->PackInfo[queue_index].bEthCSSupport) { + skb_push(skb, ETH_HLEN); + + memcpy(skb->data, skb->dev->dev_addr, 6); + memcpy(skb->data+6, skb->dev->dev_addr, 6); + (*(skb->data+11))++; + *(skb->data+12) = 0x08; + *(skb->data+13) = 0x00; + p_leader->PLength += ETH_HLEN; + } + + skb->protocol = eth_type_trans(skb, ad->dev); + netif_rx(skb); + } else { + BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, + RX_DATA, DBG_LVL_ALL, + "i/f not up hance freeing SKB..."); + dev_kfree_skb(skb); + } + + ++ad->dev->stats.rx_packets; + ad->dev->stats.rx_bytes += p_leader->PLength; + + for (ui_index = 0; ui_index < MIBS_MAX_HIST_ENTRIES; ui_index++) { + if ((p_leader->PLength <= + MIBS_PKTSIZEHIST_RANGE*(ui_index+1)) && + (p_leader->PLength > MIBS_PKTSIZEHIST_RANGE*(ui_index))) + + ad->aRxPktSizeHist[ui_index]++; + } +} + static int SearchVcid(struct bcm_mini_adapter *Adapter, unsigned short usVcid) { int iIndex = 0; @@ -24,8 +111,9 @@ GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter) pRcb = &psIntfAdapter->asUsbRcb[index]; pRcb->bUsed = TRUE; pRcb->psIntfAdapter = psIntfAdapter; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d", - index, atomic_read(&psIntfAdapter->uNumRcbUsed)); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, + DBG_LVL_ALL, "Got Rx desc %d used %d", index, + atomic_read(&psIntfAdapter->uNumRcbUsed)); index = (index + 1) % MAXIMUM_USB_RCB; atomic_set(&psIntfAdapter->uCurrRcb, index); atomic_inc(&psIntfAdapter->uNumRcbUsed); @@ -40,7 +128,6 @@ static void read_bulk_callback(struct urb *urb) bool bHeaderSupressionEnabled = false; int QueueIndex = NO_OF_QUEUES + 1; UINT uiIndex = 0; - int process_done = 1; struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context; struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter; struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; @@ -63,7 +150,10 @@ static void read_bulk_callback(struct urb *urb) Adapter->bEndPointHalted = TRUE; wake_up(&Adapter->tx_packet_wait_queue); } else { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Rx URB has got cancelled. status :%d", urb->status); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, + DBG_LVL_ALL, + "Rx URB has got cancelled. status :%d", + urb->status); } pRcb->bUsed = false; atomic_dec(&psIntfAdapter->uNumRcbUsed); @@ -72,17 +162,22 @@ static void read_bulk_callback(struct urb *urb) } if (Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "device is going in low power mode while PMU option selected..hence rx packet should not be process"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, + "device is going in low power mode while PMU option selected..hence rx packet should not be process"); return; } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, + "Read back done len %d\n", pLeader->PLength); if (!pLeader->PLength) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, + "Leader Length 0"); atomic_dec(&psIntfAdapter->uNumRcbUsed); return; } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status, pLeader->PLength, pLeader->Vcid); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, + "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", + pLeader->Status, pLeader->PLength, pLeader->Vcid); if (MAX_CNTL_PKT_SIZE < pLeader->PLength) { if (netif_msg_rx_err(Adapter)) pr_info(PFX "%s: corrupted leader length...%d\n", @@ -100,95 +195,52 @@ static void read_bulk_callback(struct urb *urb) bHeaderSupressionEnabled & Adapter->bPHSEnabled; } - skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER); + skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES + + SKB_RESERVE_ETHERNET_HEADER); if (!skb) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "NO SKBUFF!!! Dropping the Packet"); atomic_dec(&psIntfAdapter->uNumRcbUsed); return; } /* If it is a control Packet, then call handle_bcm_packet ()*/ if ((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) || (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt..."); - *(PUSHORT)skb->data = pLeader->Status; - memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + - (sizeof(struct bcm_leader)), pLeader->PLength); - skb->len = pLeader->PLength + sizeof(USHORT); - - spin_lock(&Adapter->control_queue_lock); - ENQUEUEPACKET(Adapter->RxControlHead, Adapter->RxControlTail, skb); - spin_unlock(&Adapter->control_queue_lock); - - atomic_inc(&Adapter->cntrlpktCnt); - wake_up(&Adapter->process_rx_cntrlpkt); + handle_control_packet(psIntfAdapter, Adapter, pLeader, skb, + urb); } else { - /* - * Data Packet, Format a proper Ethernet Header - * and give it to the stack - */ - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt..."); - skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); - memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_leader), pLeader->PLength); - skb->dev = Adapter->dev; - - /* currently skb->len has extra ETH_HLEN bytes in the beginning */ - skb_put(skb, pLeader->PLength + ETH_HLEN); - Adapter->PackInfo[QueueIndex].uiTotalRxBytes += pLeader->PLength; - Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes += pLeader->PLength; - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength); - - if (netif_running(Adapter->dev)) { - /* Moving ahead by ETH_HLEN to the data ptr as received from FW */ - skb_pull(skb, ETH_HLEN); - PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len, - NULL, bHeaderSupressionEnabled); - - if (!Adapter->PackInfo[QueueIndex].bEthCSSupport) { - skb_push(skb, ETH_HLEN); - - memcpy(skb->data, skb->dev->dev_addr, 6); - memcpy(skb->data+6, skb->dev->dev_addr, 6); - (*(skb->data+11))++; - *(skb->data+12) = 0x08; - *(skb->data+13) = 0x00; - pLeader->PLength += ETH_HLEN; - } - - skb->protocol = eth_type_trans(skb, Adapter->dev); - process_done = netif_rx(skb); - } else { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB..."); - dev_kfree_skb(skb); - } - - ++Adapter->dev->stats.rx_packets; - Adapter->dev->stats.rx_bytes += pLeader->PLength; - - for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) { - if ((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && - (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) - Adapter->aRxPktSizeHist[uiIndex]++; - } + format_eth_hdr_to_stack(psIntfAdapter, Adapter, pLeader, skb, + urb, uiIndex, QueueIndex, + bHeaderSupressionEnabled); } Adapter->PrevNumRecvDescs++; pRcb->bUsed = false; atomic_dec(&psIntfAdapter->uNumRcbUsed); } -static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb) +static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, + struct bcm_usb_rcb *pRcb) { struct urb *urb = pRcb->urb; int retval = 0; - usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr), - urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback, pRcb); + usb_fill_bulk_urb(urb, psIntfAdapter->udev, + usb_rcvbulkpipe(psIntfAdapter->udev, + psIntfAdapter->sBulkIn.bulk_in_endpointAddr), + urb->transfer_buffer, + BCM_USB_MAX_READ_LENGTH, + read_bulk_callback, pRcb); + if (false == psIntfAdapter->psAdapter->device_removed && false == psIntfAdapter->psAdapter->bEndPointHalted && false == psIntfAdapter->bSuspended && false == psIntfAdapter->bPreparingForBusSuspend) { retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, + RX_DPC, DBG_LVL_ALL, + "failed submitting read urb, error %d", + retval); /* if this return value is because of pipe halt. need to clear this. */ if (retval == -EPIPE) { psIntfAdapter->psAdapter->bEndPointHalted = TRUE; @@ -216,13 +268,17 @@ Return: TRUE - If Rx was successful. bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter) { - USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed); + USHORT RxDescCount = NUM_RX_DESC - + atomic_read(&psIntfAdapter->uNumRcbUsed); + struct bcm_usb_rcb *pRcb = NULL; while (RxDescCount) { pRcb = GetBulkInRcb(psIntfAdapter); if (pRcb == NULL) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer"); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, + DBG_TYPE_PRINTK, 0, 0, + "Unable to get Rcb pointer"); return false; } ReceiveRcb(psIntfAdapter, pRcb); |