12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/****************************************************************************** 22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * usb_ops_linux.c 32865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 42865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. 52865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Linux device driver for RTL8192SU 62865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 72865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is free software; you can redistribute it and/or modify it 82865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * under the terms of version 2 of the GNU General Public License as 92865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * published by the Free Software Foundation. 102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT 122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * more details. 152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * You should have received a copy of the GNU General Public License along with 172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * this program; if not, write to the Free Software Foundation, Inc., 182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Modifications for inclusion into the Linux staging tree are 212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2010 Larry Finger. All rights reserved. 222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Contact information: 242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * WLAN FAE <wlanfae@realtek.com> 252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Larry Finger <Larry.Finger@lwfinger.net> 262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ******************************************************************************/ 282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define _HCI_OPS_OS_C_ 302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 31359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/usb.h> 32359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar 332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h" 342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h" 352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_intf.h" 362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "usb_ops.h" 372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define RTL871X_VENQT_READ 0xc0 392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define RTL871X_VENQT_WRITE 0x40 402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstruct zero_bulkout_context { 422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void *pbuf; 432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void *purb; 442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void *pirp; 452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger void *padapter; 462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger}; 472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeruint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv) 492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 5068e9b249565ef2786eee2b4676c8f04c8154215dAli Bahar pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC); 512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!pintfpriv->piorw_urb) 522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _FAIL; 532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger sema_init(&(pintfpriv->io_retevt), 0); 542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _SUCCESS; 552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv) 582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pintfpriv->piorw_urb) { 602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_kill_urb(pintfpriv->piorw_urb); 612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_free_urb(pintfpriv->piorw_urb); 622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr) 662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int pipe = 0; 682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_device *pusbd = pdvobj->pusbdev; 692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pdvobj->nr_endpoint == 11) { 712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (addr) { 722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BKQ: 732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x07); 742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BEQ: 762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x06); 772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_VIQ: 792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x05); 802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_VOQ: 822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x04); 832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BCNQ: 852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0a); 862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BMCQ: /* HI Queue */ 882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0b); 892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_MGTQ: 912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0c); 922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_RX0FF: 942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ 952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_C2HCMD: 972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_rcvbulkpipe(pusbd, 0x09); /* in */ 982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_H2CCMD: 1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0d); 1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if (pdvobj->nr_endpoint == 6) { 1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (addr) { 1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BKQ: 1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x07); 1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BEQ: 1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x06); 1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_VIQ: 1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x05); 1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_VOQ: 1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x04); 1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_RX0FF: 1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_C2HCMD: 1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ 1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_H2CCMD: 1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BCNQ: 1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BMCQ: 1242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_MGTQ: 1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0d); 1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else if (pdvobj->nr_endpoint == 4) { 1292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (addr) { 1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BEQ: 1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x06); 1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_VOQ: 1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x04); 1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_RX0FF: 1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_C2HCMD: 1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ 1392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_H2CCMD: 1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BCNQ: 1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_BMCQ: 1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case RTL8712_DMA_MGTQ: 1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndbulkpipe(pusbd, 0x0d); 1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else 1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = 0; 1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return pipe; 1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void usb_write_mem_complete(struct urb *purb) 1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct io_queue *pio_q = (struct io_queue *)purb->context; 1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct intf_hdl *pintf = &(pio_q->intf); 1562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct intf_priv *pintfpriv = pintf->pintfpriv; 1572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)pintf->adapter; 1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (purb->status != 0) { 1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (purb->status == (-ESHUTDOWN)) 1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->bDriverStopped = true; 1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->bSurpriseRemoved = true; 1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger up(&pintfpriv->io_retevt); 1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) 1692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int pipe; 1712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int status; 1722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter; 1732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct intf_priv *pintfpriv = pintfhdl->pintfpriv; 1742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct io_queue *pio_queue = (struct io_queue *)padapter->pio_queue; 1752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev; 1762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_device *pusbd = pdvobj->pusbdev; 1772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct urb *piorw_urb = pintfpriv->piorw_urb; 1782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) || 1802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (padapter->pwrctrlpriv.pnp_bstop_trx)) 1812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 1822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* translate DMA FIFO addr to pipehandle */ 1832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = ffaddr2pipehdl(pdvobj, addr); 1842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pipe == 0) 1852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 1862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_fill_bulk_urb(piorw_urb, pusbd, pipe, 1872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger wmem, cnt, usb_write_mem_complete, 1882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pio_queue); 189302d37a4b333d8252ba386554a90809833092cbaAli Bahar status = usb_submit_urb(piorw_urb, GFP_ATOMIC); 1902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _down_sema(&pintfpriv->io_retevt); 1912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void r8712_usb_read_port_complete(struct urb *purb) 1942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger uint isevt, *pbuf; 1962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_buf *precvbuf = (struct recv_buf *)purb->context; 1972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)precvbuf->adapter; 1982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_priv *precvpriv = &padapter->recvpriv; 1992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (padapter->bSurpriseRemoved || padapter->bDriverStopped) 2012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 2022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (purb->status == 0) { /* SUCCESS */ 2032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((purb->actual_length > (MAX_RECVBUF_SZ)) || 2042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (purb->actual_length < RXDESC_SIZE)) { 2052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = true; 2062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, 2072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (unsigned char *)precvbuf); 2082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 2092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->transfer_len = purb->actual_length; 2102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pbuf = (uint *)precvbuf->pbuf; 2112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff; 2122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((isevt & 0x1ff) == 0x1ff) { 2132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_rxcmd_event_hdl(padapter, pbuf); 2142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = true; 2152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_read_port(padapter, precvpriv->ff_hwaddr, 2162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0, (unsigned char *)precvbuf); 2172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 2182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _pkt *pskb = precvbuf->pskb; 2194eaef85670f347be2bf7431227fe2630598884a8Melike Yurtoglu 2202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb_put(pskb, purb->actual_length); 2212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb_queue_tail(&precvpriv->rx_skb_queue, pskb); 2222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tasklet_hi_schedule(&precvpriv->recv_tasklet); 2232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pskb = NULL; 2242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = false; 2252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_read_port(padapter, precvpriv->ff_hwaddr, 2262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 0, (unsigned char *)precvbuf); 2272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 2302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (purb->status) { 2312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -EINVAL: 2322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -EPIPE: 2332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -ENODEV: 2342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -ESHUTDOWN: 2352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -ENOENT: 2362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->bDriverStopped = true; 2372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -EPROTO: 2392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = true; 2402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, 2412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (unsigned char *)precvbuf); 2422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case -EINPROGRESS: 24487a573ada017b40facab87b149fcbb3344eab9e8Przemo Firszt netdev_err(padapter->pnetdev, "ERROR: URB IS IN PROGRESS!\n"); 2452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 2472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 2482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 2512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) 2532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 2542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int pipe; 2552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int err; 2562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 tmpaddr = 0; 2572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int alignment = 0; 2582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 ret = _SUCCESS; 2592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct urb *purb = NULL; 2602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_buf *precvbuf = (struct recv_buf *)rmem; 2612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct intf_priv *pintfpriv = pintfhdl->pintfpriv; 2622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev; 2632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *adapter = (struct _adapter *)pdvobj->padapter; 2642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_priv *precvpriv = &adapter->recvpriv; 2652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_device *pusbd = pdvobj->pusbdev; 2662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 2672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (adapter->bDriverStopped || adapter->bSurpriseRemoved || 2682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger adapter->pwrctrlpriv.pnp_bstop_trx) 2692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _FAIL; 2702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((precvbuf->reuse == false) || (precvbuf->pskb == NULL)) { 2712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); 2722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (NULL != precvbuf->pskb) 2732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = true; 2742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 2752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf != NULL) { 2762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_init_recvbuf(adapter, precvbuf); 2772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* re-assign for linux based on skb */ 2782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((precvbuf->reuse == false) || (precvbuf->pskb == NULL)) { 2792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, 2802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); 2812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->pskb == NULL) 2822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _FAIL; 2832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tmpaddr = (addr_t)precvbuf->pskb->data; 2842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1); 2852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb_reserve(precvbuf->pskb, 2862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (RECVBUFF_ALIGN_SZ - alignment)); 2872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->phead = precvbuf->pskb->head; 2882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pdata = precvbuf->pskb->data; 2892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); 2902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pend = skb_end_pointer(precvbuf->pskb); 2912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pbuf = precvbuf->pskb->data; 2922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { /* reuse skb */ 2932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->phead = precvbuf->pskb->head; 2942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pdata = precvbuf->pskb->data; 2952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); 2962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pend = skb_end_pointer(precvbuf->pskb); 2972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pbuf = precvbuf->pskb->data; 2982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = false; 2992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger purb = precvbuf->purb; 3012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* translate DMA FIFO addr to pipehandle */ 3022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = ffaddr2pipehdl(pdvobj, addr); 3032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_fill_bulk_urb(purb, pusbd, pipe, 3042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pbuf, MAX_RECVBUF_SZ, 3052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_usb_read_port_complete, 3062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf); 307302d37a4b333d8252ba386554a90809833092cbaAli Bahar err = usb_submit_urb(purb, GFP_ATOMIC); 3082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((err) && (err != (-EPERM))) 3092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ret = _FAIL; 3102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else 3112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ret = _FAIL; 3122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return ret; 3132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_usb_read_port_cancel(struct _adapter *padapter) 3162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int i; 3182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_buf *precvbuf; 3192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; 3212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < NR_RECVBUFF; i++) { 3222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->purb) 3232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_kill_urb(precvbuf->purb); 3242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf++; 3252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_xmit_bh(void *priv) 3292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int ret = false; 3312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)priv; 3322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 3332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 334ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar if ((padapter->bDriverStopped == true) || 335ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar (padapter->bSurpriseRemoved == true)) { 33687a573ada017b40facab87b149fcbb3344eab9e8Przemo Firszt netdev_err(padapter->pnetdev, "xmit_bh => bDriverStopped or bSurpriseRemoved\n"); 337ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar return; 3382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 339ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL); 340ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar if (ret == false) 341ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar return; 342ee5b1aadfd5cda257337a9b9777114a10c18c31eAli Bahar tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); 3432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void usb_write_port_complete(struct urb *purb) 3462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int i; 3482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe = (struct xmit_frame *)purb->context; 3492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; 3502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = pxmitframe->padapter; 3512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 3522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib = &pxmitframe->attrib; 3532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pattrib->priority) { 3552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 1: 3562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 2: 3572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->bkq_cnt--; 3582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 4: 3602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 5: 3612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->viq_cnt--; 3622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 6: 3642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 7: 3652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->voq_cnt--; 3662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 3682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 3: 3692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 3702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->beq_cnt--; 3712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->txirp_cnt--; 3742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < 8; i++) { 3752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (purb == pxmitframe->pxmit_urb[i]) { 3762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->bpending[i] = false; 3772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (padapter->bSurpriseRemoved) 3812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 3822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (purb->status) { 3832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 3842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 38657b6686ebbf55d3f44d02c72d0d87f5d12032a08Tapasweni Pathak netdev_warn(padapter->pnetdev, 38757b6686ebbf55d3f44d02c72d0d87f5d12032a08Tapasweni Pathak "r8712u: pipe error: (%d)\n", purb->status); 3882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 3892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 3902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* not to consider tx fragment */ 3912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); 3922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 3932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); 3942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 3952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 3962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingeru32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) 3972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 3982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned long irqL; 3992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int i, status; 4002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int pipe; 4012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u32 ret, bwritezero; 4022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct urb *purb = NULL; 4032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter; 4042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv; 4052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 4062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_frame *pxmitframe = (struct xmit_frame *)wmem; 4072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_device *pusbd = pdvobj->pusbdev; 4082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct pkt_attrib *pattrib = &pxmitframe->attrib; 4092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) || 4112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (padapter->pwrctrlpriv.pnp_bstop_trx)) 4122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _FAIL; 4132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < 8; i++) { 4142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitframe->bpending[i] == false) { 4152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger spin_lock_irqsave(&pxmitpriv->lock, irqL); 4162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->txirp_cnt++; 4172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->bpending[i] = true; 4182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger switch (pattrib->priority) { 4192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 1: 4202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 2: 4212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->bkq_cnt++; 4222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 4: 4242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 5: 4252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->viq_cnt++; 4262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 6: 4282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 7: 4292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->voq_cnt++; 4302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 0: 4322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger case 3: 4332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger default: 4342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitpriv->beq_cnt++; 4352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger spin_unlock_irqrestore(&pxmitpriv->lock, irqL); 4382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->sz[i] = (u16)cnt; 4392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger purb = pxmitframe->pxmit_urb[i]; 4402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger break; 4412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger bwritezero = false; 4442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pdvobj->ishighspeed) { 4452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (cnt > 0 && cnt % 512 == 0) 4462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger bwritezero = true; 4472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 4482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (cnt > 0 && cnt % 64 == 0) 4492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger bwritezero = true; 4502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* translate DMA FIFO addr to pipehandle */ 4522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = ffaddr2pipehdl(pdvobj, addr); 4532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0) 4542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger purb->transfer_flags &= (~URB_NO_INTERRUPT); 4552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 4562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger purb->transfer_flags |= URB_NO_INTERRUPT; 4572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (bwritezero) 4582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger cnt += 8; 4592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_fill_bulk_urb(purb, pusbd, pipe, 4602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe->mem_addr, 4612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger cnt, usb_write_port_complete, 4622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitframe); /* context is xmit_frame */ 463302d37a4b333d8252ba386554a90809833092cbaAli Bahar status = usb_submit_urb(purb, GFP_ATOMIC); 4642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (!status) 4652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ret = _SUCCESS; 4662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 4672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ret = _FAIL; 4682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return ret; 4692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 4702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_usb_write_port_cancel(struct _adapter *padapter) 4722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 4732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int i, j; 4742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct xmit_buf *pxmitbuf = (struct xmit_buf *) 4752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger padapter->xmitpriv.pxmitbuf; 4762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (i = 0; i < NR_XMITBUFF; i++) { 4782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger for (j = 0; j < 8; j++) { 4792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (pxmitbuf->pxmit_urb[j]) 4802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_kill_urb(pxmitbuf->pxmit_urb[j]); 4812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pxmitbuf++; 4832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 4842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 4852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 4862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, 4872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u16 index, void *pdata, u16 len, u8 requesttype) 4882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 4892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger unsigned int pipe; 4902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int status; 4912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 reqtype; 4922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *) 4932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pintfpriv->intf_dev; 4942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct usb_device *udev = pdvobjpriv->pusbdev; 4952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* For mstar platform, mstar suggests the address for USB IO 4962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * should be 16 bytes alignment. Trying to fix it here. 4972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */ 4982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger u8 *palloc_buf, *pIo_buf; 4992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 50091d435fe368ab30702d7bcd50f680e7185899295Vitaly Osipov palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC); 50115a4db9268f4090987cab4b2c40818291652607eTapasweni Pathak if (palloc_buf == NULL) 502735e33fa32d56e58dccb8406281efb2fff419f23Vitaly Osipov return -ENOMEM; 5032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f); 5042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (requesttype == 0x01) { 5052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_rcvctrlpipe(udev, 0); /* read_in */ 5062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger reqtype = RTL871X_VENQT_READ; 5072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } else { 5082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pipe = usb_sndctrlpipe(udev, 0); /* write_out */ 5092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger reqtype = RTL871X_VENQT_WRITE; 5102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(pIo_buf, pdata, len); 5112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger status = usb_control_msg(udev, pipe, request, reqtype, value, index, 5132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pIo_buf, len, HZ / 2); 5142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (status > 0) { /* Success this control transfer. */ 5152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (requesttype == 0x01) { 5162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /* For Control read transfer, we have to copy the read 5172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * data from pIo_buf to pdata. 5182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger */ 5192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(pdata, pIo_buf, status); 5202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 5222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger kfree(palloc_buf); 5232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return status; 5242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 525