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