1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2012 Realtek Corporation. */
3
4 #define _USB_OPS_LINUX_C_
5
6 #include "../include/drv_types.h"
7 #include "../include/usb_ops_linux.h"
8 #include "../include/rtw_sreset.h"
9
ffaddr2pipehdl(struct dvobj_priv * pdvobj,u32 addr)10 unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
11 {
12 unsigned int pipe = 0, ep_num = 0;
13 struct usb_device *pusbd = pdvobj->pusbdev;
14
15 if (addr == RECV_BULK_IN_ADDR) {
16 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
17 } else if (addr == RECV_INT_IN_ADDR) {
18 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
19 } else if (addr < HW_QUEUE_ENTRY) {
20 ep_num = pdvobj->Queue2Pipe[addr];
21 pipe = usb_sndbulkpipe(pusbd, ep_num);
22 }
23
24 return pipe;
25 }
26
27 struct zero_bulkout_context {
28 void *pbuf;
29 void *purb;
30 void *pirp;
31 void *padapter;
32 };
33
usb_read_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)34 void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
35 {
36 }
37
usb_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)38 void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
39 {
40 }
41
usb_read_port_cancel(struct intf_hdl * pintfhdl)42 void usb_read_port_cancel(struct intf_hdl *pintfhdl)
43 {
44 int i;
45 struct recv_buf *precvbuf;
46 struct adapter *padapter = pintfhdl->padapter;
47 precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
48
49 DBG_88E("%s\n", __func__);
50
51 padapter->bReadPortCancel = true;
52
53 for (i = 0; i < NR_RECVBUFF; i++) {
54 precvbuf->reuse = true;
55 if (precvbuf->purb)
56 usb_kill_urb(precvbuf->purb);
57 precvbuf++;
58 }
59 }
60
usb_write_port_complete(struct urb * purb,struct pt_regs * regs)61 static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
62 {
63 struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
64 struct adapter *padapter = pxmitbuf->padapter;
65 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
66 struct hal_data_8188e *haldata;
67
68 switch (pxmitbuf->flags) {
69 case VO_QUEUE_INX:
70 pxmitpriv->voq_cnt--;
71 break;
72 case VI_QUEUE_INX:
73 pxmitpriv->viq_cnt--;
74 break;
75 case BE_QUEUE_INX:
76 pxmitpriv->beq_cnt--;
77 break;
78 case BK_QUEUE_INX:
79 pxmitpriv->bkq_cnt--;
80 break;
81 case HIGH_QUEUE_INX:
82 #ifdef CONFIG_88EU_AP_MODE
83 rtw_chk_hi_queue_cmd(padapter);
84 #endif
85 break;
86 default:
87 break;
88 }
89
90 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
91 padapter->bWritePortCancel) {
92 DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
93 __func__, padapter->bDriverStopped,
94 padapter->bSurpriseRemoved, padapter->bReadPortCancel,
95 pxmitbuf->ext_tag);
96
97 goto check_completion;
98 }
99
100 if (purb->status) {
101 DBG_88E("###=> urb_write_port_complete status(%d)\n", purb->status);
102 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
103 sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
104 } else if (purb->status == -EINPROGRESS) {
105 goto check_completion;
106 } else if (purb->status == -ENOENT) {
107 DBG_88E("%s: -ENOENT\n", __func__);
108 goto check_completion;
109 } else if (purb->status == -ECONNRESET) {
110 DBG_88E("%s: -ECONNRESET\n", __func__);
111 goto check_completion;
112 } else if (purb->status == -ESHUTDOWN) {
113 padapter->bDriverStopped = true;
114 goto check_completion;
115 } else {
116 padapter->bSurpriseRemoved = true;
117 DBG_88E("bSurpriseRemoved = true\n");
118
119 goto check_completion;
120 }
121 }
122
123 haldata = GET_HAL_DATA(padapter);
124 haldata->srestpriv.last_tx_complete_time = jiffies;
125
126 check_completion:
127 rtw_sctx_done_err(&pxmitbuf->sctx,
128 purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
129 RTW_SCTX_DONE_SUCCESS);
130
131 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
132
133 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
134
135 }
136
usb_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)137 u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
138 {
139 unsigned long irqL;
140 unsigned int pipe;
141 int status;
142 u32 ret = _FAIL;
143 struct urb *purb = NULL;
144 struct adapter *padapter = (struct adapter *)pintfhdl->padapter;
145 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
146 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
147 struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
148 struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
149 struct usb_device *pusbd = pdvobj->pusbdev;
150
151 if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
152 (padapter->pwrctrlpriv.pnp_bstop_trx)) {
153 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
154 goto exit;
155 }
156
157 spin_lock_irqsave(&pxmitpriv->lock, irqL);
158
159 switch (addr) {
160 case VO_QUEUE_INX:
161 pxmitpriv->voq_cnt++;
162 pxmitbuf->flags = VO_QUEUE_INX;
163 break;
164 case VI_QUEUE_INX:
165 pxmitpriv->viq_cnt++;
166 pxmitbuf->flags = VI_QUEUE_INX;
167 break;
168 case BE_QUEUE_INX:
169 pxmitpriv->beq_cnt++;
170 pxmitbuf->flags = BE_QUEUE_INX;
171 break;
172 case BK_QUEUE_INX:
173 pxmitpriv->bkq_cnt++;
174 pxmitbuf->flags = BK_QUEUE_INX;
175 break;
176 case HIGH_QUEUE_INX:
177 pxmitbuf->flags = HIGH_QUEUE_INX;
178 break;
179 default:
180 pxmitbuf->flags = MGT_QUEUE_INX;
181 break;
182 }
183
184 spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
185
186 purb = pxmitbuf->pxmit_urb[0];
187
188 /* translate DMA FIFO addr to pipehandle */
189 pipe = ffaddr2pipehdl(pdvobj, addr);
190
191 usb_fill_bulk_urb(purb, pusbd, pipe,
192 pxmitframe->buf_addr, /* pxmitbuf->pbuf */
193 cnt,
194 usb_write_port_complete,
195 pxmitbuf);/* context is pxmitbuf */
196
197 status = usb_submit_urb(purb, GFP_ATOMIC);
198 if (!status) {
199 struct hal_data_8188e *haldata = GET_HAL_DATA(padapter);
200
201 haldata->srestpriv.last_tx_time = jiffies;
202 } else {
203 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
204 DBG_88E("usb_write_port, status =%d\n", status);
205
206 switch (status) {
207 case -ENODEV:
208 padapter->bDriverStopped = true;
209 break;
210 default:
211 break;
212 }
213 goto exit;
214 }
215
216 ret = _SUCCESS;
217
218 /* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
219
220 exit:
221 if (ret != _SUCCESS)
222 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
223
224 return ret;
225 }
226
usb_write_port_cancel(struct intf_hdl * pintfhdl)227 void usb_write_port_cancel(struct intf_hdl *pintfhdl)
228 {
229 int i, j;
230 struct adapter *padapter = pintfhdl->padapter;
231 struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
232
233 DBG_88E("%s\n", __func__);
234
235 padapter->bWritePortCancel = true;
236
237 for (i = 0; i < NR_XMITBUFF; i++) {
238 for (j = 0; j < 8; j++) {
239 if (pxmitbuf->pxmit_urb[j])
240 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
241 }
242 pxmitbuf++;
243 }
244
245 pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
246 for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
247 for (j = 0; j < 8; j++) {
248 if (pxmitbuf->pxmit_urb[j])
249 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
250 }
251 pxmitbuf++;
252 }
253 }
254