]>
Commit | Line | Data |
---|---|---|
f8942e07 | 1 | #include "headers.h" |
cacd9222 SH |
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 | } | |
f8942e07 SH |
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 | ||
25985edc | 37 | /*this is receive call back - when pkt available for receive (BULK IN- end point)*/ |
f8942e07 SH |
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 | ||
9ec4475b SH |
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); | |
f8942e07 SH |
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 | { | |
9ec4475b SH |
98 | if (netif_msg_rx_err(Adapter)) |
99 | pr_info(PFX "%s: corrupted leader length...%d\n", | |
100 | Adapter->dev->name, pLeader->PLength); | |
cacd9222 | 101 | ++Adapter->dev->stats.rx_dropped; |
f8942e07 SH |
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 | { | |
25985edc | 126 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt..."); |
f8942e07 SH |
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 | */ | |
25985edc | 145 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt..."); |
f8942e07 SH |
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; | |
25985edc | 154 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength); |
f8942e07 | 155 | |
2515ab62 | 156 | if(netif_running(Adapter->dev)) |
f8942e07 SH |
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..."); | |
082e889b | 181 | dev_kfree_skb(skb); |
f8942e07 | 182 | } |
cacd9222 SH |
183 | |
184 | ++Adapter->dev->stats.rx_packets; | |
185 | Adapter->dev->stats.rx_bytes += pLeader->PLength; | |
186 | ||
f8942e07 SH |
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. | |
25985edc | 240 | Other - If an error occurred. |
f8942e07 SH |
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 |