Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / os_dep / usb_ops_linux.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _USB_OPS_LINUX_C_
16
17 #include <drv_types.h>
18 #include <usb_ops_linux.h>
19 #include <rtw_sreset.h>
20
21 void rtl8723au_read_port_cancel(struct rtw_adapter *padapter)
22 {
23         struct recv_buf *precvbuf;
24         int i;
25
26         precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
27
28         DBG_8723A("%s\n", __func__);
29
30         padapter->bReadPortCancel = true;
31
32         for (i = 0; i < NR_RECVBUFF ; i++) {
33                 if (precvbuf->purb)
34                         usb_kill_urb(precvbuf->purb);
35                 precvbuf++;
36         }
37         usb_kill_urb(padapter->recvpriv.int_in_urb);
38 }
39
40 static void usb_write_port23a_complete(struct urb *purb)
41 {
42         struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
43         struct rtw_adapter *padapter = pxmitbuf->padapter;
44         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
45         struct hal_data_8723a *phaldata;
46         unsigned long irqL;
47
48         switch (pxmitbuf->flags) {
49         case HIGH_QUEUE_INX:
50 #ifdef CONFIG_8723AU_AP_MODE
51                 rtw_chk_hi_queue_cmd23a(padapter);
52 #endif
53                 break;
54         default:
55                 break;
56         }
57
58         if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
59             padapter->bWritePortCancel) {
60                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
61                          "usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
62                          padapter->bDriverStopped, padapter->bSurpriseRemoved);
63                 DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR "
64                           "bSurpriseRemoved(%d) bWritePortCancel(%d) "
65                           "pxmitbuf->ext_tag(%x)\n", __func__,
66                           padapter->bDriverStopped, padapter->bSurpriseRemoved,
67                           padapter->bReadPortCancel, pxmitbuf->ext_tag);
68
69                 goto check_completion;
70         }
71
72         if (purb->status) {
73                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
74                          "usb_write_port23a_complete : purb->status(%d) != 0\n",
75                          purb->status);
76                 DBG_8723A("###=> urb_write_port_complete status(%d)\n",
77                           purb->status);
78                 if (purb->status == -EPIPE || purb->status == -EPROTO) {
79                 } else if (purb->status == -EINPROGRESS) {
80                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
81                                  "usb_write_port23a_complete: EINPROGESS\n");
82                         goto check_completion;
83                 } else if (purb->status == -ENOENT) {
84                         DBG_8723A("%s: -ENOENT\n", __func__);
85                         goto check_completion;
86                 } else if (purb->status == -ECONNRESET) {
87                         DBG_8723A("%s: -ECONNRESET\n", __func__);
88                         goto check_completion;
89                 } else if (purb->status == -ESHUTDOWN) {
90                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
91                                  "usb_write_port23a_complete: ESHUTDOWN\n");
92                         padapter->bDriverStopped = true;
93                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
94                                  "usb_write_port23a_complete:bDriverStopped = true\n");
95                         goto check_completion;
96                 } else {
97                         padapter->bSurpriseRemoved = true;
98                         DBG_8723A("bSurpriseRemoved = true\n");
99                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
100                                  "usb_write_port23a_complete:bSurpriseRemoved = true\n");
101                         goto check_completion;
102                 }
103         }
104         phaldata = GET_HAL_DATA(padapter);
105         phaldata->srestpriv.last_tx_complete_time = jiffies;
106
107 check_completion:
108         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
109         rtw23a_sctx_done_err(&pxmitbuf->sctx,
110                              purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
111                              RTW_SCTX_DONE_SUCCESS);
112         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
113
114         rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
115
116         tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
117 }
118
119 int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt,
120                          struct xmit_buf *pxmitbuf)
121 {
122         struct urb *purb = NULL;
123         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
124         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
125         struct xmit_frame *pxmitframe;
126         struct usb_device *pusbd = pdvobj->pusbdev;
127         unsigned long irqL;
128         unsigned int pipe, ep_num;
129         int status;
130         int ret = _FAIL;
131
132         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "+usb_write_port23a\n");
133
134         if (padapter->bDriverStopped || padapter->bSurpriseRemoved) {
135                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
136                          "%s:(padapter->bDriverStopped || padapter->bSurpriseRemoved)!!!\n",
137                          __func__);
138                 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
139                 goto exit;
140         }
141
142         pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
143         spin_lock_irqsave(&pxmitpriv->lock, irqL);
144
145         switch (addr) {
146         case VO_QUEUE_INX:
147                 pxmitbuf->flags = VO_QUEUE_INX;
148                 break;
149         case VI_QUEUE_INX:
150                 pxmitbuf->flags = VI_QUEUE_INX;
151                 break;
152         case BE_QUEUE_INX:
153                 pxmitbuf->flags = BE_QUEUE_INX;
154                 break;
155         case BK_QUEUE_INX:
156                 pxmitbuf->flags = BK_QUEUE_INX;
157                 break;
158         case HIGH_QUEUE_INX:
159                 pxmitbuf->flags = HIGH_QUEUE_INX;
160                 break;
161         default:
162                 pxmitbuf->flags = MGT_QUEUE_INX;
163                 break;
164         }
165
166         spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
167
168         purb = pxmitbuf->pxmit_urb[0];
169
170         /* translate DMA FIFO addr to pipehandle */
171         ep_num = pdvobj->Queue2Pipe[addr];
172         pipe = usb_sndbulkpipe(pusbd, ep_num);
173
174         usb_fill_bulk_urb(purb, pusbd, pipe,
175                           pxmitframe->buf_addr, /*  pxmitbuf->pbuf */
176                           cnt, usb_write_port23a_complete,
177                           pxmitbuf);/* context is pxmitbuf */
178
179         status = usb_submit_urb(purb, GFP_ATOMIC);
180         if (!status) {
181                 struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter);
182                 phaldata->srestpriv.last_tx_time = jiffies;
183         } else {
184                 rtw23a_sctx_done_err(&pxmitbuf->sctx,
185                                      RTW_SCTX_DONE_WRITE_PORT_ERR);
186                 DBG_8723A("usb_write_port23a, status =%d\n", status);
187                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
188                          "usb_write_port23a(): usb_submit_urb, status =%x\n",
189                          status);
190
191                 switch (status) {
192                 case -ENODEV:
193                         padapter->bDriverStopped = true;
194                         break;
195                 default:
196                         break;
197                 }
198                 goto exit;
199         }
200         ret = _SUCCESS;
201         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "-usb_write_port23a\n");
202
203 exit:
204         if (ret != _SUCCESS)
205                 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
206
207         return ret;
208 }
209
210 void rtl8723au_write_port_cancel(struct rtw_adapter *padapter)
211 {
212         struct xmit_buf *pxmitbuf;
213         struct list_head *plist;
214         int j;
215
216         DBG_8723A("%s\n", __func__);
217
218         padapter->bWritePortCancel = true;
219
220         list_for_each(plist, &padapter->xmitpriv.xmitbuf_list) {
221                 pxmitbuf = container_of(plist, struct xmit_buf, list2);
222                 for (j = 0; j < 8; j++) {
223                         if (pxmitbuf->pxmit_urb[j])
224                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
225                 }
226         }
227         list_for_each(plist, &padapter->xmitpriv.xmitextbuf_list) {
228                 pxmitbuf = container_of(plist, struct xmit_buf, list2);
229                 for (j = 0; j < 8; j++) {
230                         if (pxmitbuf->pxmit_urb[j])
231                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
232                 }
233         }
234 }