staging: Beeceem USB Wimax driver
[linux-block.git] / drivers / staging / bcm / InterfaceRx.c
CommitLineData
f8942e07
SH
1#include "headers.h"
2extern int SearchVcid(PMINI_ADAPTER , unsigned short);
3
4
5static PUSB_RCB
6GetBulkInRcb(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)*/
28static 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
191static 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/*
222Function: InterfaceRx
223
224Description: This is the hardware specific Function for Recieveing
225 data packet/control packets from the device.
226
227Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context
228
229
230
231Return: TRUE - If Rx was successful.
232 Other - If an error occured.
233*/
234
235BOOLEAN 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