Commit | Line | Data |
---|---|---|
f8942e07 SH |
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 |