X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=kernel%2Fdrivers%2Fstaging%2Frtl8723au%2Fos_dep%2Fusb_ops_linux.c;fp=kernel%2Fdrivers%2Fstaging%2Frtl8723au%2Fos_dep%2Fusb_ops_linux.c;h=0cdaef0a8c24b2bd89935686bb68035bf42e84cb;hb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;hp=0000000000000000000000000000000000000000;hpb=98260f3884f4a202f9ca5eabed40b1354c489b29;p=kvmfornfv.git diff --git a/kernel/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/kernel/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c new file mode 100644 index 000000000..0cdaef0a8 --- /dev/null +++ b/kernel/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c @@ -0,0 +1,234 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + ******************************************************************************/ +#define _USB_OPS_LINUX_C_ + +#include +#include +#include + +void rtl8723au_read_port_cancel(struct rtw_adapter *padapter) +{ + struct recv_buf *precvbuf; + int i; + + precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; + + DBG_8723A("%s\n", __func__); + + padapter->bReadPortCancel = true; + + for (i = 0; i < NR_RECVBUFF ; i++) { + if (precvbuf->purb) + usb_kill_urb(precvbuf->purb); + precvbuf++; + } + usb_kill_urb(padapter->recvpriv.int_in_urb); +} + +static void usb_write_port23a_complete(struct urb *purb) +{ + struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; + struct rtw_adapter *padapter = pxmitbuf->padapter; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct hal_data_8723a *phaldata; + unsigned long irqL; + + switch (pxmitbuf->flags) { + case HIGH_QUEUE_INX: +#ifdef CONFIG_8723AU_AP_MODE + rtw_chk_hi_queue_cmd23a(padapter); +#endif + break; + default: + break; + } + + if (padapter->bSurpriseRemoved || padapter->bDriverStopped || + padapter->bWritePortCancel) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", + padapter->bDriverStopped, padapter->bSurpriseRemoved); + DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR " + "bSurpriseRemoved(%d) bWritePortCancel(%d) " + "pxmitbuf->ext_tag(%x)\n", __func__, + padapter->bDriverStopped, padapter->bSurpriseRemoved, + padapter->bReadPortCancel, pxmitbuf->ext_tag); + + goto check_completion; + } + + if (purb->status) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete : purb->status(%d) != 0\n", + purb->status); + DBG_8723A("###=> urb_write_port_complete status(%d)\n", + purb->status); + if (purb->status == -EPIPE || purb->status == -EPROTO) { + } else if (purb->status == -EINPROGRESS) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete: EINPROGESS\n"); + goto check_completion; + } else if (purb->status == -ENOENT) { + DBG_8723A("%s: -ENOENT\n", __func__); + goto check_completion; + } else if (purb->status == -ECONNRESET) { + DBG_8723A("%s: -ECONNRESET\n", __func__); + goto check_completion; + } else if (purb->status == -ESHUTDOWN) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete: ESHUTDOWN\n"); + padapter->bDriverStopped = true; + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete:bDriverStopped = true\n"); + goto check_completion; + } else { + padapter->bSurpriseRemoved = true; + DBG_8723A("bSurpriseRemoved = true\n"); + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a_complete:bSurpriseRemoved = true\n"); + goto check_completion; + } + } + phaldata = GET_HAL_DATA(padapter); + phaldata->srestpriv.last_tx_complete_time = jiffies; + +check_completion: + spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); + rtw23a_sctx_done_err(&pxmitbuf->sctx, + purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : + RTW_SCTX_DONE_SUCCESS); + spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); + + rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); + + tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); +} + +int rtl8723au_write_port(struct rtw_adapter *padapter, u32 addr, u32 cnt, + struct xmit_buf *pxmitbuf) +{ + struct urb *purb = NULL; + struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct xmit_frame *pxmitframe; + struct usb_device *pusbd = pdvobj->pusbdev; + unsigned long irqL; + unsigned int pipe, ep_num; + int status; + int ret = _FAIL; + + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "+usb_write_port23a\n"); + + if (padapter->bDriverStopped || padapter->bSurpriseRemoved) { + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "%s:(padapter->bDriverStopped || padapter->bSurpriseRemoved)!!!\n", + __func__); + rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY); + goto exit; + } + + pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data; + spin_lock_irqsave(&pxmitpriv->lock, irqL); + + switch (addr) { + case VO_QUEUE_INX: + pxmitbuf->flags = VO_QUEUE_INX; + break; + case VI_QUEUE_INX: + pxmitbuf->flags = VI_QUEUE_INX; + break; + case BE_QUEUE_INX: + pxmitbuf->flags = BE_QUEUE_INX; + break; + case BK_QUEUE_INX: + pxmitbuf->flags = BK_QUEUE_INX; + break; + case HIGH_QUEUE_INX: + pxmitbuf->flags = HIGH_QUEUE_INX; + break; + default: + pxmitbuf->flags = MGT_QUEUE_INX; + break; + } + + spin_unlock_irqrestore(&pxmitpriv->lock, irqL); + + purb = pxmitbuf->pxmit_urb[0]; + + /* translate DMA FIFO addr to pipehandle */ + ep_num = pdvobj->Queue2Pipe[addr]; + pipe = usb_sndbulkpipe(pusbd, ep_num); + + usb_fill_bulk_urb(purb, pusbd, pipe, + pxmitframe->buf_addr, /* pxmitbuf->pbuf */ + cnt, usb_write_port23a_complete, + pxmitbuf);/* context is pxmitbuf */ + + status = usb_submit_urb(purb, GFP_ATOMIC); + if (!status) { + struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter); + phaldata->srestpriv.last_tx_time = jiffies; + } else { + rtw23a_sctx_done_err(&pxmitbuf->sctx, + RTW_SCTX_DONE_WRITE_PORT_ERR); + DBG_8723A("usb_write_port23a, status =%d\n", status); + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, + "usb_write_port23a(): usb_submit_urb, status =%x\n", + status); + + switch (status) { + case -ENODEV: + padapter->bDriverStopped = true; + break; + default: + break; + } + goto exit; + } + ret = _SUCCESS; + RT_TRACE(_module_hci_ops_os_c_, _drv_err_, "-usb_write_port23a\n"); + +exit: + if (ret != _SUCCESS) + rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf); + + return ret; +} + +void rtl8723au_write_port_cancel(struct rtw_adapter *padapter) +{ + struct xmit_buf *pxmitbuf; + struct list_head *plist; + int j; + + DBG_8723A("%s\n", __func__); + + padapter->bWritePortCancel = true; + + list_for_each(plist, &padapter->xmitpriv.xmitbuf_list) { + pxmitbuf = container_of(plist, struct xmit_buf, list2); + for (j = 0; j < 8; j++) { + if (pxmitbuf->pxmit_urb[j]) + usb_kill_urb(pxmitbuf->pxmit_urb[j]); + } + } + list_for_each(plist, &padapter->xmitpriv.xmitextbuf_list) { + pxmitbuf = container_of(plist, struct xmit_buf, list2); + for (j = 0; j < 8; j++) { + if (pxmitbuf->pxmit_urb[j]) + usb_kill_urb(pxmitbuf->pxmit_urb[j]); + } + } +}