Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / drivers / staging / rtl8188eu / os_dep / usb_ops_linux.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _USB_OPS_LINUX_C_
8
9 #include <drv_types.h>
10 #include <recv_osdep.h>
11 #include <rtw_sreset.h>
12
13 static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
14 {
15         struct hal_data_8188e *haldata = adapt->HalData;
16
17         if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
18                 DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
19                 return;
20         }
21
22         /*  HISR */
23         memcpy(&haldata->IntArray[0], &pbuf[USB_INTR_CONTENT_HISR_OFFSET], 4);
24         memcpy(&haldata->IntArray[1], &pbuf[USB_INTR_CONTENT_HISRE_OFFSET], 4);
25
26         /*  C2H Event */
27         if (pbuf[0] != 0)
28                 memcpy(&haldata->C2hArray[0],
29                        &pbuf[USB_INTR_CONTENT_C2H_OFFSET], 16);
30 }
31
32 static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
33 {
34         u8 *pbuf;
35         u8 shift_sz = 0;
36         u16 pkt_cnt;
37         u32 pkt_offset, skb_len, alloc_sz;
38         s32 transfer_len;
39         struct recv_stat *prxstat;
40         struct phy_stat *pphy_status = NULL;
41         struct sk_buff *pkt_copy = NULL;
42         struct recv_frame *precvframe = NULL;
43         struct rx_pkt_attrib *pattrib = NULL;
44         struct hal_data_8188e *haldata = adapt->HalData;
45         struct recv_priv *precvpriv = &adapt->recvpriv;
46         struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
47
48         transfer_len = (s32)pskb->len;
49         pbuf = pskb->data;
50
51         prxstat = (struct recv_stat *)pbuf;
52         pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
53
54         do {
55                 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
56                          ("%s: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
57                           __func__, prxstat->rxdw0, prxstat->rxdw1,
58                           prxstat->rxdw2, prxstat->rxdw4));
59
60                 prxstat = (struct recv_stat *)pbuf;
61
62                 precvframe = rtw_alloc_recvframe(pfree_recv_queue);
63                 if (!precvframe) {
64                         RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
65                                  ("%s: precvframe==NULL\n", __func__));
66                         DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
67                         goto _exit_recvbuf2recvframe;
68                 }
69
70                 INIT_LIST_HEAD(&precvframe->list);
71
72                 update_recvframe_attrib_88e(precvframe, prxstat);
73
74                 pattrib = &precvframe->attrib;
75
76                 if ((pattrib->crc_err) || (pattrib->icv_err)) {
77                         DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
78
79                         rtw_free_recvframe(precvframe, pfree_recv_queue);
80                         goto _exit_recvbuf2recvframe;
81                 }
82
83                 if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
84                         pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
85
86                 pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
87
88                 if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
89                         RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
90                                  ("%s: pkt_len<=0\n", __func__));
91                         DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len\n", __func__, __LINE__);
92                         rtw_free_recvframe(precvframe, pfree_recv_queue);
93                         goto _exit_recvbuf2recvframe;
94                 }
95
96                 /*      Modified by Albert 20101213 */
97                 /*      For 8 bytes IP header alignment. */
98                 if (pattrib->qos)       /*      Qos data, wireless lan header length is 26 */
99                         shift_sz = 6;
100                 else
101                         shift_sz = 0;
102
103                 skb_len = pattrib->pkt_len;
104
105                 /*  for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
106                 /*  modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
107                 if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
108                         if (skb_len <= 1650)
109                                 alloc_sz = 1664;
110                         else
111                                 alloc_sz = skb_len + 14;
112                 } else {
113                         alloc_sz = skb_len;
114                         /*      6 is for IP header 8 bytes alignment in QoS packet case. */
115                         /*      8 is for skb->data 4 bytes alignment. */
116                         alloc_sz += 14;
117                 }
118
119                 pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
120                 if (pkt_copy) {
121                         pkt_copy->dev = adapt->pnetdev;
122                         precvframe->pkt = pkt_copy;
123                         skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
124                         skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
125                         skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
126                 } else {
127                         DBG_88E("%s: alloc_skb fail , drop frag frame\n",
128                                 __func__);
129                         rtw_free_recvframe(precvframe, pfree_recv_queue);
130                         goto _exit_recvbuf2recvframe;
131                 }
132
133                 switch (haldata->UsbRxAggMode) {
134                 case USB_RX_AGG_DMA:
135                 case USB_RX_AGG_MIX:
136                         pkt_offset = (u16)round_up(pkt_offset, 128);
137                         break;
138                 case USB_RX_AGG_USB:
139                         pkt_offset = (u16)round_up(pkt_offset, 4);
140                         break;
141                 case USB_RX_AGG_DISABLE:
142                 default:
143                         break;
144                 }
145                 if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
146                         if (pattrib->physt)
147                                 update_recvframe_phyinfo_88e(precvframe, pphy_status);
148                         if (rtw_recv_entry(precvframe) != _SUCCESS) {
149                                 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
150                                          ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",
151                                          __func__));
152                         }
153                 } else if (pattrib->pkt_rpt_type == TX_REPORT1) {
154                         /* CCX-TXRPT ack for xmit mgmt frames. */
155                         handle_txrpt_ccx_88e(adapt, precvframe->pkt->data);
156                         rtw_free_recvframe(precvframe, pfree_recv_queue);
157                 } else if (pattrib->pkt_rpt_type == TX_REPORT2) {
158                         ODM_RA_TxRPT2Handle_8188E(&haldata->odmpriv,
159                                                   precvframe->pkt->data,
160                                                   pattrib->pkt_len,
161                                                   pattrib->MacIDValidEntry[0],
162                                                   pattrib->MacIDValidEntry[1]);
163                         rtw_free_recvframe(precvframe, pfree_recv_queue);
164                 } else if (pattrib->pkt_rpt_type == HIS_REPORT) {
165                         interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->pkt->data);
166                         rtw_free_recvframe(precvframe, pfree_recv_queue);
167                 }
168                 pkt_cnt--;
169                 transfer_len -= pkt_offset;
170                 pbuf += pkt_offset;
171                 precvframe = NULL;
172                 pkt_copy = NULL;
173
174                 if (transfer_len > 0 && pkt_cnt == 0)
175                         pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
176
177         } while ((transfer_len > 0) && (pkt_cnt > 0));
178
179 _exit_recvbuf2recvframe:
180
181         return _SUCCESS;
182 }
183
184 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
185 {
186         unsigned int pipe = 0, ep_num = 0;
187         struct usb_device *pusbd = pdvobj->pusbdev;
188
189         if (addr == RECV_BULK_IN_ADDR) {
190                 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
191         } else if (addr == RECV_INT_IN_ADDR) {
192                 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
193         } else if (addr < HW_QUEUE_ENTRY) {
194                 ep_num = pdvobj->Queue2Pipe[addr];
195                 pipe = usb_sndbulkpipe(pusbd, ep_num);
196         }
197
198         return pipe;
199 }
200
201 static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
202 {
203         struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
204         struct usb_device *udev = dvobjpriv->pusbdev;
205         unsigned int pipe;
206         int status = 0;
207         u8 reqtype;
208         u8 *pIo_buf;
209         int vendorreq_times = 0;
210
211         if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
212                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
213                          ("%s:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
214                           __func__));
215                 status = -EPERM;
216                 goto exit;
217         }
218
219         if (len > MAX_VENDOR_REQ_CMD_SIZE) {
220                 DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
221                 status = -EINVAL;
222                 goto exit;
223         }
224
225         if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex)) {
226                 status = -ERESTARTSYS;
227                 goto exit;
228         }
229
230         /*  Acquire IO memory for vendorreq */
231         pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC);
232
233         if (!pIo_buf) {
234                 status = -ENOMEM;
235                 goto release_mutex;
236         }
237
238         while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
239                 memset(pIo_buf, 0, len);
240
241                 if (requesttype == 0x01) {
242                         pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
243                         reqtype =  REALTEK_USB_VENQT_READ;
244                 } else {
245                         pipe = usb_sndctrlpipe(udev, 0);/* write_out */
246                         reqtype =  REALTEK_USB_VENQT_WRITE;
247                         memcpy(pIo_buf, pdata, len);
248                 }
249
250                 status = usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
251
252                 if (status == len) {   /*  Success this control transfer. */
253                         if (requesttype == 0x01)
254                                 memcpy(pdata, pIo_buf,  len);
255                 } else { /*  error cases */
256                         DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
257                                 value, (requesttype == 0x01) ? "read" : "write",
258                                 len, status, *(u32 *)pdata, vendorreq_times);
259
260                         if (status < 0) {
261                                 if (status == (-ESHUTDOWN) || status == -ENODEV)
262                                         adapt->bSurpriseRemoved = true;
263                                 else
264                                         adapt->HalData->srestpriv.wifi_error_status = USB_VEN_REQ_CMD_FAIL;
265                         } else { /*  status != len && status >= 0 */
266                                 if (status > 0) {
267                                         if (requesttype == 0x01) {
268                                                 /*  For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
269                                                 memcpy(pdata, pIo_buf,  len);
270                                         }
271                                 }
272                         }
273                 }
274
275                 /*  firmware download is checksummed, don't retry */
276                 if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
277                         break;
278         }
279         kfree(pIo_buf);
280
281 release_mutex:
282         mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
283 exit:
284         return status;
285 }
286
287 u8 usb_read8(struct adapter *adapter, u32 addr)
288 {
289         u8 request;
290         u8 requesttype;
291         u16 wvalue;
292         u16 index;
293         u16 len;
294         u8 data = 0;
295
296         request = 0x05;
297         requesttype = 0x01;/* read_in */
298         index = 0;/* n/a */
299
300         wvalue = (u16)(addr & 0x0000ffff);
301         len = 1;
302
303         usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
304
305         return data;
306 }
307
308 u16 usb_read16(struct adapter *adapter, u32 addr)
309 {
310         u8 request;
311         u8 requesttype;
312         u16 wvalue;
313         u16 index;
314         u16 len;
315         __le32 data;
316
317         request = 0x05;
318         requesttype = 0x01;/* read_in */
319         index = 0;/* n/a */
320         wvalue = (u16)(addr & 0x0000ffff);
321         len = 2;
322         usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
323
324         return (u16)(le32_to_cpu(data) & 0xffff);
325 }
326
327 u32 usb_read32(struct adapter *adapter, u32 addr)
328 {
329         u8 request;
330         u8 requesttype;
331         u16 wvalue;
332         u16 index;
333         u16 len;
334         __le32 data;
335
336         request = 0x05;
337         requesttype = 0x01;/* read_in */
338         index = 0;/* n/a */
339
340         wvalue = (u16)(addr & 0x0000ffff);
341         len = 4;
342
343         usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
344
345         return le32_to_cpu(data);
346 }
347
348 static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
349 {
350         struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
351         struct adapter *adapt = (struct adapter *)precvbuf->adapter;
352         struct recv_priv *precvpriv = &adapt->recvpriv;
353
354         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s!!!\n", __func__));
355
356         if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
357                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
358                          ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
359                          __func__, adapt->bDriverStopped,
360                          adapt->bSurpriseRemoved));
361
362                 precvbuf->reuse = true;
363                 DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
364                         __func__, adapt->bDriverStopped,
365                         adapt->bSurpriseRemoved, adapt->bReadPortCancel);
366                 return;
367         }
368
369         if (purb->status == 0) { /* SUCCESS */
370                 if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
371                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
372                                  ("%s: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n",
373                                  __func__));
374                         precvbuf->reuse = true;
375                         usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
376                         DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
377                 } else {
378                         skb_put(precvbuf->pskb, purb->actual_length);
379                         skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
380
381                         if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
382                                 tasklet_schedule(&precvpriv->recv_tasklet);
383
384                         precvbuf->pskb = NULL;
385                         precvbuf->reuse = false;
386                         usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
387                 }
388         } else {
389                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
390                          ("%s : purb->status(%d) != 0\n",
391                           __func__, purb->status));
392
393                 DBG_88E("###=> %s => urb status(%d)\n", __func__, purb->status);
394                 skb_put(precvbuf->pskb, purb->actual_length);
395                 precvbuf->pskb = NULL;
396
397                 switch (purb->status) {
398                 case -EINVAL:
399                 case -EPIPE:
400                 case -ENODEV:
401                 case -ESHUTDOWN:
402                         adapt->bSurpriseRemoved = true;
403                         /* fall through */
404                 case -ENOENT:
405                         adapt->bDriverStopped = true;
406                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
407                                  ("%s:bDriverStopped=true\n", __func__));
408                         break;
409                 case -EPROTO:
410                 case -EOVERFLOW:
411                         adapt->HalData->srestpriv.wifi_error_status = USB_READ_PORT_FAIL;
412                         precvbuf->reuse = true;
413                         usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
414                         break;
415                 case -EINPROGRESS:
416                         DBG_88E("ERROR: URB IS IN PROGRESS!\n");
417                         break;
418                 default:
419                         break;
420                 }
421         }
422 }
423
424 u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf)
425 {
426         struct urb *purb = NULL;
427         struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
428         struct recv_priv *precvpriv = &adapter->recvpriv;
429         struct usb_device *pusbd = pdvobj->pusbdev;
430         int err;
431         unsigned int pipe;
432         u32 ret = _SUCCESS;
433
434         if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
435             adapter->pwrctrlpriv.pnp_bstop_trx) {
436                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
437                          ("%s:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
438                           __func__));
439                 return _FAIL;
440         }
441
442         if (!precvbuf) {
443                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
444                          ("%s:precvbuf==NULL\n", __func__));
445                 return _FAIL;
446         }
447
448         if (!precvbuf->reuse || !precvbuf->pskb) {
449                 precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
450                 if (precvbuf->pskb)
451                         precvbuf->reuse = true;
452         }
453
454         /* re-assign for linux based on skb */
455         if (!precvbuf->reuse || !precvbuf->pskb) {
456                 precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ);
457                 if (!precvbuf->pskb) {
458                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
459                         DBG_88E("#### %s() alloc_skb fail!#####\n", __func__);
460                         return _FAIL;
461                 }
462         } else { /* reuse skb */
463                 precvbuf->reuse = false;
464         }
465
466         purb = precvbuf->purb;
467
468         /* translate DMA FIFO addr to pipehandle */
469         pipe = ffaddr2pipehdl(pdvobj, addr);
470
471         usb_fill_bulk_urb(purb, pusbd, pipe,
472                           precvbuf->pskb->data,
473                           MAX_RECVBUF_SZ,
474                           usb_read_port_complete,
475                           precvbuf);/* context is precvbuf */
476
477         err = usb_submit_urb(purb, GFP_ATOMIC);
478         if ((err) && (err != (-EPERM))) {
479                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
480                          ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
481                          err, purb->status));
482                 DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
483                         err, purb->status);
484                 ret = _FAIL;
485         }
486
487         return ret;
488 }
489
490 void rtw_hal_inirp_deinit(struct adapter *padapter)
491 {
492         int i;
493         struct recv_buf *precvbuf;
494
495         precvbuf = padapter->recvpriv.precv_buf;
496
497         DBG_88E("%s\n", __func__);
498
499         padapter->bReadPortCancel = true;
500
501         for (i = 0; i < NR_RECVBUFF; i++) {
502                 precvbuf->reuse = true;
503                 if (precvbuf->purb)
504                         usb_kill_urb(precvbuf->purb);
505                 precvbuf++;
506         }
507 }
508
509 int usb_write8(struct adapter *adapter, u32 addr, u8 val)
510 {
511         u8 request;
512         u8 requesttype;
513         u16 wvalue;
514         u16 index;
515         u16 len;
516         u8 data;
517
518         request = 0x05;
519         requesttype = 0x00;/* write_out */
520         index = 0;/* n/a */
521         wvalue = (u16)(addr & 0x0000ffff);
522         len = 1;
523         data = val;
524         return usbctrl_vendorreq(adapter, request, wvalue,
525                                  index, &data, len, requesttype);
526 }
527
528 int usb_write16(struct adapter *adapter, u32 addr, u16 val)
529 {
530         u8 request;
531         u8 requesttype;
532         u16 wvalue;
533         u16 index;
534         u16 len;
535         __le32 data;
536
537         request = 0x05;
538         requesttype = 0x00;/* write_out */
539         index = 0;/* n/a */
540
541         wvalue = (u16)(addr & 0x0000ffff);
542         len = 2;
543
544         data = cpu_to_le32(val & 0x0000ffff);
545
546         return usbctrl_vendorreq(adapter, request, wvalue,
547                                  index, &data, len, requesttype);
548 }
549
550 int usb_write32(struct adapter *adapter, u32 addr, u32 val)
551 {
552         u8 request;
553         u8 requesttype;
554         u16 wvalue;
555         u16 index;
556         u16 len;
557         __le32 data;
558
559         request = 0x05;
560         requesttype = 0x00;/* write_out */
561         index = 0;/* n/a */
562
563         wvalue = (u16)(addr & 0x0000ffff);
564         len = 4;
565         data = cpu_to_le32(val);
566
567         return usbctrl_vendorreq(adapter, request, wvalue,
568                                  index, &data, len, requesttype);
569 }
570
571 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
572 {
573         struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
574         struct adapter *padapter = pxmitbuf->padapter;
575         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
576
577         switch (pxmitbuf->flags) {
578         case VO_QUEUE_INX:
579                 pxmitpriv->voq_cnt--;
580                 break;
581         case VI_QUEUE_INX:
582                 pxmitpriv->viq_cnt--;
583                 break;
584         case BE_QUEUE_INX:
585                 pxmitpriv->beq_cnt--;
586                 break;
587         case BK_QUEUE_INX:
588                 pxmitpriv->bkq_cnt--;
589                 break;
590         case HIGH_QUEUE_INX:
591 #ifdef CONFIG_88EU_AP_MODE
592                 rtw_chk_hi_queue_cmd(padapter);
593 #endif
594                 break;
595         default:
596                 break;
597         }
598
599         if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
600             padapter->bWritePortCancel) {
601                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
602                          ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
603                           __func__, padapter->bDriverStopped,
604                           padapter->bSurpriseRemoved));
605                 DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
606                         __func__, padapter->bDriverStopped,
607                         padapter->bSurpriseRemoved, padapter->bReadPortCancel,
608                         pxmitbuf->ext_tag);
609
610                 goto check_completion;
611         }
612
613         if (purb->status) {
614                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
615                          ("%s : purb->status(%d) != 0\n",
616                           __func__, purb->status));
617                 DBG_88E("###=> %s status(%d)\n", __func__, purb->status);
618                 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
619                         sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
620                 } else if (purb->status == -EINPROGRESS) {
621                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
622                                  ("%s: EINPROGRESS\n", __func__));
623                         goto check_completion;
624                 } else if (purb->status == -ENOENT) {
625                         DBG_88E("%s: -ENOENT\n", __func__);
626                         goto check_completion;
627                 } else if (purb->status == -ECONNRESET) {
628                         DBG_88E("%s: -ECONNRESET\n", __func__);
629                         goto check_completion;
630                 } else if (purb->status == -ESHUTDOWN) {
631                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
632                                  ("%s: ESHUTDOWN\n", __func__));
633                         padapter->bDriverStopped = true;
634                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
635                                  ("%s:bDriverStopped = true\n", __func__));
636                         goto check_completion;
637                 } else {
638                         padapter->bSurpriseRemoved = true;
639                         DBG_88E("bSurpriseRemoved = true\n");
640                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
641                                  ("%s:bSurpriseRemoved = true\n", __func__));
642                         goto check_completion;
643                 }
644         }
645
646 check_completion:
647         rtw_sctx_done_err(&pxmitbuf->sctx,
648                           purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
649                           RTW_SCTX_DONE_SUCCESS);
650
651         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
652
653         tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
654 }
655
656 u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf *xmitbuf)
657 {
658         unsigned long irqL;
659         unsigned int pipe;
660         int status;
661         u32 ret = _FAIL;
662         struct urb *purb = NULL;
663         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
664         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
665         struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data;
666         struct usb_device *pusbd = pdvobj->pusbdev;
667
668         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+%s\n", __func__));
669
670         if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
671             (padapter->pwrctrlpriv.pnp_bstop_trx)) {
672                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
673                          ("%s:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
674                           __func__));
675                 rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
676                 goto exit;
677         }
678
679         spin_lock_irqsave(&pxmitpriv->lock, irqL);
680
681         switch (addr) {
682         case VO_QUEUE_INX:
683                 pxmitpriv->voq_cnt++;
684                 xmitbuf->flags = VO_QUEUE_INX;
685                 break;
686         case VI_QUEUE_INX:
687                 pxmitpriv->viq_cnt++;
688                 xmitbuf->flags = VI_QUEUE_INX;
689                 break;
690         case BE_QUEUE_INX:
691                 pxmitpriv->beq_cnt++;
692                 xmitbuf->flags = BE_QUEUE_INX;
693                 break;
694         case BK_QUEUE_INX:
695                 pxmitpriv->bkq_cnt++;
696                 xmitbuf->flags = BK_QUEUE_INX;
697                 break;
698         case HIGH_QUEUE_INX:
699                 xmitbuf->flags = HIGH_QUEUE_INX;
700                 break;
701         default:
702                 xmitbuf->flags = MGT_QUEUE_INX;
703                 break;
704         }
705
706         spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
707
708         purb    = xmitbuf->pxmit_urb[0];
709
710         /* translate DMA FIFO addr to pipehandle */
711         pipe = ffaddr2pipehdl(pdvobj, addr);
712
713         usb_fill_bulk_urb(purb, pusbd, pipe,
714                           pxmitframe->buf_addr, /*  xmitbuf->pbuf */
715                           cnt,
716                           usb_write_port_complete,
717                           xmitbuf);/* context is xmitbuf */
718
719         status = usb_submit_urb(purb, GFP_ATOMIC);
720         if (status) {
721                 rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
722                 DBG_88E("%s, status =%d\n", __func__, status);
723                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
724                          ("%s(): usb_submit_urb, status =%x\n",
725                           __func__, status));
726
727                 switch (status) {
728                 case -ENODEV:
729                         padapter->bDriverStopped = true;
730                         break;
731                 default:
732                         break;
733                 }
734                 goto exit;
735         }
736
737         ret = _SUCCESS;
738
739 /*    We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
740
741         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-%s\n", __func__));
742
743 exit:
744         if (ret != _SUCCESS)
745                 rtw_free_xmitbuf(pxmitpriv, xmitbuf);
746         return ret;
747 }
748
749 void usb_write_port_cancel(struct adapter *padapter)
750 {
751         int i, j;
752         struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
753
754         DBG_88E("%s\n", __func__);
755
756         padapter->bWritePortCancel = true;
757
758         for (i = 0; i < NR_XMITBUFF; i++) {
759                 for (j = 0; j < 8; j++) {
760                         if (pxmitbuf->pxmit_urb[j])
761                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
762                 }
763                 pxmitbuf++;
764         }
765
766         pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
767         for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
768                 for (j = 0; j < 8; j++) {
769                         if (pxmitbuf->pxmit_urb[j])
770                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
771                 }
772                 pxmitbuf++;
773         }
774 }
775
776 void rtl8188eu_recv_tasklet(void *priv)
777 {
778         struct sk_buff *pskb;
779         struct adapter *adapt = priv;
780         struct recv_priv *precvpriv = &adapt->recvpriv;
781
782         while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
783                 if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
784                         DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
785                         dev_kfree_skb_any(pskb);
786                         break;
787                 }
788                 recvbuf2recvframe(adapt, pskb);
789                 skb_reset_tail_pointer(pskb);
790                 pskb->len = 0;
791                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
792         }
793 }
794
795 void rtl8188eu_xmit_tasklet(void *priv)
796 {
797         struct adapter *adapt = priv;
798         struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
799
800         if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
801                 return;
802
803         while (1) {
804                 if ((adapt->bDriverStopped) ||
805                     (adapt->bSurpriseRemoved) ||
806                     (adapt->bWritePortCancel)) {
807                         DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
808                         break;
809                 }
810
811                 if (!rtl8188eu_xmitframe_complete(adapt, pxmitpriv))
812                         break;
813         }
814 }