staging: rtl8723au: Use correct pipe type for USB interrupts
[cascardo/linux.git] / 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 unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr)
22 {
23         struct usb_device *pusbd = pdvobj->pusbdev;
24         unsigned int pipe = 0, ep_num = 0;
25
26         if (addr == RECV_BULK_IN_ADDR) {
27                 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
28         } else if (addr == RECV_INT_IN_ADDR) {
29                 pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]);
30         } else if (addr < HW_QUEUE_ENTRY) {
31                 ep_num = pdvobj->Queue2Pipe[addr];
32                 pipe = usb_sndbulkpipe(pusbd, ep_num);
33         }
34         return pipe;
35 }
36
37 struct zero_bulkout_context {
38         void *pbuf;
39         void *purb;
40         void *pirp;
41         void *padapter;
42 };
43
44 void usb_read_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
45 {
46 }
47
48 void usb_write_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
49 {
50 }
51
52 void usb_read_port_cancel23a(struct intf_hdl *pintfhdl)
53 {
54         struct recv_buf *precvbuf;
55         struct rtw_adapter *padapter = pintfhdl->padapter;
56         int i;
57
58         precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
59
60         DBG_8723A("%s\n", __func__);
61
62         padapter->bReadPortCancel = true;
63
64         for (i = 0; i < NR_RECVBUFF ; i++) {
65                 if (precvbuf->purb)
66                         usb_kill_urb(precvbuf->purb);
67                 precvbuf++;
68         }
69         usb_kill_urb(padapter->recvpriv.int_in_urb);
70 }
71
72 static void usb_write_port23a_complete(struct urb *purb, struct pt_regs *regs)
73 {
74         struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
75         struct rtw_adapter *padapter = pxmitbuf->padapter;
76         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
77         struct hal_data_8723a *phaldata;
78         unsigned long irqL;
79
80         switch (pxmitbuf->flags) {
81         case VO_QUEUE_INX:
82                 pxmitpriv->voq_cnt--;
83                 break;
84         case VI_QUEUE_INX:
85                 pxmitpriv->viq_cnt--;
86                 break;
87         case BE_QUEUE_INX:
88                 pxmitpriv->beq_cnt--;
89                 break;
90         case BK_QUEUE_INX:
91                 pxmitpriv->bkq_cnt--;
92                 break;
93         case HIGH_QUEUE_INX:
94 #ifdef CONFIG_8723AU_AP_MODE
95                 rtw_chk_hi_queue_cmd23a(padapter);
96 #endif
97                 break;
98         default:
99                 break;
100         }
101
102         if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
103             padapter->bWritePortCancel) {
104                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
105                          ("usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
106                          padapter->bDriverStopped, padapter->bSurpriseRemoved));
107                 DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
108                           __func__, padapter->bDriverStopped,
109                           padapter->bSurpriseRemoved, padapter->bReadPortCancel,
110                           pxmitbuf->ext_tag);
111
112                 goto check_completion;
113         }
114
115         if (purb->status) {
116                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
117                          ("usb_write_port23a_complete : purb->status(%d) != 0\n",
118                          purb->status));
119                 DBG_8723A("###=> urb_write_port_complete status(%d)\n",
120                           purb->status);
121                 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
122                         sreset_set_wifi_error_status23a(padapter,
123                                                      USB_WRITE_PORT_FAIL);
124                 } else if (purb->status == -EINPROGRESS) {
125                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
126                                  ("usb_write_port23a_complete: EINPROGESS\n"));
127                         goto check_completion;
128                 } else if (purb->status == -ENOENT) {
129                         DBG_8723A("%s: -ENOENT\n", __func__);
130                         goto check_completion;
131                 } else if (purb->status == -ECONNRESET) {
132                         DBG_8723A("%s: -ECONNRESET\n", __func__);
133                         goto check_completion;
134                 } else if (purb->status == -ESHUTDOWN) {
135                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
136                                  ("usb_write_port23a_complete: ESHUTDOWN\n"));
137                         padapter->bDriverStopped = true;
138                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
139                                  ("usb_write_port23a_complete:bDriverStopped = true\n"));
140                         goto check_completion;
141                 } else {
142                         padapter->bSurpriseRemoved = true;
143                         DBG_8723A("bSurpriseRemoved = true\n");
144                         RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
145                                  ("usb_write_port23a_complete:bSurpriseRemoved = true\n"));
146                         goto check_completion;
147                 }
148         }
149         phaldata = GET_HAL_DATA(padapter);
150         phaldata->srestpriv.last_tx_complete_time = jiffies;
151
152 check_completion:
153         spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
154         rtw23a_sctx_done_err(&pxmitbuf->sctx,
155                           purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
156                           RTW_SCTX_DONE_SUCCESS);
157         spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
158
159         rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
160
161         tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
162 }
163
164 u32 usb_write_port23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
165                    struct xmit_buf *pxmitbuf)
166 {
167         struct urb *purb = NULL;
168         struct rtw_adapter *padapter = (struct rtw_adapter *)pintfhdl->padapter;
169         struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
170         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
171         struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
172         struct usb_device *pusbd = pdvobj->pusbdev;
173         unsigned long irqL;
174         unsigned int pipe;
175         int status;
176         u32 ret = _FAIL;
177
178         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port23a\n"));
179
180         if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
181             (padapter->pwrctrlpriv.pnp_bstop_trx)) {
182                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
183                          ("usb_write_port23a:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
184                 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
185                 goto exit;
186         }
187
188         spin_lock_irqsave(&pxmitpriv->lock, irqL);
189
190         switch (addr) {
191         case VO_QUEUE_INX:
192                 pxmitpriv->voq_cnt++;
193                 pxmitbuf->flags = VO_QUEUE_INX;
194                 break;
195         case VI_QUEUE_INX:
196                 pxmitpriv->viq_cnt++;
197                 pxmitbuf->flags = VI_QUEUE_INX;
198                 break;
199         case BE_QUEUE_INX:
200                 pxmitpriv->beq_cnt++;
201                 pxmitbuf->flags = BE_QUEUE_INX;
202                 break;
203         case BK_QUEUE_INX:
204                 pxmitpriv->bkq_cnt++;
205                 pxmitbuf->flags = BK_QUEUE_INX;
206                 break;
207         case HIGH_QUEUE_INX:
208                 pxmitbuf->flags = HIGH_QUEUE_INX;
209                 break;
210         default:
211                 pxmitbuf->flags = MGT_QUEUE_INX;
212                 break;
213         }
214
215         spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
216
217         purb    = pxmitbuf->pxmit_urb[0];
218
219         /* translate DMA FIFO addr to pipehandle */
220         pipe = ffaddr2pipehdl23a(pdvobj, addr);
221
222         usb_fill_bulk_urb(purb, pusbd, pipe,
223                           pxmitframe->buf_addr, /*  pxmitbuf->pbuf */
224                           cnt, usb_write_port23a_complete,
225                           pxmitbuf);/* context is pxmitbuf */
226
227         status = usb_submit_urb(purb, GFP_ATOMIC);
228         if (!status) {
229                 struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter);
230                 phaldata->srestpriv.last_tx_time = jiffies;
231         } else {
232                 rtw23a_sctx_done_err(&pxmitbuf->sctx,
233                                   RTW_SCTX_DONE_WRITE_PORT_ERR);
234                 DBG_8723A("usb_write_port23a, status =%d\n", status);
235                 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
236                          ("usb_write_port23a(): usb_submit_urb, status =%x\n",
237                          status));
238
239                 switch (status) {
240                 case -ENODEV:
241                         padapter->bDriverStopped = true;
242                         break;
243                 default:
244                         break;
245                 }
246                 goto exit;
247         }
248         ret = _SUCCESS;
249         RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port23a\n"));
250
251 exit:
252         if (ret != _SUCCESS)
253                 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
254
255         return ret;
256 }
257
258 void usb_write_port23a_cancel(struct intf_hdl *pintfhdl)
259 {
260         struct rtw_adapter *padapter = pintfhdl->padapter;
261         struct xmit_buf *pxmitbuf;
262         struct list_head *plist;
263         int j;
264
265         DBG_8723A("%s\n", __func__);
266
267         padapter->bWritePortCancel = true;
268
269         list_for_each(plist, &padapter->xmitpriv.xmitbuf_list) {
270                 pxmitbuf = container_of(plist, struct xmit_buf, list2);
271                 for (j = 0; j < 8; j++) {
272                         if (pxmitbuf->pxmit_urb[j])
273                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
274                 }
275         }
276         list_for_each(plist, &padapter->xmitpriv.xmitextbuf_list) {
277                 pxmitbuf = container_of(plist, struct xmit_buf, list2);
278                 for (j = 0; j < 8; j++) {
279                         if (pxmitbuf->pxmit_urb[j])
280                                 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
281                 }
282         }
283 }