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