Merge branch 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[pandora-kernel.git] / drivers / staging / bcm / InterfaceRx.c
1 #include "headers.h"
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 }
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 avilable 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         PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
49         PLEADER 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, "Recived control pkt...");
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                   */
145         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt...");
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;
154         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived 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                         PHSRecieve(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 Recieveing
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.
240                                         Other - If an error occured.
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