blob: 0f179b9382d3a0df62728acc082c9a15e876221b [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001#include "headers.h"
Stephen Hemmingercacd9222010-11-01 13:34:35 -04002
Matthias Beyerc6346fa2014-06-30 10:10:02 +02003static void handle_control_packet(struct bcm_interface_adapter *interface,
4 struct bcm_mini_adapter *ad,
5 struct bcm_leader *leader,
6 struct sk_buff *skb,
7 struct urb *urb)
8{
9 BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL,
10 "Received control pkt...");
11 *(PUSHORT)skb->data = leader->Status;
12 memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
13 (sizeof(struct bcm_leader)), leader->PLength);
14 skb->len = leader->PLength + sizeof(USHORT);
15
16 spin_lock(&ad->control_queue_lock);
17 ENQUEUEPACKET(ad->RxControlHead, ad->RxControlTail, skb);
18 spin_unlock(&ad->control_queue_lock);
19
20 atomic_inc(&ad->cntrlpktCnt);
21 wake_up(&ad->process_rx_cntrlpkt);
22}
23
Matthias Beyer3a162b12014-06-30 10:10:03 +020024static void format_eth_hdr_to_stack(struct bcm_interface_adapter *interface,
25 struct bcm_mini_adapter *ad,
26 struct bcm_leader *p_leader,
27 struct sk_buff *skb,
28 struct urb *urb,
29 UINT ui_index,
30 int queue_index,
Matthias Beyer8139b8d2014-06-30 10:10:04 +020031 bool b_header_supression_endabled)
Matthias Beyer3a162b12014-06-30 10:10:03 +020032{
33 /*
34 * Data Packet, Format a proper Ethernet Header
35 * and give it to the stack
36 */
37 BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
38 DBG_LVL_ALL, "Received Data pkt...");
39 skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
40 memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer +
41 sizeof(struct bcm_leader), p_leader->PLength);
42 skb->dev = ad->dev;
43
44 /* currently skb->len has extra ETH_HLEN bytes in the beginning */
45 skb_put(skb, p_leader->PLength + ETH_HLEN);
46 ad->PackInfo[queue_index].uiTotalRxBytes += p_leader->PLength;
47 ad->PackInfo[queue_index].uiThisPeriodRxBytes += p_leader->PLength;
48 BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
49 DBG_LVL_ALL, "Received Data pkt of len :0x%X",
50 p_leader->PLength);
51
52 if (netif_running(ad->dev)) {
53 /* Moving ahead by ETH_HLEN to the data ptr as received from FW */
54 skb_pull(skb, ETH_HLEN);
55 PHSReceive(ad, p_leader->Vcid, skb, &skb->len,
56 NULL, b_header_supression_endabled);
57
58 if (!ad->PackInfo[queue_index].bEthCSSupport) {
59 skb_push(skb, ETH_HLEN);
60
61 memcpy(skb->data, skb->dev->dev_addr, 6);
62 memcpy(skb->data+6, skb->dev->dev_addr, 6);
63 (*(skb->data+11))++;
64 *(skb->data+12) = 0x08;
65 *(skb->data+13) = 0x00;
66 p_leader->PLength += ETH_HLEN;
67 }
68
69 skb->protocol = eth_type_trans(skb, ad->dev);
Matthias Beyer8139b8d2014-06-30 10:10:04 +020070 netif_rx(skb);
Matthias Beyer3a162b12014-06-30 10:10:03 +020071 } else {
72 BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX,
73 RX_DATA, DBG_LVL_ALL,
74 "i/f not up hance freeing SKB...");
75 dev_kfree_skb(skb);
76 }
77
78 ++ad->dev->stats.rx_packets;
79 ad->dev->stats.rx_bytes += p_leader->PLength;
80
81 for (ui_index = 0; ui_index < MIBS_MAX_HIST_ENTRIES; ui_index++) {
82 if ((p_leader->PLength <=
83 MIBS_PKTSIZEHIST_RANGE*(ui_index+1)) &&
84 (p_leader->PLength > MIBS_PKTSIZEHIST_RANGE*(ui_index)))
85
86 ad->aRxPktSizeHist[ui_index]++;
87 }
88}
89
Matthias Oefeleind38eca92014-01-08 23:15:06 +010090static int SearchVcid(struct bcm_mini_adapter *Adapter, unsigned short usVcid)
Stephen Hemmingercacd9222010-11-01 13:34:35 -040091{
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +010092 int iIndex = 0;
Stephen Hemmingercacd9222010-11-01 13:34:35 -040093
Matthias Oefelein7d774a52014-01-08 23:15:08 +010094 for (iIndex = (NO_OF_QUEUES-1); iIndex >= 0; iIndex--)
95 if (Adapter->PackInfo[iIndex].usVCID_Value == usVcid)
Stephen Hemmingercacd9222010-11-01 13:34:35 -040096 return iIndex;
97 return NO_OF_QUEUES+1;
98
99}
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700100
101
Kevin McKinney71dd0922012-11-01 23:42:22 -0400102static struct bcm_usb_rcb *
Kevin McKinneyd6861cf2012-11-01 23:42:21 -0400103GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700104{
Kevin McKinney71dd0922012-11-01 23:42:22 -0400105 struct bcm_usb_rcb *pRcb = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700106 UINT index = 0;
107
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100108 if ((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100109 (psIntfAdapter->psAdapter->StopAllXaction == false)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700110 index = atomic_read(&psIntfAdapter->uCurrRcb);
111 pRcb = &psIntfAdapter->asUsbRcb[index];
112 pRcb->bUsed = TRUE;
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100113 pRcb->psIntfAdapter = psIntfAdapter;
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200114 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX, RX_DPC,
115 DBG_LVL_ALL, "Got Rx desc %d used %d", index,
116 atomic_read(&psIntfAdapter->uNumRcbUsed));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700117 index = (index + 1) % MAXIMUM_USB_RCB;
118 atomic_set(&psIntfAdapter->uCurrRcb, index);
119 atomic_inc(&psIntfAdapter->uNumRcbUsed);
120 }
121 return pRcb;
122}
123
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300124/*this is receive call back - when pkt available for receive (BULK IN- end point)*/
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700125static void read_bulk_callback(struct urb *urb)
126{
127 struct sk_buff *skb = NULL;
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700128 bool bHeaderSupressionEnabled = false;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700129 int QueueIndex = NO_OF_QUEUES + 1;
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100130 UINT uiIndex = 0;
Kevin McKinney71dd0922012-11-01 23:42:22 -0400131 struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context;
Kevin McKinneyd6861cf2012-11-01 23:42:21 -0400132 struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter;
Kevin McKinney29794602012-05-26 12:05:12 -0400133 struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
Kevin McKinneyff352042012-05-26 12:05:11 -0400134 struct bcm_leader *pLeader = urb->transfer_buffer;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700135
Stephen Hemminger9ec44752010-11-01 12:18:36 -0400136 if (unlikely(netif_msg_rx_status(Adapter)))
137 pr_info(PFX "%s: rx urb status %d length %d\n",
138 Adapter->dev->name, urb->status, urb->actual_length);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700139
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100140 if ((Adapter->device_removed == TRUE) ||
141 (TRUE == Adapter->bEndPointHalted) ||
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100142 (0 == urb->actual_length)) {
Matthias Oefelein26ac5b42014-01-08 23:15:07 +0100143 pRcb->bUsed = false;
144 atomic_dec(&psIntfAdapter->uNumRcbUsed);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700145 return;
146 }
147
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100148 if (urb->status != STATUS_SUCCESS) {
149 if (urb->status == -EPIPE) {
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100150 Adapter->bEndPointHalted = TRUE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700151 wake_up(&Adapter->tx_packet_wait_queue);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100152 } else {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200153 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC,
154 DBG_LVL_ALL,
155 "Rx URB has got cancelled. status :%d",
156 urb->status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700157 }
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700158 pRcb->bUsed = false;
Matthias Oefelein26ac5b42014-01-08 23:15:07 +0100159 atomic_dec(&psIntfAdapter->uNumRcbUsed);
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100160 urb->status = STATUS_SUCCESS;
161 return;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700162 }
163
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100164 if (Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200165 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
166 "device is going in low power mode while PMU option selected..hence rx packet should not be process");
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100167 return;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700168 }
169
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200170 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
171 "Read back done len %d\n", pLeader->PLength);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100172 if (!pLeader->PLength) {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200173 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
174 "Leader Length 0");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700175 atomic_dec(&psIntfAdapter->uNumRcbUsed);
176 return;
177 }
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200178 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,
179 "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX",
180 pLeader->Status, pLeader->PLength, pLeader->Vcid);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100181 if (MAX_CNTL_PKT_SIZE < pLeader->PLength) {
Stephen Hemminger9ec44752010-11-01 12:18:36 -0400182 if (netif_msg_rx_err(Adapter))
183 pr_info(PFX "%s: corrupted leader length...%d\n",
184 Adapter->dev->name, pLeader->PLength);
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400185 ++Adapter->dev->stats.rx_dropped;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700186 atomic_dec(&psIntfAdapter->uNumRcbUsed);
187 return;
188 }
189
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100190 QueueIndex = SearchVcid(Adapter, pLeader->Vcid);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100191 if (QueueIndex < NO_OF_QUEUES) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700192 bHeaderSupressionEnabled =
193 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
194 bHeaderSupressionEnabled =
195 bHeaderSupressionEnabled & Adapter->bPHSEnabled;
196 }
197
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200198 skb = dev_alloc_skb(pLeader->PLength + SKB_RESERVE_PHS_BYTES +
199 SKB_RESERVE_ETHERNET_HEADER);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100200 if (!skb) {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200201 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
202 "NO SKBUFF!!! Dropping the Packet");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700203 atomic_dec(&psIntfAdapter->uNumRcbUsed);
204 return;
205 }
Matthias Oefelein26ac5b42014-01-08 23:15:07 +0100206 /* If it is a control Packet, then call handle_bcm_packet ()*/
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100207 if ((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100208 (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) {
Matthias Beyerc6346fa2014-06-30 10:10:02 +0200209 handle_control_packet(psIntfAdapter, Adapter, pLeader, skb,
210 urb);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100211 } else {
Matthias Beyer3a162b12014-06-30 10:10:03 +0200212 format_eth_hdr_to_stack(psIntfAdapter, Adapter, pLeader, skb,
213 urb, uiIndex, QueueIndex,
Matthias Beyer8139b8d2014-06-30 10:10:04 +0200214 bHeaderSupressionEnabled);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700215 }
Matthias Oefelein26ac5b42014-01-08 23:15:07 +0100216 Adapter->PrevNumRecvDescs++;
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700217 pRcb->bUsed = false;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700218 atomic_dec(&psIntfAdapter->uNumRcbUsed);
219}
220
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200221static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter,
222 struct bcm_usb_rcb *pRcb)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700223{
224 struct urb *urb = pRcb->urb;
225 int retval = 0;
226
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200227 usb_fill_bulk_urb(urb, psIntfAdapter->udev,
228 usb_rcvbulkpipe(psIntfAdapter->udev,
229 psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
230 urb->transfer_buffer,
231 BCM_USB_MAX_READ_LENGTH,
232 read_bulk_callback, pRcb);
233
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100234 if (false == psIntfAdapter->psAdapter->device_removed &&
235 false == psIntfAdapter->psAdapter->bEndPointHalted &&
236 false == psIntfAdapter->bSuspended &&
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100237 false == psIntfAdapter->bPreparingForBusSuspend) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700238 retval = usb_submit_urb(urb, GFP_ATOMIC);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100239 if (retval) {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200240 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_RX,
241 RX_DPC, DBG_LVL_ALL,
242 "failed submitting read urb, error %d",
243 retval);
Matthias Oefelein69cb4a82014-01-08 23:15:10 +0100244 /* if this return value is because of pipe halt. need to clear this. */
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100245 if (retval == -EPIPE) {
Matthias Oefelein1b42f1d2014-01-08 23:15:05 +0100246 psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700247 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
248 }
249
250 }
251 }
252 return retval;
253}
254
255/*
256Function: InterfaceRx
257
Joe Perchesceeb6fe2011-06-23 11:40:18 -0700258Description: This is the hardware specific Function for Receiving
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700259 data packet/control packets from the device.
260
Kevin McKinney29794602012-05-26 12:05:12 -0400261Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700262
263
264
265Return: TRUE - If Rx was successful.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300266 Other - If an error occurred.
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700267*/
268
Matthias Oefelein7d774a52014-01-08 23:15:08 +0100269bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700270{
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200271 USHORT RxDescCount = NUM_RX_DESC -
272 atomic_read(&psIntfAdapter->uNumRcbUsed);
273
Kevin McKinney71dd0922012-11-01 23:42:22 -0400274 struct bcm_usb_rcb *pRcb = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700275
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100276 while (RxDescCount) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700277 pRcb = GetBulkInRcb(psIntfAdapter);
Matthias Oefeleinb0303a82014-01-08 23:15:09 +0100278 if (pRcb == NULL) {
Matthias Beyerf5c86ab2014-06-30 10:10:01 +0200279 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
280 DBG_TYPE_PRINTK, 0, 0,
281 "Unable to get Rcb pointer");
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700282 return false;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700283 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700284 ReceiveRcb(psIntfAdapter, pRcb);
285 RxDescCount--;
Matthias Oefelein26ac5b42014-01-08 23:15:07 +0100286 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700287 return TRUE;
288}
289