root/drivers/staging/rtl8712/usb_ops_linux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. r8712_usb_init_intf_priv
  2. r8712_usb_unload_intf_priv
  3. ffaddr2pipehdl
  4. usb_write_mem_complete
  5. r8712_usb_write_mem
  6. r8712_usb_read_port_complete
  7. r8712_usb_read_port
  8. r8712_usb_read_port_cancel
  9. r8712_xmit_bh
  10. usb_write_port_complete
  11. r8712_usb_write_port
  12. r8712_usb_write_port_cancel
  13. r8712_usbctrl_vendorreq

   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 }

/* [<][>][^][v][top][bottom][index][help] */