Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / os_dep / usb_ops_linux.c
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 (file)
index 0000000..0cdaef0
--- /dev/null
@@ -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 <drv_types.h>
+#include <usb_ops_linux.h>
+#include <rtw_sreset.h>
+
+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]);
+               }
+       }
+}