1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 * usb_ops_linux.c
4 *
5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6 * Linux device driver for RTL8192SU
7 *
8 * Modifications for inclusion into the Linux staging tree are
9 * Copyright(c) 2010 Larry Finger. All rights reserved.
10 *
11 * Contact information:
12 * WLAN FAE <wlanfae@realtek.com>
13 * Larry Finger <Larry.Finger@lwfinger.net>
14 *
15 ******************************************************************************/
16
17 #define _HCI_OPS_OS_C_
18
19 #include <linux/usb.h>
20
21 #include "osdep_service.h"
22 #include "drv_types.h"
23 #include "osdep_intf.h"
24 #include "usb_ops.h"
25
26 #define RTL871X_VENQT_READ 0xc0
27 #define RTL871X_VENQT_WRITE 0x40
28
r8712_usb_init_intf_priv(struct intf_priv * pintfpriv)29 uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv)
30 {
31 pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC);
32 if (!pintfpriv->piorw_urb)
33 return _FAIL;
34 init_completion(&pintfpriv->io_retevt_comp);
35 return _SUCCESS;
36 }
37
r8712_usb_unload_intf_priv(struct intf_priv * pintfpriv)38 void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv)
39 {
40 if (pintfpriv->piorw_urb) {
41 usb_kill_urb(pintfpriv->piorw_urb);
42 usb_free_urb(pintfpriv->piorw_urb);
43 }
44 }
45
ffaddr2pipehdl(struct dvobj_priv * pdvobj,u32 addr)46 static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
47 {
48 unsigned int pipe = 0;
49 struct usb_device *pusbd = pdvobj->pusbdev;
50
51 if (pdvobj->nr_endpoint == 11) {
52 switch (addr) {
53 case RTL8712_DMA_BKQ:
54 pipe = usb_sndbulkpipe(pusbd, 0x07);
55 break;
56 case RTL8712_DMA_BEQ:
57 pipe = usb_sndbulkpipe(pusbd, 0x06);
58 break;
59 case RTL8712_DMA_VIQ:
60 pipe = usb_sndbulkpipe(pusbd, 0x05);
61 break;
62 case RTL8712_DMA_VOQ:
63 pipe = usb_sndbulkpipe(pusbd, 0x04);
64 break;
65 case RTL8712_DMA_BCNQ:
66 pipe = usb_sndbulkpipe(pusbd, 0x0a);
67 break;
68 case RTL8712_DMA_BMCQ: /* HI Queue */
69 pipe = usb_sndbulkpipe(pusbd, 0x0b);
70 break;
71 case RTL8712_DMA_MGTQ:
72 pipe = usb_sndbulkpipe(pusbd, 0x0c);
73 break;
74 case RTL8712_DMA_RX0FF:
75 pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
76 break;
77 case RTL8712_DMA_C2HCMD:
78 pipe = usb_rcvbulkpipe(pusbd, 0x09); /* in */
79 break;
80 case RTL8712_DMA_H2CCMD:
81 pipe = usb_sndbulkpipe(pusbd, 0x0d);
82 break;
83 }
84 } else if (pdvobj->nr_endpoint == 6) {
85 switch (addr) {
86 case RTL8712_DMA_BKQ:
87 pipe = usb_sndbulkpipe(pusbd, 0x07);
88 break;
89 case RTL8712_DMA_BEQ:
90 pipe = usb_sndbulkpipe(pusbd, 0x06);
91 break;
92 case RTL8712_DMA_VIQ:
93 pipe = usb_sndbulkpipe(pusbd, 0x05);
94 break;
95 case RTL8712_DMA_VOQ:
96 pipe = usb_sndbulkpipe(pusbd, 0x04);
97 break;
98 case RTL8712_DMA_RX0FF:
99 case RTL8712_DMA_C2HCMD:
100 pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
101 break;
102 case RTL8712_DMA_H2CCMD:
103 case RTL8712_DMA_BCNQ:
104 case RTL8712_DMA_BMCQ:
105 case RTL8712_DMA_MGTQ:
106 pipe = usb_sndbulkpipe(pusbd, 0x0d);
107 break;
108 }
109 } else if (pdvobj->nr_endpoint == 4) {
110 switch (addr) {
111 case RTL8712_DMA_BEQ:
112 pipe = usb_sndbulkpipe(pusbd, 0x06);
113 break;
114 case RTL8712_DMA_VOQ:
115 pipe = usb_sndbulkpipe(pusbd, 0x04);
116 break;
117 case RTL8712_DMA_RX0FF:
118 case RTL8712_DMA_C2HCMD:
119 pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
120 break;
121 case RTL8712_DMA_H2CCMD:
122 case RTL8712_DMA_BCNQ:
123 case RTL8712_DMA_BMCQ:
124 case RTL8712_DMA_MGTQ:
125 pipe = usb_sndbulkpipe(pusbd, 0x0d);
126 break;
127 }
128 } else {
129 pipe = 0;
130 }
131 return pipe;
132 }
133
usb_write_mem_complete(struct urb * purb)134 static void usb_write_mem_complete(struct urb *purb)
135 {
136 struct io_queue *pio_q = (struct io_queue *)purb->context;
137 struct intf_hdl *pintf = &(pio_q->intf);
138 struct intf_priv *pintfpriv = pintf->pintfpriv;
139 struct _adapter *padapter = (struct _adapter *)pintf->adapter;
140
141 if (purb->status != 0) {
142 if (purb->status == (-ESHUTDOWN))
143 padapter->driver_stopped = true;
144 else
145 padapter->surprise_removed = true;
146 }
147 complete(&pintfpriv->io_retevt_comp);
148 }
149
r8712_usb_write_mem(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)150 void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
151 {
152 unsigned int pipe;
153 struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
154 struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
155 struct io_queue *pio_queue = padapter->pio_queue;
156 struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
157 struct usb_device *pusbd = pdvobj->pusbdev;
158 struct urb *piorw_urb = pintfpriv->piorw_urb;
159
160 if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
161 (padapter->pwrctrlpriv.pnp_bstop_trx))
162 return;
163 /* translate DMA FIFO addr to pipehandle */
164 pipe = ffaddr2pipehdl(pdvobj, addr);
165 if (pipe == 0)
166 return;
167 usb_fill_bulk_urb(piorw_urb, pusbd, pipe,
168 wmem, cnt, usb_write_mem_complete,
169 pio_queue);
170 usb_submit_urb(piorw_urb, GFP_ATOMIC);
171 wait_for_completion_interruptible(&pintfpriv->io_retevt_comp);
172 }
173
r8712_usb_read_port_complete(struct urb * purb)174 static void r8712_usb_read_port_complete(struct urb *purb)
175 {
176 uint isevt;
177 __le32 *pbuf;
178 struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
179 struct _adapter *padapter = (struct _adapter *)precvbuf->adapter;
180 struct recv_priv *precvpriv = &padapter->recvpriv;
181
182 if (padapter->surprise_removed || padapter->driver_stopped)
183 return;
184 if (purb->status == 0) { /* SUCCESS */
185 if ((purb->actual_length > (MAX_RECVBUF_SZ)) ||
186 (purb->actual_length < RXDESC_SIZE)) {
187 r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
188 (unsigned char *)precvbuf);
189 } else {
190 _pkt *pskb = precvbuf->pskb;
191
192 precvbuf->transfer_len = purb->actual_length;
193 pbuf = (__le32 *)precvbuf->pbuf;
194 isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff;
195 if ((isevt & 0x1ff) == 0x1ff) {
196 r8712_rxcmd_event_hdl(padapter, pbuf);
197 skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
198 r8712_read_port(padapter, precvpriv->ff_hwaddr,
199 0, (unsigned char *)precvbuf);
200 } else {
201 skb_put(pskb, purb->actual_length);
202 skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
203 tasklet_hi_schedule(&precvpriv->recv_tasklet);
204 r8712_read_port(padapter, precvpriv->ff_hwaddr,
205 0, (unsigned char *)precvbuf);
206 }
207 }
208 } else {
209 switch (purb->status) {
210 case -EINVAL:
211 case -EPIPE:
212 case -ENODEV:
213 case -ESHUTDOWN:
214 padapter->driver_stopped = true;
215 break;
216 case -ENOENT:
217 if (!padapter->suspended) {
218 padapter->driver_stopped = true;
219 break;
220 }
221 fallthrough;
222 case -EPROTO:
223 r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
224 (unsigned char *)precvbuf);
225 break;
226 case -EINPROGRESS:
227 netdev_err(padapter->pnetdev, "ERROR: URB IS IN PROGRESS!\n");
228 break;
229 default:
230 break;
231 }
232 }
233 }
234
r8712_usb_read_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * rmem)235 u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
236 {
237 unsigned int pipe;
238 int err;
239 u32 tmpaddr = 0;
240 int alignment = 0;
241 u32 ret = _SUCCESS;
242 struct urb *purb = NULL;
243 struct recv_buf *precvbuf = (struct recv_buf *)rmem;
244 struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
245 struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
246 struct _adapter *adapter = pdvobj->padapter;
247 struct recv_priv *precvpriv = &adapter->recvpriv;
248 struct usb_device *pusbd = pdvobj->pusbdev;
249
250 if (adapter->driver_stopped || adapter->surprise_removed ||
251 adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf)
252 return _FAIL;
253 r8712_init_recvbuf(adapter, precvbuf);
254 /* Try to use skb from the free queue */
255 precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
256
257 if (!precvbuf->pskb) {
258 precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev,
259 MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
260 if (!precvbuf->pskb)
261 return _FAIL;
262 tmpaddr = (addr_t)precvbuf->pskb->data;
263 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
264 skb_reserve(precvbuf->pskb,
265 (RECVBUFF_ALIGN_SZ - alignment));
266 precvbuf->phead = precvbuf->pskb->head;
267 precvbuf->pdata = precvbuf->pskb->data;
268 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
269 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
270 precvbuf->pbuf = precvbuf->pskb->data;
271 } else { /* skb is reused */
272 precvbuf->phead = precvbuf->pskb->head;
273 precvbuf->pdata = precvbuf->pskb->data;
274 precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
275 precvbuf->pend = skb_end_pointer(precvbuf->pskb);
276 precvbuf->pbuf = precvbuf->pskb->data;
277 }
278 purb = precvbuf->purb;
279 /* translate DMA FIFO addr to pipehandle */
280 pipe = ffaddr2pipehdl(pdvobj, addr);
281 usb_fill_bulk_urb(purb, pusbd, pipe,
282 precvbuf->pbuf, MAX_RECVBUF_SZ,
283 r8712_usb_read_port_complete,
284 precvbuf);
285 err = usb_submit_urb(purb, GFP_ATOMIC);
286 if ((err) && (err != (-EPERM)))
287 ret = _FAIL;
288 return ret;
289 }
290
r8712_usb_read_port_cancel(struct _adapter * padapter)291 void r8712_usb_read_port_cancel(struct _adapter *padapter)
292 {
293 int i;
294 struct recv_buf *precvbuf;
295
296 precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
297 for (i = 0; i < NR_RECVBUFF; i++) {
298 if (precvbuf->purb)
299 usb_kill_urb(precvbuf->purb);
300 precvbuf++;
301 }
302 }
303
r8712_xmit_bh(struct tasklet_struct * t)304 void r8712_xmit_bh(struct tasklet_struct *t)
305 {
306 int ret = false;
307 struct _adapter *padapter = from_tasklet(padapter, t,
308 xmitpriv.xmit_tasklet);
309 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
310
311 if (padapter->driver_stopped ||
312 padapter->surprise_removed) {
313 netdev_err(padapter->pnetdev, "xmit_bh => driver_stopped or surprise_removed\n");
314 return;
315 }
316 ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
317 if (!ret)
318 return;
319 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
320 }
321
usb_write_port_complete(struct urb * purb)322 static void usb_write_port_complete(struct urb *purb)
323 {
324 int i;
325 struct xmit_frame *pxmitframe = (struct xmit_frame *)purb->context;
326 struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
327 struct _adapter *padapter = pxmitframe->padapter;
328 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
329 struct pkt_attrib *pattrib = &pxmitframe->attrib;
330
331 switch (pattrib->priority) {
332 case 1:
333 case 2:
334 pxmitpriv->bkq_cnt--;
335 break;
336 case 4:
337 case 5:
338 pxmitpriv->viq_cnt--;
339 break;
340 case 6:
341 case 7:
342 pxmitpriv->voq_cnt--;
343 break;
344 case 0:
345 case 3:
346 default:
347 pxmitpriv->beq_cnt--;
348 break;
349 }
350 pxmitpriv->txirp_cnt--;
351 for (i = 0; i < 8; i++) {
352 if (purb == pxmitframe->pxmit_urb[i]) {
353 pxmitframe->bpending[i] = false;
354 break;
355 }
356 }
357 if (padapter->surprise_removed)
358 return;
359 switch (purb->status) {
360 case 0:
361 break;
362 default:
363 netdev_warn(padapter->pnetdev,
364 "r8712u: pipe error: (%d)\n", purb->status);
365 break;
366 }
367 /* not to consider tx fragment */
368 r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
369 r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
370 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
371 }
372
r8712_usb_write_port(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * wmem)373 u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
374 {
375 unsigned long irqL;
376 int i, status;
377 unsigned int pipe;
378 u32 ret, bwritezero;
379 struct urb *purb = NULL;
380 struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
381 struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
382 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
383 struct xmit_frame *pxmitframe = (struct xmit_frame *)wmem;
384 struct usb_device *pusbd = pdvobj->pusbdev;
385 struct pkt_attrib *pattrib = &pxmitframe->attrib;
386
387 if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
388 (padapter->pwrctrlpriv.pnp_bstop_trx))
389 return _FAIL;
390 for (i = 0; i < 8; i++) {
391 if (!pxmitframe->bpending[i]) {
392 spin_lock_irqsave(&pxmitpriv->lock, irqL);
393 pxmitpriv->txirp_cnt++;
394 pxmitframe->bpending[i] = true;
395 switch (pattrib->priority) {
396 case 1:
397 case 2:
398 pxmitpriv->bkq_cnt++;
399 break;
400 case 4:
401 case 5:
402 pxmitpriv->viq_cnt++;
403 break;
404 case 6:
405 case 7:
406 pxmitpriv->voq_cnt++;
407 break;
408 case 0:
409 case 3:
410 default:
411 pxmitpriv->beq_cnt++;
412 break;
413 }
414 spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
415 pxmitframe->sz[i] = (u16)cnt;
416 purb = pxmitframe->pxmit_urb[i];
417 break;
418 }
419 }
420 bwritezero = false;
421 if (pdvobj->ishighspeed) {
422 if (cnt > 0 && cnt % 512 == 0)
423 bwritezero = true;
424 } else {
425 if (cnt > 0 && cnt % 64 == 0)
426 bwritezero = true;
427 }
428 /* translate DMA FIFO addr to pipehandle */
429 pipe = ffaddr2pipehdl(pdvobj, addr);
430 if (pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)
431 purb->transfer_flags &= (~URB_NO_INTERRUPT);
432 else
433 purb->transfer_flags |= URB_NO_INTERRUPT;
434 if (bwritezero)
435 cnt += 8;
436 usb_fill_bulk_urb(purb, pusbd, pipe,
437 pxmitframe->mem_addr,
438 cnt, usb_write_port_complete,
439 pxmitframe); /* context is xmit_frame */
440 status = usb_submit_urb(purb, GFP_ATOMIC);
441 if (!status)
442 ret = _SUCCESS;
443 else
444 ret = _FAIL;
445 return ret;
446 }
447
r8712_usb_write_port_cancel(struct _adapter * padapter)448 void r8712_usb_write_port_cancel(struct _adapter *padapter)
449 {
450 int i, j;
451 struct xmit_buf *pxmitbuf = (struct xmit_buf *)
452 padapter->xmitpriv.pxmitbuf;
453
454 for (i = 0; i < NR_XMITBUFF; i++) {
455 for (j = 0; j < 8; j++) {
456 if (pxmitbuf->pxmit_urb[j])
457 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
458 }
459 pxmitbuf++;
460 }
461 }
462
r8712_usbctrl_vendorreq(struct intf_priv * pintfpriv,u8 request,u16 value,u16 index,void * pdata,u16 len,u8 requesttype)463 int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
464 u16 index, void *pdata, u16 len, u8 requesttype)
465 {
466 unsigned int pipe;
467 int status;
468 u8 reqtype;
469 struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
470 pintfpriv->intf_dev;
471 struct usb_device *udev = pdvobjpriv->pusbdev;
472 /* For mstar platform, mstar suggests the address for USB IO
473 * should be 16 bytes alignment. Trying to fix it here.
474 */
475 u8 *palloc_buf, *pIo_buf;
476
477 palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC);
478 if (!palloc_buf)
479 return -ENOMEM;
480 pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f);
481 if (requesttype == 0x01) {
482 pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
483 reqtype = RTL871X_VENQT_READ;
484 } else {
485 pipe = usb_sndctrlpipe(udev, 0); /* write_out */
486 reqtype = RTL871X_VENQT_WRITE;
487 memcpy(pIo_buf, pdata, len);
488 }
489 status = usb_control_msg(udev, pipe, request, reqtype, value, index,
490 pIo_buf, len, 500);
491 if (status < 0)
492 goto free;
493 if (status != len) {
494 status = -EREMOTEIO;
495 goto free;
496 }
497 /* Success this control transfer. */
498 if (requesttype == 0x01) {
499 /* For Control read transfer, we have to copy the read
500 * data from pIo_buf to pdata.
501 */
502 memcpy(pdata, pIo_buf, status);
503 }
504
505 free:
506 kfree(palloc_buf);
507 return status;
508 }
509