Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.16 233 lines 8.2 kB view raw
1#include "headers.h" 2 3static int SearchVcid(struct bcm_mini_adapter *Adapter, unsigned short usVcid) 4{ 5 int iIndex = 0; 6 7 for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--) 8 if (Adapter->PackInfo[iIndex].usVCID_Value == usVcid) 9 return iIndex; 10 return NO_OF_QUEUES+1; 11 12} 13 14 15static struct bcm_usb_rcb * 16GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter) 17{ 18 struct bcm_usb_rcb *pRcb = NULL; 19 UINT index = 0; 20 21 if ((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) && 22 (psIntfAdapter->psAdapter->StopAllXaction == false)) { 23 index = atomic_read(&psIntfAdapter->uCurrRcb); 24 pRcb = &psIntfAdapter->asUsbRcb[index]; 25 pRcb->bUsed = TRUE; 26 pRcb->psIntfAdapter = psIntfAdapter; 27 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d", 28 index, atomic_read(&psIntfAdapter->uNumRcbUsed)); 29 index = (index + 1) % MAXIMUM_USB_RCB; 30 atomic_set(&psIntfAdapter->uCurrRcb, index); 31 atomic_inc(&psIntfAdapter->uNumRcbUsed); 32 } 33 return pRcb; 34} 35 36/*this is receive call back - when pkt available for receive (BULK IN- end point)*/ 37static void read_bulk_callback(struct urb *urb) 38{ 39 struct sk_buff *skb = NULL; 40 bool bHeaderSupressionEnabled = false; 41 int QueueIndex = NO_OF_QUEUES + 1; 42 UINT uiIndex = 0; 43 int process_done = 1; 44 struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context; 45 struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter; 46 struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; 47 struct bcm_leader *pLeader = urb->transfer_buffer; 48 49 if (unlikely(netif_msg_rx_status(Adapter))) 50 pr_info(PFX "%s: rx urb status %d length %d\n", 51 Adapter->dev->name, urb->status, urb->actual_length); 52 53 if ((Adapter->device_removed == TRUE) || 54 (TRUE == Adapter->bEndPointHalted) || 55 (0 == urb->actual_length)) { 56 pRcb->bUsed = false; 57 atomic_dec(&psIntfAdapter->uNumRcbUsed); 58 return; 59 } 60 61 if (urb->status != STATUS_SUCCESS) { 62 if (urb->status == -EPIPE) { 63 Adapter->bEndPointHalted = TRUE; 64 wake_up(&Adapter->tx_packet_wait_queue); 65 } else { 66 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Rx URB has got cancelled. status :%d", urb->status); 67 } 68 pRcb->bUsed = false; 69 atomic_dec(&psIntfAdapter->uNumRcbUsed); 70 urb->status = STATUS_SUCCESS; 71 return; 72 } 73 74 if (Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) { 75 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"); 76 return; 77 } 78 79 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength); 80 if (!pLeader->PLength) { 81 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0"); 82 atomic_dec(&psIntfAdapter->uNumRcbUsed); 83 return; 84 } 85 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); 86 if (MAX_CNTL_PKT_SIZE < pLeader->PLength) { 87 if (netif_msg_rx_err(Adapter)) 88 pr_info(PFX "%s: corrupted leader length...%d\n", 89 Adapter->dev->name, pLeader->PLength); 90 ++Adapter->dev->stats.rx_dropped; 91 atomic_dec(&psIntfAdapter->uNumRcbUsed); 92 return; 93 } 94 95 QueueIndex = SearchVcid(Adapter, pLeader->Vcid); 96 if (QueueIndex < NO_OF_QUEUES) { 97 bHeaderSupressionEnabled = 98 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; 99 bHeaderSupressionEnabled = 100 bHeaderSupressionEnabled & Adapter->bPHSEnabled; 101 } 102 103 skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER); 104 if (!skb) { 105 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet"); 106 atomic_dec(&psIntfAdapter->uNumRcbUsed); 107 return; 108 } 109 /* If it is a control Packet, then call handle_bcm_packet ()*/ 110 if ((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) || 111 (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) { 112 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt..."); 113 *(PUSHORT)skb->data = pLeader->Status; 114 memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + 115 (sizeof(struct bcm_leader)), pLeader->PLength); 116 skb->len = pLeader->PLength + sizeof(USHORT); 117 118 spin_lock(&Adapter->control_queue_lock); 119 ENQUEUEPACKET(Adapter->RxControlHead, Adapter->RxControlTail, skb); 120 spin_unlock(&Adapter->control_queue_lock); 121 122 atomic_inc(&Adapter->cntrlpktCnt); 123 wake_up(&Adapter->process_rx_cntrlpkt); 124 } else { 125 /* 126 * Data Packet, Format a proper Ethernet Header 127 * and give it to the stack 128 */ 129 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt..."); 130 skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); 131 memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_leader), pLeader->PLength); 132 skb->dev = Adapter->dev; 133 134 /* currently skb->len has extra ETH_HLEN bytes in the beginning */ 135 skb_put(skb, pLeader->PLength + ETH_HLEN); 136 Adapter->PackInfo[QueueIndex].uiTotalRxBytes += pLeader->PLength; 137 Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes += pLeader->PLength; 138 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength); 139 140 if (netif_running(Adapter->dev)) { 141 /* Moving ahead by ETH_HLEN to the data ptr as received from FW */ 142 skb_pull(skb, ETH_HLEN); 143 PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len, 144 NULL, bHeaderSupressionEnabled); 145 146 if (!Adapter->PackInfo[QueueIndex].bEthCSSupport) { 147 skb_push(skb, ETH_HLEN); 148 149 memcpy(skb->data, skb->dev->dev_addr, 6); 150 memcpy(skb->data+6, skb->dev->dev_addr, 6); 151 (*(skb->data+11))++; 152 *(skb->data+12) = 0x08; 153 *(skb->data+13) = 0x00; 154 pLeader->PLength += ETH_HLEN; 155 } 156 157 skb->protocol = eth_type_trans(skb, Adapter->dev); 158 process_done = netif_rx(skb); 159 } else { 160 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB..."); 161 dev_kfree_skb(skb); 162 } 163 164 ++Adapter->dev->stats.rx_packets; 165 Adapter->dev->stats.rx_bytes += pLeader->PLength; 166 167 for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) { 168 if ((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && 169 (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) 170 Adapter->aRxPktSizeHist[uiIndex]++; 171 } 172 } 173 Adapter->PrevNumRecvDescs++; 174 pRcb->bUsed = false; 175 atomic_dec(&psIntfAdapter->uNumRcbUsed); 176} 177 178static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_rcb *pRcb) 179{ 180 struct urb *urb = pRcb->urb; 181 int retval = 0; 182 183 usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr), 184 urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback, pRcb); 185 if (false == psIntfAdapter->psAdapter->device_removed && 186 false == psIntfAdapter->psAdapter->bEndPointHalted && 187 false == psIntfAdapter->bSuspended && 188 false == psIntfAdapter->bPreparingForBusSuspend) { 189 retval = usb_submit_urb(urb, GFP_ATOMIC); 190 if (retval) { 191 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval); 192 /* if this return value is because of pipe halt. need to clear this. */ 193 if (retval == -EPIPE) { 194 psIntfAdapter->psAdapter->bEndPointHalted = TRUE; 195 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); 196 } 197 198 } 199 } 200 return retval; 201} 202 203/* 204Function: InterfaceRx 205 206Description: This is the hardware specific Function for Receiving 207 data packet/control packets from the device. 208 209Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context 210 211 212 213Return: TRUE - If Rx was successful. 214 Other - If an error occurred. 215*/ 216 217bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter) 218{ 219 USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed); 220 struct bcm_usb_rcb *pRcb = NULL; 221 222 while (RxDescCount) { 223 pRcb = GetBulkInRcb(psIntfAdapter); 224 if (pRcb == NULL) { 225 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer"); 226 return false; 227 } 228 ReceiveRcb(psIntfAdapter, pRcb); 229 RxDescCount--; 230 } 231 return TRUE; 232} 233