2022-06-08 23:46:35 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* Copyright(c) 2007 - 2012 Realtek Corporation. */
|
|
|
|
|
2013-05-19 04:28:07 +00:00
|
|
|
#define _USB_OPS_LINUX_C_
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
#include "../include/drv_types.h"
|
|
|
|
#include "../include/usb_ops_linux.h"
|
|
|
|
#include "../include/rtl8188e_recv.h"
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
|
|
|
|
{
|
2013-08-12 02:47:28 +00:00
|
|
|
unsigned int pipe = 0, ep_num = 0;
|
2013-05-19 04:28:07 +00:00
|
|
|
struct usb_device *pusbd = pdvobj->pusbdev;
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
if (addr < HW_QUEUE_ENTRY) {
|
2013-05-19 04:28:07 +00:00
|
|
|
ep_num = pdvobj->Queue2Pipe[addr];
|
|
|
|
pipe = usb_sndbulkpipe(pusbd, ep_num);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pipe;
|
|
|
|
}
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
void rtw_read_port_cancel(struct adapter *padapter)
|
2013-05-19 04:28:07 +00:00
|
|
|
{
|
|
|
|
int i;
|
2022-06-08 23:46:35 +00:00
|
|
|
struct recv_buf *precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-05-26 03:02:10 +00:00
|
|
|
padapter->bReadPortCancel = true;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
for (i = 0; i < NR_RECVBUFF; i++) {
|
2013-05-26 03:02:10 +00:00
|
|
|
precvbuf->reuse = true;
|
2013-08-12 02:47:28 +00:00
|
|
|
if (precvbuf->purb)
|
2013-05-19 04:28:07 +00:00
|
|
|
usb_kill_urb(precvbuf->purb);
|
|
|
|
precvbuf++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
|
|
|
|
{
|
|
|
|
struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
|
2013-07-27 01:08:39 +00:00
|
|
|
struct adapter *padapter = pxmitbuf->padapter;
|
2013-07-20 22:33:31 +00:00
|
|
|
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-07-20 22:33:31 +00:00
|
|
|
switch (pxmitbuf->flags) {
|
|
|
|
case VO_QUEUE_INX:
|
|
|
|
pxmitpriv->voq_cnt--;
|
|
|
|
break;
|
|
|
|
case VI_QUEUE_INX:
|
|
|
|
pxmitpriv->viq_cnt--;
|
|
|
|
break;
|
|
|
|
case BE_QUEUE_INX:
|
|
|
|
pxmitpriv->beq_cnt--;
|
|
|
|
break;
|
|
|
|
case BK_QUEUE_INX:
|
|
|
|
pxmitpriv->bkq_cnt--;
|
|
|
|
break;
|
|
|
|
case HIGH_QUEUE_INX:
|
|
|
|
rtw_chk_hi_queue_cmd(padapter);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2013-05-19 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
|
2022-06-08 23:46:35 +00:00
|
|
|
padapter->bWritePortCancel)
|
2013-05-19 04:28:07 +00:00
|
|
|
goto check_completion;
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
if (purb->status) {
|
2022-06-08 23:46:35 +00:00
|
|
|
if (purb->status == -EINPROGRESS) {
|
2013-05-19 04:28:07 +00:00
|
|
|
goto check_completion;
|
|
|
|
} else if (purb->status == -ENOENT) {
|
|
|
|
goto check_completion;
|
|
|
|
} else if (purb->status == -ECONNRESET) {
|
|
|
|
goto check_completion;
|
|
|
|
} else if (purb->status == -ESHUTDOWN) {
|
2013-08-12 02:47:28 +00:00
|
|
|
padapter->bDriverStopped = true;
|
2013-05-19 04:28:07 +00:00
|
|
|
goto check_completion;
|
2022-06-08 23:46:35 +00:00
|
|
|
} else if ((purb->status != -EPIPE) && (purb->status != -EPROTO)) {
|
2013-08-12 02:47:28 +00:00
|
|
|
padapter->bSurpriseRemoved = true;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
goto check_completion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
check_completion:
|
|
|
|
rtw_sctx_done_err(&pxmitbuf->sctx,
|
2013-08-12 02:47:28 +00:00
|
|
|
purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
|
|
|
|
RTW_SCTX_DONE_SUCCESS);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
u32 rtw_write_port(struct adapter *padapter, u32 addr, u32 cnt, u8 *wmem)
|
2013-05-19 04:28:07 +00:00
|
|
|
{
|
2013-07-24 03:39:20 +00:00
|
|
|
unsigned long irqL;
|
2013-05-19 04:28:07 +00:00
|
|
|
unsigned int pipe;
|
|
|
|
int status;
|
2013-10-19 17:45:47 +00:00
|
|
|
u32 ret = _FAIL;
|
2013-08-12 02:47:28 +00:00
|
|
|
struct urb *purb = NULL;
|
2013-05-19 04:28:07 +00:00
|
|
|
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
|
|
|
|
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
|
|
|
struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
|
|
|
|
struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
|
|
|
|
struct usb_device *pusbd = pdvobj->pusbdev;
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
|
|
|
|
(padapter->pwrctrlpriv.pnp_bstop_trx)) {
|
2013-05-19 04:28:07 +00:00
|
|
|
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2014-11-28 23:37:57 +00:00
|
|
|
spin_lock_irqsave(&pxmitpriv->lock, irqL);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
switch (addr) {
|
|
|
|
case VO_QUEUE_INX:
|
|
|
|
pxmitpriv->voq_cnt++;
|
|
|
|
pxmitbuf->flags = VO_QUEUE_INX;
|
|
|
|
break;
|
|
|
|
case VI_QUEUE_INX:
|
|
|
|
pxmitpriv->viq_cnt++;
|
|
|
|
pxmitbuf->flags = VI_QUEUE_INX;
|
|
|
|
break;
|
|
|
|
case BE_QUEUE_INX:
|
|
|
|
pxmitpriv->beq_cnt++;
|
|
|
|
pxmitbuf->flags = BE_QUEUE_INX;
|
|
|
|
break;
|
|
|
|
case BK_QUEUE_INX:
|
|
|
|
pxmitpriv->bkq_cnt++;
|
|
|
|
pxmitbuf->flags = BK_QUEUE_INX;
|
|
|
|
break;
|
|
|
|
case HIGH_QUEUE_INX:
|
|
|
|
pxmitbuf->flags = HIGH_QUEUE_INX;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pxmitbuf->flags = MGT_QUEUE_INX;
|
|
|
|
break;
|
2013-05-19 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:37:57 +00:00
|
|
|
spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
purb = pxmitbuf->pxmit_urb[0];
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
/* translate DMA FIFO addr to pipehandle */
|
2013-05-19 04:28:07 +00:00
|
|
|
pipe = ffaddr2pipehdl(pdvobj, addr);
|
|
|
|
|
|
|
|
usb_fill_bulk_urb(purb, pusbd, pipe,
|
2013-08-12 02:47:28 +00:00
|
|
|
pxmitframe->buf_addr, /* pxmitbuf->pbuf */
|
|
|
|
cnt,
|
|
|
|
usb_write_port_complete,
|
|
|
|
pxmitbuf);/* context is pxmitbuf */
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
status = usb_submit_urb(purb, GFP_ATOMIC);
|
2022-06-08 23:46:35 +00:00
|
|
|
if (status) {
|
2013-05-19 04:28:07 +00:00
|
|
|
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case -ENODEV:
|
2013-08-12 02:47:28 +00:00
|
|
|
padapter->bDriverStopped = true;
|
2013-05-19 04:28:07 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
ret = _SUCCESS;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
/* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
exit:
|
|
|
|
if (ret != _SUCCESS)
|
|
|
|
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
|
2014-12-01 22:31:15 +00:00
|
|
|
|
2013-05-19 04:28:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
void rtw_write_port_cancel(struct adapter *padapter)
|
2013-05-19 04:28:07 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
|
|
|
|
|
2013-05-26 03:02:10 +00:00
|
|
|
padapter->bWritePortCancel = true;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
for (i = 0; i < NR_XMITBUFF; i++) {
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
if (pxmitbuf->pxmit_urb[j])
|
2013-05-19 04:28:07 +00:00
|
|
|
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
|
|
|
|
}
|
|
|
|
pxmitbuf++;
|
|
|
|
}
|
|
|
|
|
2013-08-12 02:47:28 +00:00
|
|
|
pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
|
2013-05-19 04:28:07 +00:00
|
|
|
for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
|
2013-08-12 02:47:28 +00:00
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
if (pxmitbuf->pxmit_urb[j])
|
2013-05-19 04:28:07 +00:00
|
|
|
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
|
|
|
|
}
|
|
|
|
pxmitbuf++;
|
|
|
|
}
|
|
|
|
}
|