]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
arm: imx6: defconfig: update tx6 defconfigs
[karo-tx-linux.git] / drivers / staging / rtl8188eu / 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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  ******************************************************************************/
19 #define _USB_OPS_LINUX_C_
20
21 #include <drv_types.h>
22 #include <usb_ops_linux.h>
23 #include <rtw_sreset.h>
24
25 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
26 {
27         unsigned int pipe = 0, ep_num = 0;
28         struct usb_device *pusbd = pdvobj->pusbdev;
29
30         if (addr == RECV_BULK_IN_ADDR) {
31                 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
32         } else if (addr == RECV_INT_IN_ADDR) {
33                 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
34         } else if (addr < HW_QUEUE_ENTRY) {
35                 ep_num = pdvobj->Queue2Pipe[addr];
36                 pipe = usb_sndbulkpipe(pusbd, ep_num);
37         }
38
39         return pipe;
40 }
41
42 struct zero_bulkout_context {
43         void *pbuf;
44         void *purb;
45         void *pirp;
46         void *padapter;
47 };
48
49 void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
50 {
51 }
52
53 void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
54 {
55 }
56
57 void usb_read_port_cancel(struct intf_hdl *pintfhdl)
58 {
59         int i;
60         struct recv_buf *precvbuf;
61         struct adapter  *padapter = pintfhdl->padapter;
62         precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
63
64         DBG_88E("%s\n", __func__);
65
66         padapter->bReadPortCancel = true;
67
68         for (i = 0; i < NR_RECVBUFF; i++) {
69                 precvbuf->reuse = true;
70                 if (precvbuf->purb)
71                         usb_kill_urb(precvbuf->purb);
72                 precvbuf++;
73         }
74 }
75
76 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
77 {
78         struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
79         struct adapter  *padapter = pxmitbuf->padapter;
80         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
81         struct hal_data_8188e   *haldata;
82
83 _func_enter_;
84
85         switch (pxmitbuf->flags) {
86         case VO_QUEUE_INX:
87                 pxmitpriv->voq_cnt--;
88                 break;
89         case VI_QUEUE_INX:
90                 pxmitpriv->viq_cnt--;
91                 break;
92         case BE_QUEUE_INX:
93                 pxmitpriv->beq_cnt--;
94                 break;
95         case BK_QUEUE_INX:
96                 pxmitpriv->bkq_cnt--;
97                 break;
98         case HIGH_QUEUE_INX:
99 #ifdef CONFIG_88EU_AP_MODE
100                 rtw_chk_hi_queue_cmd(padapter);
101 #endif
102                 break;
103         default:
104                 break;
105         }
106
107         if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
108             padapter->bWritePortCancel) {
109                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
110                          ("usb_write_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
111                          padapter->bDriverStopped, padapter->bSurpriseRemoved));
112                 DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
113                         __func__, padapter->bDriverStopped,
114                         padapter->bSurpriseRemoved, padapter->bReadPortCancel,
115                         pxmitbuf->ext_tag);
116
117                 goto check_completion;
118         }
119
120         if (purb->status) {
121                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port_complete : purb->status(%d) != 0\n", purb->status));
122                 DBG_88E("###=> urb_write_port_complete status(%d)\n", purb->status);
123                 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
124                         sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
125                 } else if (purb->status == -EINPROGRESS) {
126                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port_complete: EINPROGESS\n"));
127                         goto check_completion;
128                 } else if (purb->status == -ENOENT) {
129                         DBG_88E("%s: -ENOENT\n", __func__);
130                         goto check_completion;
131                 } else if (purb->status == -ECONNRESET) {
132                         DBG_88E("%s: -ECONNRESET\n", __func__);
133                         goto check_completion;
134                 } else if (purb->status == -ESHUTDOWN) {
135                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port_complete: ESHUTDOWN\n"));
136                         padapter->bDriverStopped = true;
137                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port_complete:bDriverStopped = true\n"));
138                         goto check_completion;
139                 } else {
140                         padapter->bSurpriseRemoved = true;
141                         DBG_88E("bSurpriseRemoved = true\n");
142                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port_complete:bSurpriseRemoved = true\n"));
143
144                         goto check_completion;
145                 }
146         }
147
148         haldata = GET_HAL_DATA(padapter);
149         haldata->srestpriv.last_tx_complete_time = rtw_get_current_time();
150
151 check_completion:
152         rtw_sctx_done_err(&pxmitbuf->sctx,
153                           purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
154                           RTW_SCTX_DONE_SUCCESS);
155
156         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
157
158         tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
159
160 _func_exit_;
161 }
162
163 u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
164 {
165         unsigned long irqL;
166         unsigned int pipe;
167         int status;
168         u32 ret = _FAIL;
169         struct urb *purb = NULL;
170         struct adapter *padapter = (struct adapter *)pintfhdl->padapter;
171         struct dvobj_priv       *pdvobj = adapter_to_dvobj(padapter);
172         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
173         struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
174         struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
175         struct usb_device *pusbd = pdvobj->pusbdev;
176
177 _func_enter_;
178
179         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port\n"));
180
181         if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
182             (padapter->pwrctrlpriv.pnp_bstop_trx)) {
183                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
184                          ("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
185                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
186                 goto exit;
187         }
188
189         _enter_critical(&pxmitpriv->lock, &irqL);
190
191         switch (addr) {
192         case VO_QUEUE_INX:
193                 pxmitpriv->voq_cnt++;
194                 pxmitbuf->flags = VO_QUEUE_INX;
195                 break;
196         case VI_QUEUE_INX:
197                 pxmitpriv->viq_cnt++;
198                 pxmitbuf->flags = VI_QUEUE_INX;
199                 break;
200         case BE_QUEUE_INX:
201                 pxmitpriv->beq_cnt++;
202                 pxmitbuf->flags = BE_QUEUE_INX;
203                 break;
204         case BK_QUEUE_INX:
205                 pxmitpriv->bkq_cnt++;
206                 pxmitbuf->flags = BK_QUEUE_INX;
207                 break;
208         case HIGH_QUEUE_INX:
209                 pxmitbuf->flags = HIGH_QUEUE_INX;
210                 break;
211         default:
212                 pxmitbuf->flags = MGT_QUEUE_INX;
213                 break;
214         }
215
216         _exit_critical(&pxmitpriv->lock, &irqL);
217
218         purb    = pxmitbuf->pxmit_urb[0];
219
220         /* translate DMA FIFO addr to pipehandle */
221         pipe = ffaddr2pipehdl(pdvobj, addr);
222
223         usb_fill_bulk_urb(purb, pusbd, pipe,
224                           pxmitframe->buf_addr, /*  pxmitbuf->pbuf */
225                           cnt,
226                           usb_write_port_complete,
227                           pxmitbuf);/* context is pxmitbuf */
228
229         status = usb_submit_urb(purb, GFP_ATOMIC);
230         if (!status) {
231                 struct hal_data_8188e   *haldata = GET_HAL_DATA(padapter);
232
233                 haldata->srestpriv.last_tx_time = rtw_get_current_time();
234         } else {
235                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
236                 DBG_88E("usb_write_port, status =%d\n", status);
237                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_write_port(): usb_submit_urb, status =%x\n", status));
238
239                 switch (status) {
240                 case -ENODEV:
241                         padapter->bDriverStopped = true;
242                         break;
243                 default:
244                         break;
245                 }
246                 goto exit;
247         }
248
249         ret = _SUCCESS;
250
251 /*    We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
252
253         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port\n"));
254
255 exit:
256         if (ret != _SUCCESS)
257                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
258 _func_exit_;
259         return ret;
260 }
261
262 void usb_write_port_cancel(struct intf_hdl *pintfhdl)
263 {
264         int i, j;
265         struct adapter  *padapter = pintfhdl->padapter;
266         struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
267
268         DBG_88E("%s\n", __func__);
269
270         padapter->bWritePortCancel = true;
271
272         for (i = 0; i < NR_XMITBUFF; i++) {
273                 for (j = 0; j < 8; j++) {
274                         if (pxmitbuf->pxmit_urb[j])
275                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
276                 }
277                 pxmitbuf++;
278         }
279
280         pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
281         for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
282                 for (j = 0; j < 8; j++) {
283                         if (pxmitbuf->pxmit_urb[j])
284                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
285                 }
286                 pxmitbuf++;
287         }
288 }