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