Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
InterfaceRx.c
Go to the documentation of this file.
1 #include "headers.h"
2 
3 static 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 
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 
37 /*this is receive call back - when pkt available for receive (BULK IN- end point)*/
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  struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
49  struct bcm_leader *pLeader = urb->transfer_buffer;
50 
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);
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  {
98  if (netif_msg_rx_err(Adapter))
99  pr_info(PFX "%s: corrupted leader length...%d\n",
100  Adapter->dev->name, pLeader->PLength);
101  ++Adapter->dev->stats.rx_dropped;
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  {
126  BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt...");
127  *(PUSHORT)skb->data = pLeader->Status;
128  memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
129  (sizeof(struct bcm_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  */
145  BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt...");
146  skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
147  memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(struct bcm_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;
154  BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength);
155 
156  if(netif_running(Adapter->dev))
157  {
158  /* Moving ahead by ETH_HLEN to the data ptr as received from FW */
159  skb_pull(skb, ETH_HLEN);
160  PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
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...");
181  dev_kfree_skb(skb);
182  }
183 
184  ++Adapter->dev->stats.rx_packets;
185  Adapter->dev->stats.rx_bytes += pLeader->PLength;
186 
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 
232 Description: This is the hardware specific Function for Receiving
233  data packet/control packets from the device.
234 
235 Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
236 
237 
238 
239 Return: TRUE - If Rx was successful.
240  Other - If an error occurred.
241 */
242 
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