diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceRx.c')
-rw-r--r-- | drivers/staging/bcm/InterfaceRx.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c new file mode 100644 index 00000000000..6fee9684f2e --- /dev/null +++ b/drivers/staging/bcm/InterfaceRx.c | |||
@@ -0,0 +1,256 @@ | |||
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 | |||