2022-06-08 23:46:35 +00:00
|
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
/* Copyright(c) 2007 - 2011 Realtek Corporation. */
|
|
|
|
|
|
|
|
|
|
#include "../include/osdep_service.h"
|
|
|
|
|
#include "../include/drv_types.h"
|
|
|
|
|
#include "../include/osdep_intf.h"
|
|
|
|
|
#include "../include/usb_ops.h"
|
|
|
|
|
#include "../include/recv_osdep.h"
|
|
|
|
|
#include "../include/rtl8188e_hal.h"
|
|
|
|
|
|
|
|
|
|
static int usb_read(struct intf_hdl *intf, u16 value, void *data, u8 size)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct adapter *adapt = intf->padapter;
|
|
|
|
|
struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct usb_device *udev = dvobjpriv->pusbdev;
|
2022-06-08 23:46:35 +00:00
|
|
|
|
int status;
|
|
|
|
|
u8 io_buf[4];
|
|
|
|
|
|
|
|
|
|
if (adapt->bSurpriseRemoved || adapt->pwrctrlpriv.pnp_bstop_trx)
|
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
|
|
status = usb_control_msg_recv(udev, 0, REALTEK_USB_VENQT_CMD_REQ,
|
|
|
|
|
REALTEK_USB_VENQT_READ, value,
|
|
|
|
|
REALTEK_USB_VENQT_CMD_IDX, io_buf,
|
|
|
|
|
size, RTW_USB_CONTROL_MSG_TIMEOUT,
|
|
|
|
|
GFP_KERNEL);
|
|
|
|
|
|
|
|
|
|
if (status == -ESHUTDOWN ||
|
|
|
|
|
status == -ENODEV ||
|
|
|
|
|
status == -ENOENT) {
|
|
|
|
|
/*
|
|
|
|
|
* device or controller has been disabled due to
|
|
|
|
|
* some problem that could not be worked around,
|
|
|
|
|
* device or bus doesn’t exist, endpoint does not
|
|
|
|
|
* exist or is not enabled.
|
|
|
|
|
*/
|
|
|
|
|
adapt->bSurpriseRemoved = true;
|
|
|
|
|
return status;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
}
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (status < 0) {
|
|
|
|
|
if (rtw_inc_and_chk_continual_urb_error(dvobjpriv))
|
|
|
|
|
adapt->bSurpriseRemoved = true;
|
|
|
|
|
|
|
|
|
|
return status;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
}
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_reset_continual_urb_error(dvobjpriv);
|
|
|
|
|
memcpy(data, io_buf, size);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
static int usb_write(struct intf_hdl *intf, u16 value, void *data, u8 size)
|
|
|
|
|
{
|
|
|
|
|
struct adapter *adapt = intf->padapter;
|
|
|
|
|
struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
|
|
|
|
|
struct usb_device *udev = dvobjpriv->pusbdev;
|
|
|
|
|
int status;
|
|
|
|
|
u8 io_buf[VENDOR_CMD_MAX_DATA_LEN];
|
|
|
|
|
|
|
|
|
|
if (adapt->bSurpriseRemoved || adapt->pwrctrlpriv.pnp_bstop_trx)
|
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
|
|
memcpy(io_buf, data, size);
|
|
|
|
|
status = usb_control_msg_send(udev, 0, REALTEK_USB_VENQT_CMD_REQ,
|
|
|
|
|
REALTEK_USB_VENQT_WRITE, value,
|
|
|
|
|
REALTEK_USB_VENQT_CMD_IDX, io_buf,
|
|
|
|
|
size, RTW_USB_CONTROL_MSG_TIMEOUT,
|
|
|
|
|
GFP_KERNEL);
|
|
|
|
|
|
|
|
|
|
if (status == -ESHUTDOWN ||
|
|
|
|
|
status == -ENODEV ||
|
|
|
|
|
status == -ENOENT) {
|
|
|
|
|
/*
|
|
|
|
|
* device or controller has been disabled due to
|
|
|
|
|
* some problem that could not be worked around,
|
|
|
|
|
* device or bus doesn’t exist, endpoint does not
|
|
|
|
|
* exist or is not enabled.
|
|
|
|
|
*/
|
|
|
|
|
adapt->bSurpriseRemoved = true;
|
|
|
|
|
return status;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (status < 0) {
|
|
|
|
|
if (rtw_inc_and_chk_continual_urb_error(dvobjpriv))
|
|
|
|
|
adapt->bSurpriseRemoved = true;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_reset_continual_urb_error(dvobjpriv);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-05-08 21:45:39 +00:00
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
u8 rtw_read8(struct adapter *adapter, u32 addr)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
|
|
|
|
u8 data;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
usb_read(intf, value, &data, 1);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
u16 rtw_read16(struct adapter *adapter, u32 addr)
|
2013-05-19 04:28:07 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
|
|
|
|
__le16 data;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
usb_read(intf, value, &data, 2);
|
2014-12-01 22:31:15 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return le16_to_cpu(data);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
u32 rtw_read32(struct adapter *adapter, u32 addr)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
2013-07-09 22:40:50 +00:00
|
|
|
|
__le32 data;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
usb_read(intf, value, &data, 4);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-07-09 22:40:50 +00:00
|
|
|
|
return le32_to_cpu(data);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
int rtw_write8(struct adapter *adapter, u32 addr, u8 val)
|
2013-05-19 04:28:07 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
int ret;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
ret = usb_write(intf, value, &val, 1);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return RTW_STATUS_CODE(ret);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
int rtw_write16(struct adapter *adapter, u32 addr, u16 val)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
|
|
|
|
__le16 data = cpu_to_le16(val);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
int ret;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
ret = usb_write(intf, value, &data, 2);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return RTW_STATUS_CODE(ret);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
int rtw_write32(struct adapter *adapter, u32 addr, u32 val)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
|
|
|
|
__le32 data = cpu_to_le32(val);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
int ret;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
ret = usb_write(intf, value, &data, 4);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return RTW_STATUS_CODE(ret);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
int rtw_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *data)
|
2013-05-19 04:28:07 +00:00
|
|
|
|
{
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct io_priv *io_priv = &adapter->iopriv;
|
|
|
|
|
struct intf_hdl *intf = &io_priv->intf;
|
|
|
|
|
u16 value = addr & 0xffff;
|
|
|
|
|
int ret;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (length > VENDOR_CMD_MAX_DATA_LEN)
|
|
|
|
|
return _FAIL;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
ret = usb_write(intf, value, data, length);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
return RTW_STATUS_CODE(ret);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
|
|
|
|
u8 *pbuf;
|
|
|
|
|
u8 shift_sz = 0;
|
|
|
|
|
u16 pkt_cnt;
|
|
|
|
|
u32 pkt_offset, skb_len, alloc_sz;
|
|
|
|
|
s32 transfer_len;
|
|
|
|
|
struct recv_stat *prxstat;
|
|
|
|
|
struct phy_stat *pphy_status = NULL;
|
2013-07-24 22:03:54 +00:00
|
|
|
|
struct sk_buff *pkt_copy = NULL;
|
2014-12-13 16:35:48 +00:00
|
|
|
|
struct recv_frame *precvframe = NULL;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
struct rx_pkt_attrib *pattrib = NULL;
|
2022-06-08 23:46:35 +00:00
|
|
|
|
struct hal_data_8188e *haldata = &adapt->haldata;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct recv_priv *precvpriv = &adapt->recvpriv;
|
2013-07-24 22:55:38 +00:00
|
|
|
|
struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-05-19 04:28:07 +00:00
|
|
|
|
transfer_len = (s32)pskb->len;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
pbuf = pskb->data;
|
|
|
|
|
|
2013-05-19 04:28:07 +00:00
|
|
|
|
prxstat = (struct recv_stat *)pbuf;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
do {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
prxstat = (struct recv_stat *)pbuf;
|
|
|
|
|
|
|
|
|
|
precvframe = rtw_alloc_recvframe(pfree_recv_queue);
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (!precvframe)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
goto _exit_recvbuf2recvframe;
|
|
|
|
|
|
2014-12-13 16:35:48 +00:00
|
|
|
|
INIT_LIST_HEAD(&precvframe->list);
|
|
|
|
|
precvframe->precvbuf = NULL; /* can't access the precvbuf for new arch. */
|
|
|
|
|
precvframe->len = 0;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
|
|
|
|
update_recvframe_attrib_88e(precvframe, prxstat);
|
|
|
|
|
|
2014-12-13 16:35:48 +00:00
|
|
|
|
pattrib = &precvframe->attrib;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((pattrib->crc_err) || (pattrib->icv_err)) {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
rtw_free_recvframe(precvframe, pfree_recv_queue);
|
|
|
|
|
goto _exit_recvbuf2recvframe;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
|
2013-05-08 21:45:39 +00:00
|
|
|
|
pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
|
|
|
|
|
|
|
|
|
|
pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
rtw_free_recvframe(precvframe, pfree_recv_queue);
|
|
|
|
|
goto _exit_recvbuf2recvframe;
|
|
|
|
|
}
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
/* Modified by Albert 20101213 */
|
|
|
|
|
/* For 8 bytes IP header alignment. */
|
|
|
|
|
if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
|
2013-05-08 21:45:39 +00:00
|
|
|
|
shift_sz = 6;
|
|
|
|
|
else
|
|
|
|
|
shift_sz = 0;
|
|
|
|
|
|
|
|
|
|
skb_len = pattrib->pkt_len;
|
|
|
|
|
|
2013-07-10 18:25:07 +00:00
|
|
|
|
/* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
|
|
|
|
|
/* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
|
2013-05-09 04:04:25 +00:00
|
|
|
|
if (skb_len <= 1650)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
alloc_sz = 1664;
|
|
|
|
|
else
|
|
|
|
|
alloc_sz = skb_len + 14;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
} else {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
alloc_sz = skb_len;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
|
|
|
|
|
/* 8 is for skb->data 4 bytes alignment. */
|
2013-05-08 21:45:39 +00:00
|
|
|
|
alloc_sz += 14;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
|
|
|
|
|
if (pkt_copy) {
|
|
|
|
|
pkt_copy->dev = adapt->pnetdev;
|
2014-12-13 16:35:48 +00:00
|
|
|
|
precvframe->pkt = pkt_copy;
|
|
|
|
|
precvframe->rx_head = pkt_copy->data;
|
|
|
|
|
precvframe->rx_end = pkt_copy->data + alloc_sz;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
|
|
|
|
|
skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
|
2013-10-19 17:45:47 +00:00
|
|
|
|
memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
|
2014-12-13 16:35:48 +00:00
|
|
|
|
precvframe->rx_tail = pkt_copy->data;
|
|
|
|
|
precvframe->rx_data = pkt_copy->data;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
} else {
|
|
|
|
|
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
rtw_free_recvframe(precvframe, pfree_recv_queue);
|
|
|
|
|
goto _exit_recvbuf2recvframe;
|
|
|
|
|
}
|
2014-12-13 16:35:48 +00:00
|
|
|
|
precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
|
|
|
|
|
if (precvframe->pkt) {
|
|
|
|
|
precvframe->rx_tail = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE;
|
|
|
|
|
precvframe->rx_head = precvframe->rx_tail;
|
|
|
|
|
precvframe->rx_data = precvframe->rx_tail;
|
|
|
|
|
precvframe->rx_end = pbuf + pattrib->drvinfo_sz + RXDESC_SIZE + alloc_sz;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
} else {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
rtw_free_recvframe(precvframe, pfree_recv_queue);
|
|
|
|
|
goto _exit_recvbuf2recvframe;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
recvframe_put(precvframe, skb_len);
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
pkt_offset = (u16)_RND128(pkt_offset);
|
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
|
2013-07-12 03:50:49 +00:00
|
|
|
|
if (pattrib->physt)
|
2013-08-09 03:23:49 +00:00
|
|
|
|
update_recvframe_phyinfo_88e(precvframe, (struct phy_stat *)pphy_status);
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_recv_entry(precvframe);
|
2013-07-22 19:47:05 +00:00
|
|
|
|
} else {
|
2013-07-10 18:25:07 +00:00
|
|
|
|
/* enqueue recvframe to txrtp queue */
|
2013-07-22 19:47:05 +00:00
|
|
|
|
if (pattrib->pkt_rpt_type == TX_REPORT1) {
|
2013-07-10 18:25:07 +00:00
|
|
|
|
/* CCX-TXRPT ack for xmit mgmt frames. */
|
2014-12-13 16:35:48 +00:00
|
|
|
|
handle_txrpt_ccx_88e(adapt, precvframe->rx_data);
|
2013-07-22 19:47:05 +00:00
|
|
|
|
} else if (pattrib->pkt_rpt_type == TX_REPORT2) {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
ODM_RA_TxRPT2Handle_8188E(
|
2013-08-09 03:23:49 +00:00
|
|
|
|
&haldata->odmpriv,
|
2014-12-13 16:35:48 +00:00
|
|
|
|
precvframe->rx_data,
|
2013-05-08 21:45:39 +00:00
|
|
|
|
pattrib->pkt_len,
|
|
|
|
|
pattrib->MacIDValidEntry[0],
|
|
|
|
|
pattrib->MacIDValidEntry[1]
|
|
|
|
|
);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
}
|
|
|
|
|
rtw_free_recvframe(precvframe, pfree_recv_queue);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
pkt_cnt--;
|
|
|
|
|
transfer_len -= pkt_offset;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
pbuf += pkt_offset;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
precvframe = NULL;
|
|
|
|
|
pkt_copy = NULL;
|
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
if (transfer_len > 0 && pkt_cnt == 0)
|
2022-06-08 23:46:35 +00:00
|
|
|
|
pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
} while ((transfer_len > 0) && (pkt_cnt > 0));
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
|
|
|
|
_exit_recvbuf2recvframe:
|
|
|
|
|
|
2013-05-19 04:28:07 +00:00
|
|
|
|
return _SUCCESS;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
void rtl8188eu_recv_tasklet(unsigned long priv)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
{
|
2013-07-24 22:03:54 +00:00
|
|
|
|
struct sk_buff *pskb;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct adapter *adapt = (struct adapter *)priv;
|
|
|
|
|
struct recv_priv *precvpriv = &adapt->recvpriv;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
|
2013-05-08 21:45:39 +00:00
|
|
|
|
dev_kfree_skb_any(pskb);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-08-09 03:23:49 +00:00
|
|
|
|
recvbuf2recvframe(adapt, pskb);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
skb_reset_tail_pointer(pskb);
|
|
|
|
|
pskb->len = 0;
|
|
|
|
|
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
|
|
|
|
|
{
|
2013-05-19 04:28:07 +00:00
|
|
|
|
struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct adapter *adapt = (struct adapter *)precvbuf->adapter;
|
|
|
|
|
struct recv_priv *precvpriv = &adapt->recvpriv;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
precvpriv->rx_pending_cnt--;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
|
2013-05-26 03:02:10 +00:00
|
|
|
|
precvbuf->reuse = true;
|
2014-12-01 22:31:15 +00:00
|
|
|
|
return;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (purb->status == 0) { /* SUCCESS */
|
2013-07-22 19:47:05 +00:00
|
|
|
|
if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
|
2013-05-26 03:02:10 +00:00
|
|
|
|
precvbuf->reuse = true;
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_read_port(adapt, (unsigned char *)precvbuf);
|
2013-07-22 19:47:05 +00:00
|
|
|
|
} else {
|
2013-08-09 03:23:49 +00:00
|
|
|
|
rtw_reset_continual_urb_error(adapter_to_dvobj(adapt));
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
|
|
|
|
skb_put(precvbuf->pskb, purb->actual_length);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
tasklet_schedule(&precvpriv->recv_tasklet);
|
|
|
|
|
|
|
|
|
|
precvbuf->pskb = NULL;
|
2013-05-26 03:02:10 +00:00
|
|
|
|
precvbuf->reuse = false;
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_read_port(adapt, (unsigned char *)precvbuf);
|
2013-05-19 04:28:07 +00:00
|
|
|
|
}
|
2013-07-22 19:47:05 +00:00
|
|
|
|
} else {
|
2013-11-29 22:10:20 +00:00
|
|
|
|
skb_put(precvbuf->pskb, purb->actual_length);
|
|
|
|
|
precvbuf->pskb = NULL;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt)))
|
|
|
|
|
adapt->bSurpriseRemoved = true;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-05-09 04:04:25 +00:00
|
|
|
|
switch (purb->status) {
|
2013-07-22 19:47:05 +00:00
|
|
|
|
case -EINVAL:
|
|
|
|
|
case -EPIPE:
|
|
|
|
|
case -ENODEV:
|
|
|
|
|
case -ESHUTDOWN:
|
|
|
|
|
case -ENOENT:
|
2013-08-09 03:23:49 +00:00
|
|
|
|
adapt->bDriverStopped = true;
|
2013-07-22 19:47:05 +00:00
|
|
|
|
break;
|
|
|
|
|
case -EPROTO:
|
|
|
|
|
case -EOVERFLOW:
|
|
|
|
|
precvbuf->reuse = true;
|
2022-06-08 23:46:35 +00:00
|
|
|
|
rtw_read_port(adapt, (unsigned char *)precvbuf);
|
2013-07-22 19:47:05 +00:00
|
|
|
|
break;
|
|
|
|
|
case -EINPROGRESS:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
2013-05-19 04:28:07 +00:00
|
|
|
|
}
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
u32 rtw_read_port(struct adapter *adapter, u8 *rmem)
|
2013-05-19 04:28:07 +00:00
|
|
|
|
{
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct urb *purb = NULL;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
struct recv_buf *precvbuf = (struct recv_buf *)rmem;
|
|
|
|
|
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
|
|
|
|
|
struct recv_priv *precvpriv = &adapter->recvpriv;
|
|
|
|
|
struct usb_device *pusbd = pdvobj->pusbdev;
|
2013-10-19 17:45:47 +00:00
|
|
|
|
int err;
|
|
|
|
|
unsigned int pipe;
|
|
|
|
|
size_t tmpaddr = 0;
|
|
|
|
|
size_t alignment = 0;
|
|
|
|
|
u32 ret = _SUCCESS;
|
2013-05-19 04:28:07 +00:00
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
|
2022-06-08 23:46:35 +00:00
|
|
|
|
adapter->pwrctrlpriv.pnp_bstop_trx)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
return _FAIL;
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (!precvbuf)
|
2013-11-29 22:10:20 +00:00
|
|
|
|
return _FAIL;
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (!precvbuf->reuse || !precvbuf->pskb) {
|
2013-08-09 03:23:49 +00:00
|
|
|
|
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
|
2022-06-08 23:46:35 +00:00
|
|
|
|
if (precvbuf->pskb)
|
2013-05-26 03:02:10 +00:00
|
|
|
|
precvbuf->reuse = true;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
/* re-assign for linux based on skb */
|
|
|
|
|
if (!precvbuf->reuse || !precvbuf->pskb) {
|
|
|
|
|
precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
|
|
|
|
|
if (!precvbuf->pskb)
|
|
|
|
|
return _FAIL;
|
|
|
|
|
|
|
|
|
|
tmpaddr = (size_t)precvbuf->pskb->data;
|
|
|
|
|
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
|
|
|
|
|
skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
|
|
|
|
|
} else { /* reuse skb */
|
|
|
|
|
precvbuf->reuse = false;
|
|
|
|
|
}
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
precvpriv->rx_pending_cnt++;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
purb = precvbuf->purb;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
/* translate DMA FIFO addr to pipehandle */
|
|
|
|
|
pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe);
|
2013-09-05 22:58:13 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
usb_fill_bulk_urb(purb, pusbd, pipe,
|
|
|
|
|
precvbuf->pskb->data,
|
|
|
|
|
MAX_RECVBUF_SZ,
|
|
|
|
|
usb_read_port_complete,
|
|
|
|
|
precvbuf);/* context is precvbuf */
|
2013-10-19 17:45:47 +00:00
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
err = usb_submit_urb(purb, GFP_ATOMIC);
|
|
|
|
|
if ((err) && (err != (-EPERM)))
|
|
|
|
|
ret = _FAIL;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-08 23:46:35 +00:00
|
|
|
|
void rtl8188eu_xmit_tasklet(unsigned long priv)
|
2013-05-19 04:28:07 +00:00
|
|
|
|
{
|
2013-05-26 03:02:10 +00:00
|
|
|
|
int ret = false;
|
2013-08-09 03:23:49 +00:00
|
|
|
|
struct adapter *adapt = (struct adapter *)priv;
|
|
|
|
|
struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
|
2013-05-08 21:45:39 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2013-07-22 19:47:05 +00:00
|
|
|
|
while (1) {
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if ((adapt->bDriverStopped) ||
|
|
|
|
|
(adapt->bSurpriseRemoved) ||
|
2022-06-08 23:46:35 +00:00
|
|
|
|
(adapt->bWritePortCancel))
|
2013-05-08 21:45:39 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
ret = rtl8188eu_xmitframe_complete(adapt, pxmitpriv, NULL);
|
2013-05-08 21:45:39 +00:00
|
|
|
|
|
2013-08-09 03:23:49 +00:00
|
|
|
|
if (!ret)
|
2013-05-08 21:45:39 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|