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