1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _USB_OPS_LINUX_C_
17 #include <drv_types.h>
18 #include <usb_ops_linux.h>
19 #include <rtw_sreset.h>
21 unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr)
23 struct usb_device *pusbd = pdvobj->pusbdev;
24 unsigned int pipe = 0, ep_num = 0;
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_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
30 } else if (addr < HW_QUEUE_ENTRY) {
31 ep_num = pdvobj->Queue2Pipe[addr];
32 pipe = usb_sndbulkpipe(pusbd, ep_num);
37 struct zero_bulkout_context {
44 void usb_read_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
48 void usb_write_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
52 void usb_read_port_cancel23a(struct intf_hdl *pintfhdl)
54 struct recv_buf *precvbuf;
55 struct rtw_adapter *padapter = pintfhdl->padapter;
58 precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
60 DBG_8723A("%s\n", __func__);
62 padapter->bReadPortCancel = true;
64 for (i = 0; i < NR_RECVBUFF ; i++) {
66 usb_kill_urb(precvbuf->purb);
69 usb_kill_urb(padapter->recvpriv.int_in_urb);
72 static void usb_write_port23a_complete(struct urb *purb, struct pt_regs *regs)
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;
80 switch (pxmitbuf->flags) {
94 #ifdef CONFIG_8723AU_AP_MODE
95 rtw_chk_hi_queue_cmd23a(padapter);
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,
112 goto check_completion;
116 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
117 ("usb_write_port23a_complete : purb->status(%d) != 0\n",
119 DBG_8723A("###=> urb_write_port_complete status(%d)\n",
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;
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;
149 phaldata = GET_HAL_DATA(padapter);
150 phaldata->srestpriv.last_tx_complete_time = jiffies;
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);
159 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
161 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
164 u32 usb_write_port23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
165 struct xmit_buf *pxmitbuf)
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;
178 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port23a\n"));
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);
188 spin_lock_irqsave(&pxmitpriv->lock, irqL);
192 pxmitpriv->voq_cnt++;
193 pxmitbuf->flags = VO_QUEUE_INX;
196 pxmitpriv->viq_cnt++;
197 pxmitbuf->flags = VI_QUEUE_INX;
200 pxmitpriv->beq_cnt++;
201 pxmitbuf->flags = BE_QUEUE_INX;
204 pxmitpriv->bkq_cnt++;
205 pxmitbuf->flags = BK_QUEUE_INX;
208 pxmitbuf->flags = HIGH_QUEUE_INX;
211 pxmitbuf->flags = MGT_QUEUE_INX;
215 spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
217 purb = pxmitbuf->pxmit_urb[0];
219 /* translate DMA FIFO addr to pipehandle */
220 pipe = ffaddr2pipehdl23a(pdvobj, addr);
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 */
227 status = usb_submit_urb(purb, GFP_ATOMIC);
229 struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter);
230 phaldata->srestpriv.last_tx_time = jiffies;
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",
241 padapter->bDriverStopped = true;
249 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port23a\n"));
253 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
258 void usb_write_port23a_cancel(struct intf_hdl *pintfhdl)
260 struct rtw_adapter *padapter = pintfhdl->padapter;
261 struct xmit_buf *pxmitbuf;
262 struct list_head *plist;
265 DBG_8723A("%s\n", __func__);
267 padapter->bWritePortCancel = true;
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]);
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]);