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