wireless-next patches for v6.2
Fourth set of patches for v6.2. Few final patches, a big change is that rtw88 now has USB support. Major changes: rtw88 * support USB devices rtw8821cu, rtw8822bu, rtw8822cu and rtw8723du -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmOW9EsRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZup1wf9EO1wK3M+wICOthV9hphaMK/cU5XQe455 V27N+IGg3KkeLgERYj/35C1Xwa4vXeUxWN31KvNJ/51IQaM14NfUE3OOu+gqUO36 a/HhECtcmzsjC+22hH1gvnN73/+S8VQEEfOJ//Jcg6exRmXVKRMWZU1o3rFupAR+ qePWzvYuadobmE8G/Zq2VFB5Eouf5z7MSXLd7Y/8HJMdL812GmA0nhNJXhHDt27A /K5QBOSnRQ24ZLOG4P0eFZrJGqFTcI27+w4bv+rzUL2ME/Rgp1hB7wBwQbCwD8sU Aus05avcIcVNfsTk3z7kOnYiBqf08WX6Ng6ezb9HunXXfWhLW7JtAw== =AzL1 -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Kalle Valo says: ==================== wireless-next patches for v6.2 Fourth set of patches for v6.2. Few final patches, a big change is that rtw88 now has USB support. Major changes: rtw88 * support USB devices rtw8821cu, rtw8822bu, rtw8822cu and rtw8723du * tag 'wireless-next-2022-12-12' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (43 commits) wifi: rtl8xxxu: fixing IQK failures for rtl8192eu wifi: rtlwifi: btcoexist: fix conditions branches that are never executed wifi: rtlwifi: rtl8192se: remove redundant rtl_get_bbreg() call wifi: rtw88: Add rtw8723du chipset support wifi: rtw88: Add rtw8822cu chipset support wifi: rtw88: Add rtw8822bu chipset support wifi: rtw88: Add rtw8821cu chipset support wifi: rtw88: Add common USB chip support wifi: rtw88: iterate over vif/sta list non-atomically wifi: rtw88: Drop coex mutex wifi: rtw88: Drop h2c.lock wifi: rtw88: Drop rf_lock wifi: rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held wifi: rtw88: print firmware type in info message wifi: rtw89: add join info upon create interface wifi: rtw89: fix unsuccessful interface_add flow wifi: rtw89: stop mac port function when stop_ap() wifi: rtw89: add mac TSF sync function wifi: rtw89: request full firmware only once if it's early requested wifi: rtw89: don't request partial firmware if SECURITY_LOADPIN_ENFORCE ... ==================== Link: https://lore.kernel.org/r/20221212093026.5C5AEC433D2@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
fba119cee1
|
@ -20,6 +20,7 @@ brcmfmac-objs += \
|
|||
common.o \
|
||||
core.o \
|
||||
firmware.o \
|
||||
fwvid.o \
|
||||
feature.o \
|
||||
btcoex.o \
|
||||
vendor.o \
|
||||
|
@ -47,3 +48,13 @@ brcmfmac-$(CONFIG_OF) += \
|
|||
of.o
|
||||
brcmfmac-$(CONFIG_DMI) += \
|
||||
dmi.o
|
||||
|
||||
ifeq ($(CONFIG_BRCMFMAC),m)
|
||||
obj-m += wcc/
|
||||
obj-m += cyw/
|
||||
obj-m += bca/
|
||||
else
|
||||
brcmfmac-$(CONFIG_BRCMFMAC) += wcc/core.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC) += cyw/core.o
|
||||
brcmfmac-$(CONFIG_BRCMFMAC) += bca/core.o
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
#
|
||||
# Copyright (c) 2022 Broadcom Corporation
|
||||
|
||||
ccflags-y += \
|
||||
-I $(srctree)/$(src) \
|
||||
-I $(srctree)/$(src)/.. \
|
||||
-I $(srctree)/$(src)/../../include
|
||||
|
||||
obj-m += brcmfmac-bca.o
|
||||
brcmfmac-bca-objs += \
|
||||
core.o module.o
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <core.h>
|
||||
#include <bus.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int brcmf_bca_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_bca_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
}
|
||||
|
||||
const struct brcmf_fwvid_ops brcmf_bca_ops = {
|
||||
.attach = brcmf_bca_attach,
|
||||
.detach = brcmf_bca_detach,
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <bus.h>
|
||||
#include <core.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int __init brcmf_bca_init(void)
|
||||
{
|
||||
return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE,
|
||||
&brcmf_bca_ops);
|
||||
}
|
||||
|
||||
static void __exit brcmf_bca_exit(void)
|
||||
{
|
||||
brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(BRCMFMAC);
|
||||
|
||||
module_init(brcmf_bca_init);
|
||||
module_exit(brcmf_bca_exit);
|
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#ifndef _BRCMFMAC_BCA_VOPS_H
|
||||
#define _BRCMFMAC_BCA_VOPS_H
|
||||
|
||||
extern const struct brcmf_fwvid_ops brcmf_bca_ops;
|
||||
#define BCA_VOPS (&brcmf_bca_ops)
|
||||
|
||||
#endif /* _BRCMFMAC_BCA_VOPS_H */
|
|
@ -959,33 +959,36 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define BRCMF_SDIO_DEVICE(dev_id) \
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, dev_id)}
|
||||
#define BRCMF_SDIO_DEVICE(dev_id, fw_vend) \
|
||||
{ \
|
||||
SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, dev_id), \
|
||||
.driver_data = BRCMF_FWVENDOR_ ## fw_vend \
|
||||
}
|
||||
|
||||
/* devices we support, null terminated */
|
||||
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43143),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43241),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4329),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4330),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4334),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43143, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43241, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4329, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4330, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4334, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
|
||||
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||
|
@ -1051,6 +1054,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
|||
sdiodev->bus_if = bus_if;
|
||||
bus_if->bus_priv.sdio = sdiodev;
|
||||
bus_if->proto_type = BRCMF_PROTO_BCDC;
|
||||
bus_if->fwvid = id->driver_data;
|
||||
dev_set_drvdata(&func->dev, bus_if);
|
||||
dev_set_drvdata(&sdiodev->func1->dev, bus_if);
|
||||
sdiodev->dev = &sdiodev->func1->dev;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/device.h>
|
||||
#include "debug.h"
|
||||
|
||||
/* IDs of the 6 default common rings of msgbuf protocol */
|
||||
|
@ -30,6 +31,15 @@
|
|||
/* The maximum console interval value (5 mins) */
|
||||
#define MAX_CONSOLE_INTERVAL (5 * 60)
|
||||
|
||||
enum brcmf_fwvendor {
|
||||
BRCMF_FWVENDOR_WCC,
|
||||
BRCMF_FWVENDOR_CYW,
|
||||
BRCMF_FWVENDOR_BCA,
|
||||
/* keep last */
|
||||
BRCMF_FWVENDOR_NUM,
|
||||
BRCMF_FWVENDOR_INVALID
|
||||
};
|
||||
|
||||
/* The level of bus communication with the dongle */
|
||||
enum brcmf_bus_state {
|
||||
BRCMF_BUS_DOWN, /* Not ready for frame transfers */
|
||||
|
@ -74,6 +84,7 @@ struct brcmf_bus_dcmd {
|
|||
* @get_ramsize: obtain size of device memory.
|
||||
* @get_memdump: obtain device memory dump in provided buffer.
|
||||
* @get_blob: obtain a firmware blob.
|
||||
* @remove: initiate unbind of the device.
|
||||
*
|
||||
* This structure provides an abstract interface towards the
|
||||
* bus specific driver. For control messages to common driver
|
||||
|
@ -94,6 +105,7 @@ struct brcmf_bus_ops {
|
|||
enum brcmf_blob_type type);
|
||||
void (*debugfs_create)(struct device *dev);
|
||||
int (*reset)(struct device *dev);
|
||||
void (*remove)(struct device *dev);
|
||||
};
|
||||
|
||||
|
||||
|
@ -141,10 +153,13 @@ struct brcmf_bus_stats {
|
|||
* @stats: statistics shared between common and bus layer.
|
||||
* @maxctl: maximum size for rxctl request message.
|
||||
* @chip: device identifier of the dongle chip.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
* @fwvid: firmware vendor-support identifier of the device.
|
||||
* @always_use_fws_queue: bus wants use queue also when fwsignal is inactive.
|
||||
* @wowl_supported: is wowl supported by bus driver.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
* @ops: callbacks for this bus instance.
|
||||
* @msgbuf: msgbuf protocol parameters provided by bus layer.
|
||||
* @list: member used to add this bus instance to linked list.
|
||||
*/
|
||||
struct brcmf_bus {
|
||||
union {
|
||||
|
@ -160,11 +175,14 @@ struct brcmf_bus {
|
|||
uint maxctl;
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
enum brcmf_fwvendor fwvid;
|
||||
bool always_use_fws_queue;
|
||||
bool wowl_supported;
|
||||
|
||||
const struct brcmf_bus_ops *ops;
|
||||
struct brcmf_bus_msgbuf *msgbuf;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -257,6 +275,16 @@ int brcmf_bus_reset(struct brcmf_bus *bus)
|
|||
return bus->ops->reset(bus->dev);
|
||||
}
|
||||
|
||||
static inline void brcmf_bus_remove(struct brcmf_bus *bus)
|
||||
{
|
||||
if (!bus->ops->remove) {
|
||||
device_release_driver(bus->dev);
|
||||
return;
|
||||
}
|
||||
|
||||
bus->ops->remove(bus->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* interface functions from common layer
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "core.h"
|
||||
#include "bus.h"
|
||||
#include "fwvid.h"
|
||||
#include "debug.h"
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
|
@ -1135,7 +1136,8 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
|
|||
seq_printf(s, "vendorid: 0x%04x\n", ri->vendorid);
|
||||
seq_printf(s, "deviceid: 0x%04x\n", ri->deviceid);
|
||||
seq_printf(s, "radiorev: %s\n", brcmu_dotrev_str(ri->radiorev, drev));
|
||||
seq_printf(s, "chip: %s\n", ri->chipname);
|
||||
seq_printf(s, "chip: %s (%s)\n", ri->chipname,
|
||||
brcmf_fwvid_vendor_name(bus_if->drvr));
|
||||
seq_printf(s, "chippkg: %u\n", ri->chippkg);
|
||||
seq_printf(s, "corerev: %u\n", ri->corerev);
|
||||
seq_printf(s, "boardid: 0x%04x\n", ri->boardid);
|
||||
|
@ -1332,6 +1334,12 @@ int brcmf_attach(struct device *dev)
|
|||
/* Link to bus module */
|
||||
drvr->hdrlen = 0;
|
||||
|
||||
ret = brcmf_fwvid_attach(drvr);
|
||||
if (ret != 0) {
|
||||
bphy_err(drvr, "brcmf_fwvid_attach failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Attach and link in the protocol */
|
||||
ret = brcmf_proto_attach(drvr);
|
||||
if (ret != 0) {
|
||||
|
@ -1443,6 +1451,8 @@ void brcmf_detach(struct device *dev)
|
|||
brcmf_cfg80211_detach(drvr->config);
|
||||
drvr->config = NULL;
|
||||
}
|
||||
|
||||
brcmf_fwvid_detach(drvr);
|
||||
}
|
||||
|
||||
void brcmf_free(struct device *dev)
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
#include <net/cfg80211.h>
|
||||
#include "fweh.h"
|
||||
|
||||
#if IS_MODULE(CONFIG_BRCMFMAC)
|
||||
#define BRCMF_EXPORT_SYMBOL_GPL(__sym) EXPORT_SYMBOL_NS_GPL(__sym, BRCMFMAC)
|
||||
#else
|
||||
#define BRCMF_EXPORT_SYMBOL_GPL(__sym)
|
||||
#endif
|
||||
|
||||
#define TOE_TX_CSUM_OL 0x00000001
|
||||
#define TOE_RX_CSUM_OL 0x00000002
|
||||
|
||||
|
@ -137,6 +143,8 @@ struct brcmf_pub {
|
|||
|
||||
u8 clmver[BRCMF_DCMD_SMLEN];
|
||||
u8 sta_mac_idx;
|
||||
const struct brcmf_fwvid_ops *vops;
|
||||
void *vdata;
|
||||
};
|
||||
|
||||
/* forward declarations */
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
#
|
||||
# Copyright (c) 2022 Broadcom Corporation
|
||||
|
||||
ccflags-y += \
|
||||
-I $(srctree)/$(src) \
|
||||
-I $(srctree)/$(src)/.. \
|
||||
-I $(srctree)/$(src)/../../include
|
||||
|
||||
obj-m += brcmfmac-cyw.o
|
||||
brcmfmac-cyw-objs += \
|
||||
core.o module.o
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <core.h>
|
||||
#include <bus.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int brcmf_cyw_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_cyw_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
}
|
||||
|
||||
const struct brcmf_fwvid_ops brcmf_cyw_ops = {
|
||||
.attach = brcmf_cyw_attach,
|
||||
.detach = brcmf_cyw_detach,
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <bus.h>
|
||||
#include <core.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int __init brcmf_cyw_init(void)
|
||||
{
|
||||
return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE,
|
||||
&brcmf_cyw_ops);
|
||||
}
|
||||
|
||||
static void __exit brcmf_cyw_exit(void)
|
||||
{
|
||||
brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(BRCMFMAC);
|
||||
|
||||
module_init(brcmf_cyw_init);
|
||||
module_exit(brcmf_cyw_exit);
|
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#ifndef _BRCMFMAC_CYW_VOPS_H
|
||||
#define _BRCMFMAC_CYW_VOPS_H
|
||||
|
||||
extern const struct brcmf_fwvid_ops brcmf_cyw_ops;
|
||||
#define CYW_VOPS (&brcmf_cyw_ops)
|
||||
|
||||
#endif /* _BRCMFMAC_CYW_VOPS_H */
|
|
@ -0,0 +1,199 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "bus.h"
|
||||
#include "debug.h"
|
||||
#include "fwvid.h"
|
||||
|
||||
#include "wcc/vops.h"
|
||||
#include "cyw/vops.h"
|
||||
#include "bca/vops.h"
|
||||
|
||||
struct brcmf_fwvid_entry {
|
||||
const char *name;
|
||||
const struct brcmf_fwvid_ops *vops;
|
||||
struct list_head drvr_list;
|
||||
#if IS_MODULE(CONFIG_BRCMFMAC)
|
||||
struct module *vmod;
|
||||
struct completion reg_done;
|
||||
#endif
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(fwvid_list_lock);
|
||||
|
||||
#if IS_MODULE(CONFIG_BRCMFMAC)
|
||||
#define FWVID_ENTRY_INIT(_vid, _name) \
|
||||
[BRCMF_FWVENDOR_ ## _vid] = { \
|
||||
.name = #_name, \
|
||||
.reg_done = COMPLETION_INITIALIZER(fwvid_list[BRCMF_FWVENDOR_ ## _vid].reg_done), \
|
||||
.drvr_list = LIST_HEAD_INIT(fwvid_list[BRCMF_FWVENDOR_ ## _vid].drvr_list), \
|
||||
}
|
||||
#else
|
||||
#define FWVID_ENTRY_INIT(_vid, _name) \
|
||||
[BRCMF_FWVENDOR_ ## _vid] = { \
|
||||
.name = #_name, \
|
||||
.drvr_list = LIST_HEAD_INIT(fwvid_list[BRCMF_FWVENDOR_ ## _vid].drvr_list), \
|
||||
.vops = _vid ## _VOPS \
|
||||
}
|
||||
#endif /* IS_MODULE(CONFIG_BRCMFMAC) */
|
||||
|
||||
static struct brcmf_fwvid_entry fwvid_list[BRCMF_FWVENDOR_NUM] = {
|
||||
FWVID_ENTRY_INIT(WCC, wcc),
|
||||
FWVID_ENTRY_INIT(CYW, cyw),
|
||||
FWVID_ENTRY_INIT(BCA, bca),
|
||||
};
|
||||
|
||||
#if IS_MODULE(CONFIG_BRCMFMAC)
|
||||
static int brcmf_fwvid_request_module(enum brcmf_fwvendor fwvid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!fwvid_list[fwvid].vmod) {
|
||||
struct completion *reg_done = &fwvid_list[fwvid].reg_done;
|
||||
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
|
||||
ret = request_module("brcmfmac-%s", fwvid_list[fwvid].name);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = wait_for_completion_interruptible(reg_done);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
brcmf_err("mod=%s: failed %d\n", fwvid_list[fwvid].name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *vmod,
|
||||
const struct brcmf_fwvid_ops *vops)
|
||||
{
|
||||
if (fwvid >= BRCMF_FWVENDOR_NUM)
|
||||
return -ERANGE;
|
||||
|
||||
if (WARN_ON(!vmod) || WARN_ON(!vops) ||
|
||||
WARN_ON(!vops->attach) || WARN_ON(!vops->detach))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(fwvid_list[fwvid].vmod))
|
||||
return -EEXIST;
|
||||
|
||||
brcmf_dbg(TRACE, "mod=%s: enter\n", fwvid_list[fwvid].name);
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
|
||||
fwvid_list[fwvid].vmod = vmod;
|
||||
fwvid_list[fwvid].vops = vops;
|
||||
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
|
||||
complete_all(&fwvid_list[fwvid].reg_done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fwvid_register_vendor);
|
||||
|
||||
int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod)
|
||||
{
|
||||
struct brcmf_bus *bus, *tmp;
|
||||
|
||||
if (fwvid >= BRCMF_FWVENDOR_NUM)
|
||||
return -ERANGE;
|
||||
|
||||
if (WARN_ON(fwvid_list[fwvid].vmod != mod))
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
|
||||
list_for_each_entry_safe(bus, tmp, &fwvid_list[fwvid].drvr_list, list) {
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
|
||||
brcmf_dbg(INFO, "mod=%s: removing %s\n", fwvid_list[fwvid].name,
|
||||
dev_name(bus->dev));
|
||||
brcmf_bus_remove(bus);
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
}
|
||||
|
||||
fwvid_list[fwvid].vmod = NULL;
|
||||
fwvid_list[fwvid].vops = NULL;
|
||||
reinit_completion(&fwvid_list[fwvid].reg_done);
|
||||
|
||||
brcmf_dbg(TRACE, "mod=%s: exit\n", fwvid_list[fwvid].name);
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fwvid_unregister_vendor);
|
||||
#else
|
||||
static inline int brcmf_fwvid_request_module(enum brcmf_fwvendor fwvid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr)
|
||||
{
|
||||
enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid;
|
||||
int ret;
|
||||
|
||||
if (fwvid >= ARRAY_SIZE(fwvid_list))
|
||||
return -ERANGE;
|
||||
|
||||
brcmf_dbg(TRACE, "mod=%s: enter: dev %s\n", fwvid_list[fwvid].name,
|
||||
dev_name(drvr->bus_if->dev));
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
|
||||
ret = brcmf_fwvid_request_module(fwvid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drvr->vops = fwvid_list[fwvid].vops;
|
||||
list_add(&drvr->bus_if->list, &fwvid_list[fwvid].drvr_list);
|
||||
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr)
|
||||
{
|
||||
enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid;
|
||||
|
||||
if (fwvid >= ARRAY_SIZE(fwvid_list))
|
||||
return;
|
||||
|
||||
brcmf_dbg(TRACE, "mod=%s: enter: dev %s\n", fwvid_list[fwvid].name,
|
||||
dev_name(drvr->bus_if->dev));
|
||||
|
||||
mutex_lock(&fwvid_list_lock);
|
||||
|
||||
drvr->vops = NULL;
|
||||
list_del(&drvr->bus_if->list);
|
||||
|
||||
mutex_unlock(&fwvid_list_lock);
|
||||
}
|
||||
|
||||
const char *brcmf_fwvid_vendor_name(struct brcmf_pub *drvr)
|
||||
{
|
||||
return fwvid_list[drvr->bus_if->fwvid].name;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#ifndef FWVID_H_
|
||||
#define FWVID_H_
|
||||
|
||||
#include "firmware.h"
|
||||
|
||||
struct brcmf_pub;
|
||||
|
||||
struct brcmf_fwvid_ops {
|
||||
int (*attach)(struct brcmf_pub *drvr);
|
||||
void (*detach)(struct brcmf_pub *drvr);
|
||||
};
|
||||
|
||||
/* exported functions */
|
||||
int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *mod,
|
||||
const struct brcmf_fwvid_ops *ops);
|
||||
int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod);
|
||||
|
||||
/* core driver functions */
|
||||
int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr);
|
||||
void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr);
|
||||
const char *brcmf_fwvid_vendor_name(struct brcmf_pub *drvr);
|
||||
|
||||
static inline int brcmf_fwvid_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = brcmf_fwvid_attach_ops(drvr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return drvr->vops->attach(drvr);
|
||||
}
|
||||
|
||||
static inline void brcmf_fwvid_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
if (!drvr->vops)
|
||||
return;
|
||||
|
||||
drvr->vops->detach(drvr);
|
||||
brcmf_fwvid_detach_ops(drvr);
|
||||
}
|
||||
|
||||
#endif /* FWVID_H_ */
|
|
@ -736,7 +736,7 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
|
|||
}
|
||||
|
||||
if (!brcmf_chip_set_active(devinfo->ci, resetintr))
|
||||
return -EINVAL;
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2389,6 +2389,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
bus->bus_priv.pcie = pcie_bus_dev;
|
||||
bus->ops = &brcmf_pcie_bus_ops;
|
||||
bus->proto_type = BRCMF_PROTO_MSGBUF;
|
||||
bus->fwvid = id->driver_data;
|
||||
bus->chip = devinfo->coreid;
|
||||
bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
|
||||
dev_set_drvdata(&pdev->dev, bus);
|
||||
|
@ -2570,38 +2571,47 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = {
|
|||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
#define BRCMF_PCIE_DEVICE(dev_id) { BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
|
||||
PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
|
||||
#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev) { \
|
||||
BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
|
||||
subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
|
||||
#define BRCMF_PCIE_DEVICE(dev_id, fw_vend) \
|
||||
{ \
|
||||
BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
|
||||
PCI_ANY_ID, PCI_ANY_ID, \
|
||||
PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
|
||||
BRCMF_FWVENDOR_ ## fw_vend \
|
||||
}
|
||||
#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev, fw_vend) \
|
||||
{ \
|
||||
BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \
|
||||
(subvend), (subdev), \
|
||||
PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \
|
||||
BRCMF_FWVENDOR_ ## fw_vend \
|
||||
}
|
||||
|
||||
static const struct pci_device_id brcmf_pcie_devid_table[] = {
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_RAW_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_RAW_DEVICE_ID),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_RAW_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_DEVICE_ID, CYW),
|
||||
BRCMF_PCIE_DEVICE(CY_PCIE_89459_RAW_DEVICE_ID, CYW),
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -3412,6 +3412,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
|
|||
/* Take arm out of reset */
|
||||
if (!brcmf_chip_set_active(bus->ci, rstvec)) {
|
||||
brcmf_err("error getting out of ARM core reset\n");
|
||||
bcmerror = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -4171,6 +4172,15 @@ static int brcmf_sdio_bus_reset(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_sdio_bus_remove(struct device *dev)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
|
||||
|
||||
device_release_driver(&sdiod->func2->dev);
|
||||
device_release_driver(&sdiod->func1->dev);
|
||||
}
|
||||
|
||||
static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
||||
.stop = brcmf_sdio_bus_stop,
|
||||
.preinit = brcmf_sdio_bus_preinit,
|
||||
|
@ -4183,7 +4193,8 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
|||
.get_memdump = brcmf_sdio_bus_get_memdump,
|
||||
.get_blob = brcmf_sdio_get_blob,
|
||||
.debugfs_create = brcmf_sdio_debugfs_create,
|
||||
.reset = brcmf_sdio_bus_reset
|
||||
.reset = brcmf_sdio_bus_reset,
|
||||
.remove = brcmf_sdio_bus_remove,
|
||||
};
|
||||
|
||||
#define BRCMF_SDIO_FW_CODE 0
|
||||
|
|
|
@ -1240,7 +1240,8 @@ brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)
|
|||
return fwreq;
|
||||
}
|
||||
|
||||
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
||||
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
|
||||
enum brcmf_fwvendor fwvid)
|
||||
{
|
||||
struct brcmf_bus *bus = NULL;
|
||||
struct brcmf_usbdev *bus_pub = NULL;
|
||||
|
@ -1265,6 +1266,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
|||
dev_set_drvdata(dev, bus);
|
||||
bus->ops = &brcmf_usb_bus_ops;
|
||||
bus->proto_type = BRCMF_PROTO_BCDC;
|
||||
bus->fwvid = fwvid;
|
||||
bus->always_use_fws_queue = true;
|
||||
#ifdef CONFIG_PM
|
||||
bus->wowl_supported = true;
|
||||
|
@ -1423,7 +1425,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
else
|
||||
brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n");
|
||||
|
||||
ret = brcmf_usb_probe_cb(devinfo);
|
||||
ret = brcmf_usb_probe_cb(devinfo, id->driver_info);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
@ -1511,14 +1513,23 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define BRCMF_USB_DEVICE(dev_id) \
|
||||
{ USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
|
||||
#define BRCMF_USB_DEVICE(dev_id) \
|
||||
{ \
|
||||
USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id), \
|
||||
.driver_info = BRCMF_FWVENDOR_WCC \
|
||||
}
|
||||
|
||||
#define LINKSYS_USB_DEVICE(dev_id) \
|
||||
{ USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id) }
|
||||
#define LINKSYS_USB_DEVICE(dev_id) \
|
||||
{ \
|
||||
USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id), \
|
||||
.driver_info = BRCMF_FWVENDOR_WCC \
|
||||
}
|
||||
|
||||
#define CYPRESS_USB_DEVICE(dev_id) \
|
||||
{ USB_DEVICE(CY_USB_VENDOR_ID_CYPRESS, dev_id) }
|
||||
#define CYPRESS_USB_DEVICE(dev_id) \
|
||||
{ \
|
||||
USB_DEVICE(CY_USB_VENDOR_ID_CYPRESS, dev_id), \
|
||||
.driver_info = BRCMF_FWVENDOR_WCC \
|
||||
}
|
||||
|
||||
static const struct usb_device_id brcmf_usb_devid_table[] = {
|
||||
BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: ISC
|
||||
#
|
||||
# Copyright (c) 2022 Broadcom Corporation
|
||||
|
||||
ccflags-y += \
|
||||
-I $(srctree)/$(src) \
|
||||
-I $(srctree)/$(src)/.. \
|
||||
-I $(srctree)/$(src)/../../include
|
||||
|
||||
obj-m += brcmfmac-wcc.o
|
||||
brcmfmac-wcc-objs += \
|
||||
core.o module.o
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <core.h>
|
||||
#include <bus.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int brcmf_wcc_attach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void brcmf_wcc_detach(struct brcmf_pub *drvr)
|
||||
{
|
||||
pr_err("%s: executing\n", __func__);
|
||||
}
|
||||
|
||||
const struct brcmf_fwvid_ops brcmf_wcc_ops = {
|
||||
.attach = brcmf_wcc_attach,
|
||||
.detach = brcmf_wcc_detach,
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <bus.h>
|
||||
#include <core.h>
|
||||
#include <fwvid.h>
|
||||
|
||||
#include "vops.h"
|
||||
|
||||
static int __init brcmf_wcc_init(void)
|
||||
{
|
||||
return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE,
|
||||
&brcmf_wcc_ops);
|
||||
}
|
||||
|
||||
static void __exit brcmf_wcc_exit(void)
|
||||
{
|
||||
brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(BRCMFMAC);
|
||||
|
||||
module_init(brcmf_wcc_init);
|
||||
module_exit(brcmf_wcc_exit);
|
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: ISC */
|
||||
/*
|
||||
* Copyright (c) 2022 Broadcom Corporation
|
||||
*/
|
||||
#ifndef _BRCMFMAC_WCC_VOPS_H
|
||||
#define _BRCMFMAC_WCC_VOPS_H
|
||||
|
||||
extern const struct brcmf_fwvid_ops brcmf_wcc_ops;
|
||||
#define WCC_VOPS (&brcmf_wcc_ops)
|
||||
|
||||
#endif /* _BRCMFMAC_WCC_VOPS_H */
|
|
@ -418,17 +418,6 @@ static inline void write_nic_byte(struct net_device *dev, u32 addr, u8 val)
|
|||
write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val);
|
||||
}
|
||||
|
||||
static inline void write_nic_auto_inc_address(struct net_device *dev, u32 addr)
|
||||
{
|
||||
write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS,
|
||||
addr & IPW_REG_INDIRECT_ADDR_MASK);
|
||||
}
|
||||
|
||||
static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val)
|
||||
{
|
||||
write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val);
|
||||
}
|
||||
|
||||
static void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
|
||||
const u8 * buf)
|
||||
{
|
||||
|
|
|
@ -382,9 +382,11 @@ enum iwl_scd_queue_cfg_operation {
|
|||
* @u.add.cb_size: size code
|
||||
* @u.add.bc_dram_addr: byte-count table IOVA
|
||||
* @u.add.tfdq_dram_addr: TFD queue IOVA
|
||||
* @u.remove.queue: queue ID for removal
|
||||
* @u.modify.sta_mask: new station mask for modify
|
||||
* @u.modify.queue: queue ID to modify
|
||||
* @u.remove.sta_mask: station mask of queue to remove
|
||||
* @u.remove.tid: TID of queue to remove
|
||||
* @u.modify.old_sta_mask: old station mask for modify
|
||||
* @u.modify.tid: TID of queue to modify
|
||||
* @u.modify.new_sta_mask: new station mask for modify
|
||||
*/
|
||||
struct iwl_scd_queue_cfg_cmd {
|
||||
__le32 operation;
|
||||
|
@ -399,11 +401,13 @@ struct iwl_scd_queue_cfg_cmd {
|
|||
__le64 tfdq_dram_addr;
|
||||
} __packed add; /* TX_QUEUE_CFG_CMD_ADD_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 queue;
|
||||
__le32 sta_mask;
|
||||
__le32 tid;
|
||||
} __packed remove; /* TX_QUEUE_CFG_CMD_REMOVE_API_S_VER_1 */
|
||||
struct {
|
||||
__le32 sta_mask;
|
||||
__le32 queue;
|
||||
__le32 old_sta_mask;
|
||||
__le32 tid;
|
||||
__le32 new_sta_mask;
|
||||
} __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1 */
|
||||
} __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */
|
||||
} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -157,7 +157,8 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
|||
base = fwrt->fw->inst_errlog_ptr;
|
||||
}
|
||||
|
||||
if (base < 0x400000) {
|
||||
if ((fwrt->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && !base) ||
|
||||
(fwrt->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_BZ && base < 0x400000)) {
|
||||
IWL_ERR(fwrt,
|
||||
"Not valid error log pointer 0x%08X for %s uCode\n",
|
||||
base,
|
||||
|
@ -376,7 +377,7 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
|
|||
return;
|
||||
}
|
||||
|
||||
error = iwl_read_umac_prph(trans, UMAG_SB_CPU_2_STATUS);
|
||||
error = iwl_read_umac_prph(trans, error);
|
||||
|
||||
IWL_ERR(trans, "IML/ROM dump:\n");
|
||||
|
||||
|
|
|
@ -1964,6 +1964,8 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
|
|||
!!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
|
||||
nvm->sku_cap_mimo_disabled =
|
||||
!!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
|
||||
if (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM)
|
||||
nvm->sku_cap_11be_enable = true;
|
||||
|
||||
/* Initialize PHY sku data */
|
||||
nvm->valid_tx_ant = (u8)le32_to_cpu(rsp->phy_sku.tx_chains);
|
||||
|
|
|
@ -976,6 +976,8 @@ struct iwl_trans_txqs {
|
|||
* @max_skb_frags: maximum number of fragments an SKB can have when transmitted.
|
||||
* 0 indicates that frag SKBs (NETIF_F_SG) aren't supported.
|
||||
* @hw_rf_id a u32 with the device RF ID
|
||||
* @hw_crf_id a u32 with the device CRF ID
|
||||
* @hw_cdb_id a u32 with the device CDB ID
|
||||
* @hw_id: a u32 with the ID of the device / sub-device.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
|
@ -1015,6 +1017,8 @@ struct iwl_trans {
|
|||
u32 hw_rev;
|
||||
u32 hw_rev_step;
|
||||
u32 hw_rf_id;
|
||||
u32 hw_crf_id;
|
||||
u32 hw_cdb_id;
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
u32 sku_id[3];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation
|
||||
*/
|
||||
|
@ -13,7 +13,7 @@
|
|||
/**
|
||||
* DOC: Introduction
|
||||
*
|
||||
* iwlmei is the kernel module that is in charge of the commnunication between
|
||||
* iwlmei is the kernel module that is in charge of the communication between
|
||||
* the iwlwifi driver and the CSME firmware's WLAN driver. This communication
|
||||
* uses the SAP protocol defined in another file.
|
||||
* iwlwifi can request or release ownership on the WiFi device through iwlmei.
|
||||
|
@ -348,7 +348,7 @@ void iwl_mei_set_rfkill_state(bool hw_rfkill, bool sw_rfkill);
|
|||
/**
|
||||
* iwl_mei_set_nic_info() - set mac address
|
||||
* @mac_address: mac address to set
|
||||
* @nvm_address: NVM mac adsress to set
|
||||
* @nvm_address: NVM mac address to set
|
||||
*
|
||||
* This function must be called upon mac address change.
|
||||
*/
|
||||
|
|
|
@ -1963,7 +1963,7 @@ static int iwl_mei_probe(struct mei_cl_device *cldev,
|
|||
iwl_mei_dbgfs_register(mei);
|
||||
|
||||
/*
|
||||
* We now have a Rx function in place, start the SAP procotol
|
||||
* We now have a Rx function in place, start the SAP protocol
|
||||
* we expect to get the SAP_ME_MSG_START_OK response later on.
|
||||
*/
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2021 - 2022 Intel Corporation
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@
|
|||
*
|
||||
* Since this messaging system cannot support high amounts of
|
||||
* traffic, iwlwifi and the CSME firmware's WLAN driver have an
|
||||
* addtional communication pipe to exchange information. The body
|
||||
* additional communication pipe to exchange information. The body
|
||||
* of the message is copied to a shared area and the message that
|
||||
* goes over the ME interface just signals the other side
|
||||
* that a new message is waiting in the shared area. The ME
|
||||
|
@ -55,7 +55,7 @@
|
|||
/**
|
||||
* DOC: Host and driver state messages
|
||||
*
|
||||
* In order to let CSME konw about the host state and the host driver state,
|
||||
* In order to let CSME know about the host state and the host driver state,
|
||||
* the host sends messages that let CSME know about the host's state.
|
||||
* When the host driver is loaded, the host sends %SAP_MSG_NOTIF_WIFIDR_UP.
|
||||
* When the host driver is unloaded, the host sends %SAP_MSG_NOTIF_WIFIDR_DOWN.
|
||||
|
@ -76,7 +76,7 @@
|
|||
* DOC: Ownership
|
||||
*
|
||||
* The device can be controlled either by the CSME firmware or
|
||||
* by the host driver: iwlwifi. There is a negotiaion between
|
||||
* by the host driver: iwlwifi. There is a negotiation between
|
||||
* those two entities to determine who controls (or owns) the
|
||||
* device. Since the CSME can control the device even when the
|
||||
* OS is not working or even missing, the CSME can request the
|
||||
|
@ -136,7 +136,7 @@ enum iwl_sap_me_msg_id {
|
|||
* struct iwl_sap_me_msg_hdr - the header of the ME message
|
||||
* @type: the type of the message, see &enum iwl_sap_me_msg_id.
|
||||
* @seq_num: a sequence number used for debug only.
|
||||
* @len: the length of the mssage.
|
||||
* @len: the length of the message.
|
||||
*/
|
||||
struct iwl_sap_me_msg_hdr {
|
||||
__le32 type;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright(c) 2021 Intel Corporation
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright(c) 2021 Intel Corporation
|
||||
*/
|
||||
|
|
|
@ -599,6 +599,11 @@ static void iwl_mvm_wowlan_gtk_type_iter(struct ieee80211_hw *hw,
|
|||
switch (key->cipher) {
|
||||
default:
|
||||
return;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
if (!sta)
|
||||
data->kek_kck_cmd->gtk_cipher =
|
||||
cpu_to_le32(STA_KEY_FLG_TKIP);
|
||||
return;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
data->kek_kck_cmd->igtk_cipher = cpu_to_le32(STA_KEY_FLG_GCMP);
|
||||
|
@ -610,13 +615,13 @@ static void iwl_mvm_wowlan_gtk_type_iter(struct ieee80211_hw *hw,
|
|||
if (!sta)
|
||||
data->kek_kck_cmd->gtk_cipher =
|
||||
cpu_to_le32(STA_KEY_FLG_CCM);
|
||||
break;
|
||||
return;
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
if (!sta)
|
||||
data->kek_kck_cmd->gtk_cipher =
|
||||
cpu_to_le32(STA_KEY_FLG_GCMP);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1010,11 +1010,10 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
|
|||
static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm,
|
||||
struct cfg80211_pmsr_result *res)
|
||||
{
|
||||
struct iwl_mvm_smooth_entry *resp;
|
||||
struct iwl_mvm_smooth_entry *resp = NULL, *iter;
|
||||
s64 rtt_avg, rtt = res->ftm.rtt_avg;
|
||||
u32 undershoot, overshoot;
|
||||
u8 alpha;
|
||||
bool found;
|
||||
|
||||
if (!IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH)
|
||||
return;
|
||||
|
@ -1028,15 +1027,14 @@ static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm,
|
|||
return;
|
||||
}
|
||||
|
||||
found = false;
|
||||
list_for_each_entry(resp, &mvm->ftm_initiator.smooth.resp, list) {
|
||||
if (!memcmp(res->addr, resp->addr, ETH_ALEN)) {
|
||||
found = true;
|
||||
list_for_each_entry(iter, &mvm->ftm_initiator.smooth.resp, list) {
|
||||
if (!memcmp(res->addr, iter->addr, ETH_ALEN)) {
|
||||
resp = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (!resp) {
|
||||
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
||||
if (!resp)
|
||||
return;
|
||||
|
|
|
@ -122,6 +122,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
u32 version = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0);
|
||||
u32 i;
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
enum iwl_device_family device_family = trans->trans_cfg->device_family;
|
||||
|
||||
|
||||
if (version == 6) {
|
||||
struct iwl_alive_ntf_v6 *palive;
|
||||
|
@ -230,7 +233,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
|
||||
if (umac_error_table) {
|
||||
if (umac_error_table >=
|
||||
mvm->trans->cfg->min_umac_error_event_table) {
|
||||
mvm->trans->cfg->min_umac_error_event_table ||
|
||||
device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
iwl_fw_umac_set_alive_err_table(mvm->trans,
|
||||
umac_error_table);
|
||||
} else {
|
||||
|
|
|
@ -92,6 +92,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
radio_cfg_dash = (phy_config & FW_PHY_CFG_RADIO_DASH) >>
|
||||
FW_PHY_CFG_RADIO_DASH_POS;
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
|
||||
radio_cfg_step, radio_cfg_dash);
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
return;
|
||||
|
||||
/* SKU control */
|
||||
reg_val = CSR_HW_REV_STEP_DASH(mvm->trans->hw_rev);
|
||||
|
||||
|
@ -127,9 +133,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
CSR_HW_IF_CONFIG_REG_D3_DEBUG,
|
||||
reg_val);
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "Radio type=0x%x-0x%x-0x%x\n", radio_cfg_type,
|
||||
radio_cfg_step, radio_cfg_dash);
|
||||
|
||||
/*
|
||||
* W/A : NIC is stuck in a reset state after Early PCIe power off
|
||||
* (PCIe power is lost before PERST# is asserted), causing ME FW
|
||||
|
|
|
@ -2066,22 +2066,30 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
struct ieee80211_rx_status *rx_status;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rx_no_data *desc = (void *)pkt->data;
|
||||
u32 rssi = le32_to_cpu(desc->rssi);
|
||||
u32 info_type = le32_to_cpu(desc->info) & RX_NO_DATA_INFO_TYPE_MSK;
|
||||
u32 rssi;
|
||||
u32 info_type;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_mvm_rx_phy_data phy_data = {
|
||||
.d0 = desc->phy_info[0],
|
||||
.d1 = desc->phy_info[1],
|
||||
.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD,
|
||||
.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time),
|
||||
.rate_n_flags = le32_to_cpu(desc->rate),
|
||||
.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK),
|
||||
.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK),
|
||||
.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK),
|
||||
};
|
||||
struct iwl_mvm_rx_phy_data phy_data;
|
||||
u32 format;
|
||||
|
||||
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
|
||||
return;
|
||||
|
||||
if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(struct iwl_rx_no_data)))
|
||||
return;
|
||||
|
||||
rssi = le32_to_cpu(desc->rssi);
|
||||
info_type = le32_to_cpu(desc->info) & RX_NO_DATA_INFO_TYPE_MSK;
|
||||
phy_data.d0 = desc->phy_info[0];
|
||||
phy_data.d1 = desc->phy_info[1];
|
||||
phy_data.phy_info = IWL_RX_MPDU_PHY_TSF_OVERLOAD;
|
||||
phy_data.gp2_on_air_rise = le32_to_cpu(desc->on_air_rise_time);
|
||||
phy_data.rate_n_flags = le32_to_cpu(desc->rate);
|
||||
phy_data.energy_a = u32_get_bits(rssi, RX_NO_DATA_CHAIN_A_MSK);
|
||||
phy_data.energy_b = u32_get_bits(rssi, RX_NO_DATA_CHAIN_B_MSK);
|
||||
phy_data.channel = u32_get_bits(rssi, RX_NO_DATA_CHANNEL_MSK);
|
||||
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RX_NO_DATA_NOTIF, 0) < 2) {
|
||||
IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n",
|
||||
|
@ -2093,12 +2101,6 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
format = phy_data.rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
|
||||
|
||||
if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*desc)))
|
||||
return;
|
||||
|
||||
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
|
||||
return;
|
||||
|
||||
/* Dont use dev_alloc_skb(), we'll have enough headroom once
|
||||
* ieee80211_hdr pulled.
|
||||
*/
|
||||
|
|
|
@ -316,7 +316,7 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue,
|
|||
}
|
||||
|
||||
static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
u16 *queueptr, u8 tid)
|
||||
int sta_id, u16 *queueptr, u8 tid)
|
||||
{
|
||||
int queue = *queueptr;
|
||||
struct iwl_scd_txq_cfg_cmd cmd = {
|
||||
|
@ -333,7 +333,8 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|||
SCD_QUEUE_CONFIG_CMD);
|
||||
struct iwl_scd_queue_cfg_cmd remove_cmd = {
|
||||
.operation = cpu_to_le32(IWL_SCD_QUEUE_REMOVE),
|
||||
.u.remove.queue = cpu_to_le32(queue),
|
||||
.u.remove.tid = cpu_to_le32(tid),
|
||||
.u.remove.sta_mask = cpu_to_le32(BIT(sta_id)),
|
||||
};
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0,
|
||||
|
@ -531,7 +532,7 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue,
|
|||
iwl_mvm_invalidate_sta_queue(mvm, queue,
|
||||
disable_agg_tids, false);
|
||||
|
||||
ret = iwl_mvm_disable_txq(mvm, old_sta, &queue_tmp, tid);
|
||||
ret = iwl_mvm_disable_txq(mvm, old_sta, sta_id, &queue_tmp, tid);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm,
|
||||
"Failed to free inactive queue %d (ret=%d)\n",
|
||||
|
@ -1408,7 +1409,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
|||
|
||||
out_err:
|
||||
queue_tmp = queue;
|
||||
iwl_mvm_disable_txq(mvm, sta, &queue_tmp, tid);
|
||||
iwl_mvm_disable_txq(mvm, sta, mvmsta->sta_id, &queue_tmp, tid);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1854,7 +1855,8 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
|
|||
if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
|
||||
continue;
|
||||
|
||||
iwl_mvm_disable_txq(mvm, sta, &mvm_sta->tid_data[i].txq_id, i);
|
||||
iwl_mvm_disable_txq(mvm, sta, mvm_sta->sta_id,
|
||||
&mvm_sta->tid_data[i].txq_id, i);
|
||||
mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
|
||||
}
|
||||
|
||||
|
@ -2065,7 +2067,7 @@ static int iwl_mvm_add_int_sta_with_queue(struct iwl_mvm *mvm, int macidx,
|
|||
ret = iwl_mvm_add_int_sta_common(mvm, sta, addr, macidx, maccolor);
|
||||
if (ret) {
|
||||
if (!iwl_mvm_has_new_tx_api(mvm))
|
||||
iwl_mvm_disable_txq(mvm, NULL, queue,
|
||||
iwl_mvm_disable_txq(mvm, NULL, sta->sta_id, queue,
|
||||
IWL_MAX_TID_COUNT);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2138,7 +2140,8 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_MVM_INVALID_STA))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_disable_txq(mvm, NULL, &mvm->snif_queue, IWL_MAX_TID_COUNT);
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvm->snif_sta.sta_id,
|
||||
&mvm->snif_queue, IWL_MAX_TID_COUNT);
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
|
@ -2155,7 +2158,8 @@ int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
|
|||
if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_MVM_INVALID_STA))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_disable_txq(mvm, NULL, &mvm->aux_queue, IWL_MAX_TID_COUNT);
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvm->aux_sta.sta_id,
|
||||
&mvm->aux_queue, IWL_MAX_TID_COUNT);
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvm->aux_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
|
@ -2272,7 +2276,8 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
queue = *queueptr;
|
||||
iwl_mvm_disable_txq(mvm, NULL, queueptr, IWL_MAX_TID_COUNT);
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvmvif->bcast_sta.sta_id,
|
||||
queueptr, IWL_MAX_TID_COUNT);
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
return;
|
||||
|
||||
|
@ -2507,7 +2512,8 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
|
||||
iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true);
|
||||
|
||||
iwl_mvm_disable_txq(mvm, NULL, &mvmvif->cab_queue, 0);
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvmvif->mcast_sta.sta_id,
|
||||
&mvmvif->cab_queue, 0);
|
||||
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
|
||||
if (ret)
|
||||
|
|
|
@ -376,12 +376,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
|
|||
static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_time_event_notif *notif)
|
||||
{
|
||||
struct iwl_mvm_time_event_data *te_data, *tmp;
|
||||
bool aux_roc_te = false;
|
||||
struct iwl_mvm_time_event_data *aux_roc_te = NULL, *te_data;
|
||||
|
||||
list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
|
||||
list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
|
||||
if (le32_to_cpu(notif->unique_id) == te_data->uid) {
|
||||
aux_roc_te = true;
|
||||
aux_roc_te = te_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1350,15 +1350,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
};
|
||||
|
||||
/*
|
||||
* In case that there is no OTP on the NIC, get the rf id and cdb info
|
||||
* from the prph registers.
|
||||
* Read rf id and cdb info from prph register and store it
|
||||
*/
|
||||
static int get_crf_id(struct iwl_trans *iwl_trans)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 sd_reg_ver_addr;
|
||||
u32 cdb = 0;
|
||||
u32 val;
|
||||
u32 val = 0;
|
||||
|
||||
if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
sd_reg_ver_addr = SD_REG_VER_GEN2;
|
||||
|
@ -1377,10 +1375,26 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
|
|||
iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val);
|
||||
|
||||
/* Read crf info */
|
||||
val = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
|
||||
iwl_trans->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
|
||||
|
||||
/* Read cdb info (also contains the jacket info if needed in the future */
|
||||
cdb = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
|
||||
iwl_trans->hw_cdb_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR);
|
||||
|
||||
iwl_trans_release_nic_access(iwl_trans);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case that there is no OTP on the NIC, map the rf id and cdb info
|
||||
* from the prph registers.
|
||||
*/
|
||||
static int map_crf_id(struct iwl_trans *iwl_trans)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val = iwl_trans->hw_crf_id;
|
||||
u32 cdb = iwl_trans->hw_cdb_id;
|
||||
|
||||
/* Map between crf id to rf id */
|
||||
switch (REG_CRF_ID_TYPE(val)) {
|
||||
|
@ -1410,7 +1424,7 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
|
|||
IWL_ERR(iwl_trans,
|
||||
"Can find a correct rfid for crf id 0x%x\n",
|
||||
REG_CRF_ID_TYPE(val));
|
||||
goto out_release;
|
||||
goto out;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1423,8 +1437,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans)
|
|||
IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n",
|
||||
iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val));
|
||||
|
||||
out_release:
|
||||
iwl_trans_release_nic_access(iwl_trans);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -1544,6 +1556,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
}
|
||||
|
||||
iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
|
||||
get_crf_id(iwl_trans);
|
||||
|
||||
/*
|
||||
* The RF_ID is set to zero in blank OTP so read version to
|
||||
|
@ -1552,7 +1565,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
*/
|
||||
if (iwl_trans->trans_cfg->rf_id &&
|
||||
iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
|
||||
!CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) {
|
||||
!CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && map_crf_id(iwl_trans)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_trans;
|
||||
}
|
||||
|
|
|
@ -1240,7 +1240,7 @@ struct rtl8723bu_c2h {
|
|||
u8 bw;
|
||||
} __packed ra_report;
|
||||
};
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct rtl8xxxu_fileops;
|
||||
|
||||
|
|
|
@ -780,6 +780,12 @@ static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv)
|
|||
*/
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180);
|
||||
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07f77);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
||||
/* Path A IQK setting */
|
||||
|
@ -825,11 +831,16 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf117b);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
|
||||
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
|
||||
|
||||
/* PA/PAD control by 0x56, and set = 0x0 */
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x511e0);
|
||||
|
||||
/* Enter IQK mode */
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
@ -844,14 +855,14 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160c1f);
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8216031f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x6816031f);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
mdelay(10);
|
||||
|
@ -882,11 +893,16 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ffa);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
|
||||
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
|
||||
|
||||
/* PA/PAD control by 0x56, and set = 0x0 */
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x510e0);
|
||||
|
||||
/* Enter IQK mode */
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
@ -900,14 +916,14 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f);
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x821608ff);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x281608ff);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
|
||||
|
||||
mdelay(10);
|
||||
|
@ -937,9 +953,12 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180);
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0x07f77);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
||||
/* Path B IQK setting */
|
||||
|
@ -948,11 +967,11 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x821403e2);
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82140303);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160000);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00492911);
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
|
||||
|
||||
/* One shot, path A LOK & IQK */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
|
||||
|
@ -988,11 +1007,16 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf117b);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
|
||||
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
|
||||
|
||||
/* PA/PAD control by 0x56, and set = 0x0 */
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x511e0);
|
||||
|
||||
/* Enter IQK mode */
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
@ -1007,8 +1031,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160c1f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160c1f);
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8216031f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x6816031f);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
|
||||
|
@ -1048,11 +1072,16 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ffa);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
|
||||
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
|
||||
rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
|
||||
|
||||
/* PA/PAD control by 0x56, and set = 0x0 */
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x51000);
|
||||
rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x510e0);
|
||||
|
||||
/* Enter IQK mode */
|
||||
rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
|
||||
|
@ -1066,8 +1095,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
|
|||
rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c);
|
||||
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c1f);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c1f);
|
||||
rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x821608ff);
|
||||
rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x281608ff);
|
||||
|
||||
/* LO calibration setting */
|
||||
rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891);
|
||||
|
|
|
@ -4598,6 +4598,32 @@ static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time)
|
|||
}
|
||||
}
|
||||
|
||||
static void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt,
|
||||
u8 rate, u8 sgi, u8 bw)
|
||||
{
|
||||
u8 mcs, nss;
|
||||
|
||||
rarpt->txrate.flags = 0;
|
||||
|
||||
if (rate <= DESC_RATE_54M) {
|
||||
rarpt->txrate.legacy = rtl8xxxu_legacy_ratetable[rate].bitrate;
|
||||
} else {
|
||||
rtl8xxxu_desc_to_mcsrate(rate, &mcs, &nss);
|
||||
rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
|
||||
rarpt->txrate.mcs = mcs;
|
||||
rarpt->txrate.nss = nss;
|
||||
|
||||
if (sgi)
|
||||
rarpt->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
|
||||
rarpt->txrate.bw = bw;
|
||||
}
|
||||
|
||||
rarpt->bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate);
|
||||
rarpt->desc_rate = rate;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf, u64 changed)
|
||||
|
@ -4620,9 +4646,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
u32 ramask;
|
||||
int sgi = 0;
|
||||
u8 highest_rate;
|
||||
u8 mcs = 0, nss = 0;
|
||||
u32 bit_rate;
|
||||
|
||||
u8 bw;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
|
@ -4647,37 +4671,19 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
sgi = 1;
|
||||
|
||||
highest_rate = fls(ramask) - 1;
|
||||
if (highest_rate < DESC_RATE_MCS0) {
|
||||
rarpt->txrate.legacy =
|
||||
rtl8xxxu_legacy_ratetable[highest_rate].bitrate;
|
||||
} else {
|
||||
rtl8xxxu_desc_to_mcsrate(highest_rate,
|
||||
&mcs, &nss);
|
||||
rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
|
||||
rarpt->txrate.mcs = mcs;
|
||||
rarpt->txrate.nss = nss;
|
||||
|
||||
if (sgi) {
|
||||
rarpt->txrate.flags |=
|
||||
RATE_INFO_FLAGS_SHORT_GI;
|
||||
}
|
||||
|
||||
if (rtl8xxxu_ht40_2g &&
|
||||
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
rarpt->txrate.bw = RATE_INFO_BW_40;
|
||||
else
|
||||
rarpt->txrate.bw = RATE_INFO_BW_20;
|
||||
}
|
||||
if (rtl8xxxu_ht40_2g &&
|
||||
(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
bw = RATE_INFO_BW_40;
|
||||
else
|
||||
bw = RATE_INFO_BW_20;
|
||||
rcu_read_unlock();
|
||||
bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate);
|
||||
rarpt->bit_rate = bit_rate;
|
||||
rarpt->desc_rate = highest_rate;
|
||||
|
||||
rtl8xxxu_update_ra_report(rarpt, highest_rate, sgi, bw);
|
||||
|
||||
priv->vif = vif;
|
||||
priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
|
||||
|
||||
priv->fops->update_rate_mask(priv, ramask, 0, sgi, rarpt->txrate.bw == RATE_INFO_BW_40);
|
||||
priv->fops->update_rate_mask(priv, ramask, 0, sgi, bw == RATE_INFO_BW_40);
|
||||
|
||||
rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
|
||||
|
||||
|
@ -5538,9 +5544,7 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work)
|
|||
u8 bt_info = 0;
|
||||
struct rtl8xxxu_btcoex *btcoex;
|
||||
struct rtl8xxxu_ra_report *rarpt;
|
||||
u8 rate, sgi, bw;
|
||||
u32 bit_rate;
|
||||
u8 mcs = 0, nss = 0;
|
||||
u8 bw;
|
||||
|
||||
priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work);
|
||||
btcoex = &priv->bt_coex;
|
||||
|
@ -5566,32 +5570,17 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work)
|
|||
rtl8723bu_handle_bt_info(priv);
|
||||
break;
|
||||
case C2H_8723B_RA_REPORT:
|
||||
rarpt->txrate.flags = 0;
|
||||
rate = c2h->ra_report.rate;
|
||||
sgi = c2h->ra_report.sgi;
|
||||
bw = c2h->ra_report.bw;
|
||||
bw = rarpt->txrate.bw;
|
||||
|
||||
if (rate < DESC_RATE_MCS0) {
|
||||
rarpt->txrate.legacy =
|
||||
rtl8xxxu_legacy_ratetable[rate].bitrate;
|
||||
} else {
|
||||
rtl8xxxu_desc_to_mcsrate(rate, &mcs, &nss);
|
||||
rarpt->txrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
|
||||
rarpt->txrate.mcs = mcs;
|
||||
rarpt->txrate.nss = nss;
|
||||
|
||||
if (sgi) {
|
||||
rarpt->txrate.flags |=
|
||||
RATE_INFO_FLAGS_SHORT_GI;
|
||||
}
|
||||
|
||||
if (bw == RATE_INFO_BW_20)
|
||||
rarpt->txrate.bw |= RATE_INFO_BW_20;
|
||||
if (skb->len >= offsetofend(typeof(*c2h), ra_report.bw)) {
|
||||
if (c2h->ra_report.bw == RTL8XXXU_CHANNEL_WIDTH_40)
|
||||
bw = RATE_INFO_BW_40;
|
||||
else
|
||||
bw = RATE_INFO_BW_20;
|
||||
}
|
||||
bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate);
|
||||
rarpt->bit_rate = bit_rate;
|
||||
rarpt->desc_rate = rate;
|
||||
|
||||
rtl8xxxu_update_ra_report(rarpt, c2h->ra_report.rate,
|
||||
c2h->ra_report.sgi, bw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1903,7 +1903,7 @@ btc8723b1ant_action_wifi_not_conn_scan(struct btc_coexist *btcoexist)
|
|||
true, 32);
|
||||
halbtc8723b1ant_coex_table_with_type(btcoexist,
|
||||
NORMAL_EXEC, 4);
|
||||
} else if (bt_link_info->a2dp_exist) {
|
||||
} else if (bt_link_info->pan_exist) {
|
||||
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
|
||||
true, 22);
|
||||
halbtc8723b1ant_coex_table_with_type(btcoexist,
|
||||
|
@ -1964,8 +1964,7 @@ static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist)
|
|||
true, 32);
|
||||
halbtc8723b1ant_coex_table_with_type(btcoexist,
|
||||
NORMAL_EXEC, 4);
|
||||
} else if (bt_link_info->a2dp_exist &&
|
||||
bt_link_info->pan_exist) {
|
||||
} else if (bt_link_info->pan_exist) {
|
||||
halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC,
|
||||
true, 22);
|
||||
halbtc8723b1ant_coex_table_with_type(btcoexist,
|
||||
|
|
|
@ -115,9 +115,6 @@ static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw,
|
|||
retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
|
||||
BLSSI_READBACK_DATA);
|
||||
|
||||
retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
|
||||
BLSSI_READBACK_DATA);
|
||||
|
||||
rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
|
||||
rfpath, pphyreg->rf_rb, retvalue);
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@ config RTW88_CORE
|
|||
config RTW88_PCI
|
||||
tristate
|
||||
|
||||
config RTW88_USB
|
||||
tristate
|
||||
|
||||
config RTW88_8822B
|
||||
tristate
|
||||
|
||||
|
@ -39,6 +42,17 @@ config RTW88_8822BE
|
|||
|
||||
802.11ac PCIe wireless network adapter
|
||||
|
||||
config RTW88_8822BU
|
||||
tristate "Realtek 8822BU USB wireless network adapter"
|
||||
depends on USB
|
||||
select RTW88_CORE
|
||||
select RTW88_USB
|
||||
select RTW88_8822B
|
||||
help
|
||||
Select this option will enable support for 8822BU chipset
|
||||
|
||||
802.11ac USB wireless network adapter
|
||||
|
||||
config RTW88_8822CE
|
||||
tristate "Realtek 8822CE PCI wireless network adapter"
|
||||
depends on PCI
|
||||
|
@ -50,6 +64,17 @@ config RTW88_8822CE
|
|||
|
||||
802.11ac PCIe wireless network adapter
|
||||
|
||||
config RTW88_8822CU
|
||||
tristate "Realtek 8822CU USB wireless network adapter"
|
||||
depends on USB
|
||||
select RTW88_CORE
|
||||
select RTW88_USB
|
||||
select RTW88_8822C
|
||||
help
|
||||
Select this option will enable support for 8822CU chipset
|
||||
|
||||
802.11ac USB wireless network adapter
|
||||
|
||||
config RTW88_8723DE
|
||||
tristate "Realtek 8723DE PCI wireless network adapter"
|
||||
depends on PCI
|
||||
|
@ -61,6 +86,17 @@ config RTW88_8723DE
|
|||
|
||||
802.11n PCIe wireless network adapter
|
||||
|
||||
config RTW88_8723DU
|
||||
tristate "Realtek 8723DU USB wireless network adapter"
|
||||
depends on USB
|
||||
select RTW88_CORE
|
||||
select RTW88_USB
|
||||
select RTW88_8723D
|
||||
help
|
||||
Select this option will enable support for 8723DU chipset
|
||||
|
||||
802.11n USB wireless network adapter
|
||||
|
||||
config RTW88_8821CE
|
||||
tristate "Realtek 8821CE PCI wireless network adapter"
|
||||
depends on PCI
|
||||
|
@ -72,6 +108,17 @@ config RTW88_8821CE
|
|||
|
||||
802.11ac PCIe wireless network adapter
|
||||
|
||||
config RTW88_8821CU
|
||||
tristate "Realtek 8821CU USB wireless network adapter"
|
||||
depends on USB
|
||||
select RTW88_CORE
|
||||
select RTW88_USB
|
||||
select RTW88_8821C
|
||||
help
|
||||
Select this option will enable support for 8821CU chipset
|
||||
|
||||
802.11ac USB wireless network adapter
|
||||
|
||||
config RTW88_DEBUG
|
||||
bool "Realtek rtw88 debug support"
|
||||
depends on RTW88_CORE
|
||||
|
|
|
@ -26,23 +26,38 @@ rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
|
|||
obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o
|
||||
rtw88_8822be-objs := rtw8822be.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o
|
||||
rtw88_8822bu-objs := rtw8822bu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822C) += rtw88_8822c.o
|
||||
rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o
|
||||
rtw88_8822ce-objs := rtw8822ce.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o
|
||||
rtw88_8822cu-objs := rtw8822cu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o
|
||||
rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o
|
||||
rtw88_8723de-objs := rtw8723de.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o
|
||||
rtw88_8723du-objs := rtw8723du.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821C) += rtw88_8821c.o
|
||||
rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
|
||||
rtw88_8821ce-objs := rtw8821ce.o
|
||||
|
||||
obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o
|
||||
rtw88_8821cu-objs := rtw8821cu.o
|
||||
|
||||
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
|
||||
rtw88_pci-objs := pci.o
|
||||
|
||||
obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
|
||||
rtw88_usb-objs := usb.o
|
||||
|
|
|
@ -633,7 +633,7 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
|
|||
struct rtw_coex *coex = &rtwdev->coex;
|
||||
struct sk_buff *skb_resp = NULL;
|
||||
|
||||
mutex_lock(&coex->mutex);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
rtw_fw_query_bt_mp_info(rtwdev, req);
|
||||
|
||||
|
@ -650,7 +650,6 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
|
|||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&coex->mutex);
|
||||
return skb_resp;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,9 @@ static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v)
|
|||
addr = debugfs_priv->rf_addr;
|
||||
mask = debugfs_priv->rf_mask;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
val = rtw_read_rf(rtwdev, path, addr, mask);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n",
|
||||
path, addr, mask, val);
|
||||
|
@ -390,7 +392,9 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_fw_h2c_cmd_dbg(rtwdev, param);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -414,7 +418,9 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
|
|||
return count;
|
||||
}
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_write_rf(rtwdev, path, addr, mask, val);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
|
||||
"write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n",
|
||||
path, addr, mask, val);
|
||||
|
@ -519,6 +525,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
|
|||
u32 addr, offset, data;
|
||||
u8 path;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
|
||||
seq_printf(m, "RF path:%d\n", path);
|
||||
for (addr = 0; addr < 0x100; addr += 4) {
|
||||
|
@ -533,6 +541,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
|
|||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -831,7 +841,9 @@ static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v)
|
|||
struct rtw_debugfs_priv *debugfs_priv = m->private;
|
||||
struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_coex_display_coex_info(rtwdev, m);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1026,6 +1038,8 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+',
|
||||
rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]);
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
|
||||
for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
|
||||
val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK);
|
||||
seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val);
|
||||
|
@ -1035,6 +1049,7 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m)
|
|||
txgapk->rf3f_fs[path][i], i);
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
}
|
||||
|
||||
static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v)
|
||||
|
|
|
@ -322,7 +322,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
h2c[3], h2c[2], h2c[1], h2c[0],
|
||||
h2c[7], h2c[6], h2c[5], h2c[4]);
|
||||
|
||||
spin_lock(&rtwdev->h2c.lock);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
box = rtwdev->h2c.last_box_num;
|
||||
switch (box) {
|
||||
|
@ -344,7 +344,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
break;
|
||||
default:
|
||||
WARN(1, "invalid h2c mail box number\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = read_poll_timeout_atomic(rtw_read8, box_state,
|
||||
|
@ -353,7 +353,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to send h2c command\n");
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext));
|
||||
|
@ -361,9 +361,6 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
|
|||
|
||||
if (++rtwdev->h2c.last_box_num >= 4)
|
||||
rtwdev->h2c.last_box_num = 0;
|
||||
|
||||
out:
|
||||
spin_unlock(&rtwdev->h2c.lock);
|
||||
}
|
||||
|
||||
void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c)
|
||||
|
@ -375,15 +372,13 @@ static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
|
|||
{
|
||||
int ret;
|
||||
|
||||
spin_lock(&rtwdev->h2c.lock);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq);
|
||||
ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE);
|
||||
if (ret)
|
||||
rtw_err(rtwdev, "failed to send h2c packet\n");
|
||||
rtwdev->h2c.seq++;
|
||||
|
||||
spin_unlock(&rtwdev->h2c.lock);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -166,12 +166,11 @@ static inline u32
|
|||
rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -180,11 +179,9 @@ static inline void
|
|||
rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
spin_lock_irqsave(&rtwdev->rf_lock, flags);
|
||||
rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data);
|
||||
spin_unlock_irqrestore(&rtwdev->rf_lock, flags);
|
||||
}
|
||||
|
||||
static inline u32
|
||||
|
|
|
@ -1048,6 +1048,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
|
|||
if (rtw_chip_wcpu_11ac(rtwdev))
|
||||
rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
|
||||
|
||||
if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB)
|
||||
rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -487,8 +487,8 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtw_dev *rtwdev = hw->priv;
|
||||
|
||||
rtw_fw_beacon_filter_config(rtwdev, false, vif);
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw_fw_beacon_filter_config(rtwdev, false, vif);
|
||||
rtw_sta_remove(rtwdev, sta, true);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
||||
|
|
|
@ -1731,7 +1731,8 @@ static void rtw_load_firmware_cb(const struct firmware *firmware, void *context)
|
|||
update_firmware_info(rtwdev, fw);
|
||||
complete_all(&fw->completion);
|
||||
|
||||
rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n",
|
||||
rtw_info(rtwdev, "%sFirmware version %u.%u.%u, H2C version %u\n",
|
||||
fw->type == RTW_WOWLAN_FW ? "WOW " : "",
|
||||
fw->version, fw->sub_version, fw->sub_index, fw->h2c_version);
|
||||
}
|
||||
|
||||
|
@ -1757,6 +1758,7 @@ static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
fw->type = type;
|
||||
fw->rtwdev = rtwdev;
|
||||
init_completion(&fw->completion);
|
||||
|
||||
|
@ -1781,6 +1783,10 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
|
|||
rtwdev->hci.rpwm_addr = 0x03d9;
|
||||
rtwdev->hci.cpwm_addr = 0x03da;
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtwdev->hci.rpwm_addr = 0xfe58;
|
||||
rtwdev->hci.cpwm_addr = 0xfe57;
|
||||
break;
|
||||
default:
|
||||
rtw_err(rtwdev, "unsupported hci type\n");
|
||||
return -EINVAL;
|
||||
|
@ -2065,13 +2071,10 @@ int rtw_core_init(struct rtw_dev *rtwdev)
|
|||
skb_queue_head_init(&rtwdev->coex.queue);
|
||||
skb_queue_head_init(&rtwdev->tx_report.queue);
|
||||
|
||||
spin_lock_init(&rtwdev->rf_lock);
|
||||
spin_lock_init(&rtwdev->h2c.lock);
|
||||
spin_lock_init(&rtwdev->txq_lock);
|
||||
spin_lock_init(&rtwdev->tx_report.q_lock);
|
||||
|
||||
mutex_init(&rtwdev->mutex);
|
||||
mutex_init(&rtwdev->coex.mutex);
|
||||
mutex_init(&rtwdev->hal.tx_power_mutex);
|
||||
|
||||
init_waitqueue_head(&rtwdev->coex.wait);
|
||||
|
@ -2143,7 +2146,6 @@ void rtw_core_deinit(struct rtw_dev *rtwdev)
|
|||
}
|
||||
|
||||
mutex_destroy(&rtwdev->mutex);
|
||||
mutex_destroy(&rtwdev->coex.mutex);
|
||||
mutex_destroy(&rtwdev->hal.tx_power_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_core_deinit);
|
||||
|
|
|
@ -871,6 +871,10 @@ struct rtw_chip_ops {
|
|||
bool is_tx2_path);
|
||||
void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path,
|
||||
u8 rx_path, bool is_tx2_path);
|
||||
/* for USB/SDIO only */
|
||||
void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc);
|
||||
|
||||
/* for coex */
|
||||
void (*coex_set_init)(struct rtw_dev *rtwdev);
|
||||
|
@ -1501,8 +1505,6 @@ struct rtw_coex_stat {
|
|||
};
|
||||
|
||||
struct rtw_coex {
|
||||
/* protects coex info request section */
|
||||
struct mutex mutex;
|
||||
struct sk_buff_head queue;
|
||||
wait_queue_head_t wait;
|
||||
|
||||
|
@ -1851,6 +1853,7 @@ struct rtw_fw_state {
|
|||
u16 h2c_version;
|
||||
u32 feature;
|
||||
u32 feature_ext;
|
||||
enum rtw_fw_type type;
|
||||
};
|
||||
|
||||
enum rtw_sar_sources {
|
||||
|
@ -1994,9 +1997,6 @@ struct rtw_dev {
|
|||
/* ensures exclusive access from mac80211 callbacks */
|
||||
struct mutex mutex;
|
||||
|
||||
/* read/write rf register */
|
||||
spinlock_t rf_lock;
|
||||
|
||||
/* watch dog every 2 sec */
|
||||
struct delayed_work watch_dog_work;
|
||||
u32 watch_dog_cnt;
|
||||
|
@ -2022,8 +2022,6 @@ struct rtw_dev {
|
|||
struct {
|
||||
/* incicate the mail box to use with fw */
|
||||
u8 last_box_num;
|
||||
/* protect to send h2c to fw */
|
||||
spinlock_t lock;
|
||||
u32 seq;
|
||||
} h2c;
|
||||
|
||||
|
|
|
@ -300,7 +300,7 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev)
|
|||
|
||||
data.rtwdev = rtwdev;
|
||||
data.min_rssi = U8_MAX;
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_stat_rssi_iter, &data);
|
||||
|
||||
dm_info->pre_min_rssi = dm_info->min_rssi;
|
||||
dm_info->min_rssi = data.min_rssi;
|
||||
|
@ -544,7 +544,7 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev)
|
|||
if (rtwdev->watch_dog_cnt & 0x3)
|
||||
return;
|
||||
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_ra_info_update_iter, rtwdev);
|
||||
}
|
||||
|
||||
static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx)
|
||||
|
@ -597,7 +597,7 @@ static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev)
|
|||
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
||||
|
||||
dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX;
|
||||
rtw_iterate_stas_atomic(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev);
|
||||
rtw_iterate_stas(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev);
|
||||
rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
|
||||
rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
|
||||
|
||||
rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@
|
|||
#define BIT_TXDMA_VIQ_MAP(x) \
|
||||
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
|
||||
#define REG_TXDMA_PQ_MAP 0x010C
|
||||
#define BIT_RXDMA_ARBBW_EN BIT(0)
|
||||
#define BIT_SHIFT_TXDMA_BEQ_MAP 8
|
||||
#define BIT_MASK_TXDMA_BEQ_MAP 0x3
|
||||
#define BIT_TXDMA_BEQ_MAP(x) \
|
||||
|
|
|
@ -210,6 +210,12 @@ static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8723d_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -239,6 +245,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8723de_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8723du_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -1945,6 +1954,24 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
|
|||
dm_info->pwr_trk_triggered = false;
|
||||
}
|
||||
|
||||
static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
|
||||
__le16 chksum = 0;
|
||||
__le16 *data = (__le16 *)(txdesc);
|
||||
|
||||
SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
|
||||
|
||||
while (words--)
|
||||
chksum ^= *data++;
|
||||
|
||||
chksum = ~chksum;
|
||||
|
||||
SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
|
||||
}
|
||||
|
||||
static struct rtw_chip_ops rtw8723d_ops = {
|
||||
.phy_set_param = rtw8723d_phy_set_param,
|
||||
.read_efuse = rtw8723d_read_efuse,
|
||||
|
@ -1965,6 +1992,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
|
|||
.config_bfee = NULL,
|
||||
.set_gid_table = NULL,
|
||||
.cfg_csi_rate = NULL,
|
||||
.fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8723d_coex_cfg_init,
|
||||
.coex_set_ant_switch = NULL,
|
||||
|
|
|
@ -41,6 +41,14 @@ struct rtw8723de_efuse {
|
|||
u8 sub_device_id[2];
|
||||
};
|
||||
|
||||
struct rtw8723du_efuse {
|
||||
u8 res4[48]; /* 0xd0 */
|
||||
u8 vender_id[2]; /* 0x100 */
|
||||
u8 product_id[2]; /* 0x102 */
|
||||
u8 usb_option; /* 0x104 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x107 */
|
||||
};
|
||||
|
||||
struct rtw8723d_efuse {
|
||||
__le16 rtl_id;
|
||||
u8 rsvd[2];
|
||||
|
@ -69,7 +77,10 @@ struct rtw8723d_efuse {
|
|||
u8 rfe_option;
|
||||
u8 country_code[2];
|
||||
u8 res[3];
|
||||
struct rtw8723de_efuse e;
|
||||
union {
|
||||
struct rtw8723de_efuse e;
|
||||
struct rtw8723du_efuse u;
|
||||
};
|
||||
};
|
||||
|
||||
extern const struct rtw_chip_info rtw8723d_hw_spec;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8723d.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8723du_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd723, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* 8723DU 1*1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd611, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* Edimax EW-7611ULB V2 */
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8723du_id_table);
|
||||
|
||||
static int rtw8723du_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8723du_driver = {
|
||||
.name = "rtw_8723du",
|
||||
.id_table = rtw_8723du_id_table,
|
||||
.probe = rtw8723du_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8723du_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -26,6 +26,12 @@ static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8821c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
enum rtw8821ce_rf_set {
|
||||
SWITCH_TO_BTG,
|
||||
SWITCH_TO_WLG,
|
||||
|
@ -68,6 +74,9 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8821ce_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8821cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -1148,6 +1157,13 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
|
|||
dm_info->cck_pd_default + new_lvl * 2);
|
||||
}
|
||||
|
||||
static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
fill_txdesc_checksum_common(txdesc, 16);
|
||||
}
|
||||
|
||||
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -1521,6 +1537,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
|
|||
[2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
|
||||
[4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
|
||||
[6] = RTW_DEF_RFE(8821c, 0, 0),
|
||||
[34] = RTW_DEF_RFE(8821c, 0, 0),
|
||||
};
|
||||
|
||||
static struct rtw_hw_reg rtw8821c_dig[] = {
|
||||
|
@ -1595,6 +1612,7 @@ static struct rtw_chip_ops rtw8821c_ops = {
|
|||
.config_bfee = rtw8821c_bf_config_bfee,
|
||||
.set_gid_table = rtw_bf_set_gid_table,
|
||||
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
|
||||
.fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8821c_coex_cfg_init,
|
||||
.coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch,
|
||||
|
|
|
@ -9,6 +9,26 @@
|
|||
|
||||
#define RCR_VHT_ACK BIT(26)
|
||||
|
||||
struct rtw8821cu_efuse {
|
||||
u8 res4[4]; /* 0xd0 */
|
||||
u8 usb_optional_function;
|
||||
u8 res5[0x1e];
|
||||
u8 res6[2];
|
||||
u8 serial[0x0b]; /* 0xf5 */
|
||||
u8 vid; /* 0x100 */
|
||||
u8 res7;
|
||||
u8 pid;
|
||||
u8 res8[4];
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x107 */
|
||||
u8 res9[2];
|
||||
u8 vendor_name[0x07];
|
||||
u8 res10[2];
|
||||
u8 device_name[0x14];
|
||||
u8 res11[0xcf];
|
||||
u8 package_type; /* 0x1fb */
|
||||
u8 res12[0x4];
|
||||
};
|
||||
|
||||
struct rtw8821ce_efuse {
|
||||
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
|
||||
u8 vender_id[2];
|
||||
|
@ -73,6 +93,7 @@ struct rtw8821c_efuse {
|
|||
u8 res[3];
|
||||
union {
|
||||
struct rtw8821ce_efuse e;
|
||||
struct rtw8821cu_efuse u;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8821c.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8821cu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
|
||||
|
||||
static int rtw_8821cu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8821cu_driver = {
|
||||
.name = "rtw_8821cu",
|
||||
.id_table = rtw_8821cu_id_table,
|
||||
.probe = rtw_8821cu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8821cu_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans Ulli Kroll <linux@ulli-kroll.de>");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -26,6 +26,12 @@ static void rtw8822be_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822b_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -56,6 +62,9 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8822be_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822bu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -1588,6 +1597,15 @@ static void rtw8822b_adaptivity(struct rtw_dev *rtwdev)
|
|||
rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
|
||||
}
|
||||
|
||||
static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
|
||||
|
||||
fill_txdesc_checksum_common(txdesc, words);
|
||||
}
|
||||
|
||||
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -2163,6 +2181,7 @@ static struct rtw_chip_ops rtw8822b_ops = {
|
|||
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
|
||||
.adaptivity_init = rtw8822b_adaptivity_init,
|
||||
.adaptivity = rtw8822b_adaptivity,
|
||||
.fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8822b_coex_cfg_init,
|
||||
.coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch,
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822b.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8822bu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb812, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2102, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* CCNC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822ULC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UTC */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xf822, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UAD */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb81a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Default ID */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS AC1300 USB-AC55 B1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x184c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS U2 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x19aa, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS - USB-AC58 rev A1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1870, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1874, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-181 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-182 - D1 */
|
||||
{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331f, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec)}, /* Dlink - DWA-183 D Ver */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB6400M */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0045, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB3600 v2 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U v1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U Plus v1 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T4U V3 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0116, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0117, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9055, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Netgear A6150 */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0025, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Hawking HW12ACU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x04ca, 0x8602, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);
|
||||
|
||||
static int rtw8822bu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822bu_driver = {
|
||||
.name = "rtw_8822bu",
|
||||
.id_table = rtw_8822bu_id_table,
|
||||
.probe = rtw8822bu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8822bu_driver);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -29,6 +29,12 @@ static void rtw8822ce_efuse_parsing(struct rtw_efuse *efuse,
|
|||
ether_addr_copy(efuse->addr, map->e.mac_addr);
|
||||
}
|
||||
|
||||
static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse,
|
||||
struct rtw8822c_efuse *map)
|
||||
{
|
||||
ether_addr_copy(efuse->addr, map->u.mac_addr);
|
||||
}
|
||||
|
||||
static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
||||
{
|
||||
struct rtw_efuse *efuse = &rtwdev->efuse;
|
||||
|
@ -58,6 +64,9 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
|
|||
case RTW_HCI_TYPE_PCIE:
|
||||
rtw8822ce_efuse_parsing(efuse, map);
|
||||
break;
|
||||
case RTW_HCI_TYPE_USB:
|
||||
rtw8822cu_efuse_parsing(efuse, map);
|
||||
break;
|
||||
default:
|
||||
/* unsupported now */
|
||||
return -ENOTSUPP;
|
||||
|
@ -4557,6 +4566,18 @@ static void rtw8822c_adaptivity(struct rtw_dev *rtwdev)
|
|||
rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
|
||||
}
|
||||
|
||||
static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
size_t words;
|
||||
|
||||
words = (pkt_info->pkt_offset * 8 + chip->tx_pkt_desc_sz) / 2;
|
||||
|
||||
fill_txdesc_checksum_common(txdesc, words);
|
||||
}
|
||||
|
||||
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = {
|
||||
{0x0086,
|
||||
RTW_PWR_CUT_ALL_MSK,
|
||||
|
@ -4895,6 +4916,8 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
|
|||
[0] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[1] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[2] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[3] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[4] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
[5] = RTW_DEF_RFE(8822c, 0, 5),
|
||||
[6] = RTW_DEF_RFE(8822c, 0, 0),
|
||||
};
|
||||
|
@ -4978,6 +5001,7 @@ static struct rtw_chip_ops rtw8822c_ops = {
|
|||
.cfo_track = rtw8822c_cfo_track,
|
||||
.config_tx_path = rtw8822c_config_tx_path,
|
||||
.config_txrx_mode = rtw8822c_config_trx_mode,
|
||||
.fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum,
|
||||
|
||||
.coex_set_init = rtw8822c_coex_cfg_init,
|
||||
.coex_set_ant_switch = NULL,
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include "main.h"
|
||||
#include "rtw8822c.h"
|
||||
#include "usb.h"
|
||||
|
||||
static const struct usb_device_id rtw_8822cu_id_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc812, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82e, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd820, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd82b, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, rtw_8822cu_id_table);
|
||||
|
||||
static int rtw8822bu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtw_usb_probe(intf, id);
|
||||
}
|
||||
|
||||
static struct usb_driver rtw_8822cu_driver = {
|
||||
.name = "rtw_8822cu",
|
||||
.id_table = rtw_8822cu_id_table,
|
||||
.probe = rtw8822bu_probe,
|
||||
.disconnect = rtw_usb_disconnect,
|
||||
};
|
||||
module_usb_driver(rtw_8822cu_driver);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cu driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -71,6 +71,14 @@
|
|||
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
|
||||
#define SET_TX_DESC_BT_NULL(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
|
||||
#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0))
|
||||
#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \
|
||||
le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24))
|
||||
#define GET_TX_DESC_PKT_OFFSET(txdesc) \
|
||||
le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24))
|
||||
#define GET_TX_DESC_QSEL(txdesc) \
|
||||
le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8))
|
||||
|
||||
enum rtw_tx_desc_queue_select {
|
||||
TX_DESC_QSEL_TID0 = 0,
|
||||
|
@ -123,4 +131,27 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
|
|||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf, u32 size);
|
||||
|
||||
static inline
|
||||
void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
|
||||
{
|
||||
__le16 chksum = 0;
|
||||
__le16 *data = (__le16 *)(txdesc);
|
||||
|
||||
SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
|
||||
|
||||
while (words--)
|
||||
chksum ^= *data++;
|
||||
|
||||
SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
|
||||
}
|
||||
|
||||
static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *txdesc)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
|
||||
chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,911 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "main.h"
|
||||
#include "debug.h"
|
||||
#include "reg.h"
|
||||
#include "tx.h"
|
||||
#include "rx.h"
|
||||
#include "fw.h"
|
||||
#include "ps.h"
|
||||
#include "usb.h"
|
||||
|
||||
#define RTW_USB_MAX_RXQ_LEN 512
|
||||
|
||||
struct rtw_usb_txcb {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct sk_buff_head tx_ack_queue;
|
||||
};
|
||||
|
||||
static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
|
||||
struct sk_buff *skb, int agg_num)
|
||||
{
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
struct rtw_tx_pkt_info pkt_info;
|
||||
|
||||
SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num);
|
||||
pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
|
||||
}
|
||||
|
||||
static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
__le32 *data;
|
||||
unsigned long flags;
|
||||
int idx, ret;
|
||||
static int count;
|
||||
|
||||
spin_lock_irqsave(&rtwusb->usb_lock, flags);
|
||||
|
||||
idx = rtwusb->usb_data_index;
|
||||
rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);
|
||||
|
||||
spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
|
||||
|
||||
data = &rtwusb->usb_data[idx];
|
||||
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr,
|
||||
RTW_USB_VENQT_CMD_IDX, data, len, 1000);
|
||||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "read register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
|
||||
return le32_to_cpu(*data);
|
||||
}
|
||||
|
||||
static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u8)rtw_usb_read(rtwdev, addr, 1);
|
||||
}
|
||||
|
||||
static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u16)rtw_usb_read(rtwdev, addr, 2);
|
||||
}
|
||||
|
||||
static u32 rtw_usb_read32(struct rtw_dev *rtwdev, u32 addr)
|
||||
{
|
||||
return (u32)rtw_usb_read(rtwdev, addr, 4);
|
||||
}
|
||||
|
||||
static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
|
||||
{
|
||||
struct rtw_usb *rtwusb = (struct rtw_usb *)rtwdev->priv;
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
unsigned long flags;
|
||||
__le32 *data;
|
||||
int idx, ret;
|
||||
static int count;
|
||||
|
||||
spin_lock_irqsave(&rtwusb->usb_lock, flags);
|
||||
|
||||
idx = rtwusb->usb_data_index;
|
||||
rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);
|
||||
|
||||
spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
|
||||
|
||||
data = &rtwusb->usb_data[idx];
|
||||
|
||||
*data = cpu_to_le32(val);
|
||||
|
||||
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
||||
addr, 0, data, len, 30000);
|
||||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
}
|
||||
|
||||
static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 1);
|
||||
}
|
||||
|
||||
static void rtw_usb_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 2);
|
||||
}
|
||||
|
||||
static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
|
||||
{
|
||||
rtw_usb_write(rtwdev, addr, val, 4);
|
||||
}
|
||||
|
||||
static int rtw_usb_parse(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *interface)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_host_interface *host_interface = &interface->altsetting[0];
|
||||
struct usb_interface_descriptor *interface_desc = &host_interface->desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct usb_device *usbd = interface_to_usbdev(interface);
|
||||
int num_out_pipes = 0;
|
||||
int i;
|
||||
u8 num;
|
||||
|
||||
for (i = 0; i < interface_desc->bNumEndpoints; i++) {
|
||||
endpoint = &host_interface->endpoint[i].desc;
|
||||
num = usb_endpoint_num(endpoint);
|
||||
|
||||
if (usb_endpoint_dir_in(endpoint) &&
|
||||
usb_endpoint_xfer_bulk(endpoint)) {
|
||||
if (rtwusb->pipe_in) {
|
||||
rtw_err(rtwdev, "IN pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->pipe_in = num;
|
||||
}
|
||||
|
||||
if (usb_endpoint_dir_in(endpoint) &&
|
||||
usb_endpoint_xfer_int(endpoint)) {
|
||||
if (rtwusb->pipe_interrupt) {
|
||||
rtw_err(rtwdev, "INT pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->pipe_interrupt = num;
|
||||
}
|
||||
|
||||
if (usb_endpoint_dir_out(endpoint) &&
|
||||
usb_endpoint_xfer_bulk(endpoint)) {
|
||||
if (num_out_pipes >= ARRAY_SIZE(rtwusb->out_ep)) {
|
||||
rtw_err(rtwdev, "OUT pipes overflow\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwusb->out_ep[num_out_pipes++] = num;
|
||||
}
|
||||
}
|
||||
|
||||
switch (usbd->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
rtwusb->bulkout_size = RTW_USB_FULL_SPEED_BULK_SIZE;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
rtwusb->bulkout_size = RTW_USB_HIGH_SPEED_BULK_SIZE;
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
rtwusb->bulkout_size = RTW_USB_SUPER_SPEED_BULK_SIZE;
|
||||
break;
|
||||
default:
|
||||
rtw_err(rtwdev, "failed to detect usb speed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rtwdev->hci.bulkout_num = num_out_pipes;
|
||||
|
||||
switch (num_out_pipes) {
|
||||
case 4:
|
||||
case 3:
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 2;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 2;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 2;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 2;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = 1;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = 1;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = 0;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 0;
|
||||
break;
|
||||
case 2:
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 1;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 1;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 1;
|
||||
rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 1;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
rtw_err(rtwdev, "failed to get out_pipes(%d)\n", num_out_pipes);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_write_port_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct rtw_usb_txcb *txcb = urb->context;
|
||||
struct rtw_dev *rtwdev = txcb->rtwdev;
|
||||
struct ieee80211_hw *hw = rtwdev->hw;
|
||||
|
||||
while (true) {
|
||||
struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue);
|
||||
struct ieee80211_tx_info *info;
|
||||
struct rtw_usb_tx_data *tx_data;
|
||||
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
tx_data = rtw_usb_get_tx_data(skb);
|
||||
|
||||
/* enqueue to wait for tx report */
|
||||
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
|
||||
rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* always ACK for others, then they won't be marked as drop */
|
||||
ieee80211_tx_info_clear_status(info);
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
|
||||
else
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
|
||||
kfree(txcb);
|
||||
}
|
||||
|
||||
static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel)
|
||||
{
|
||||
if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep))
|
||||
return 0;
|
||||
|
||||
return rtwusb->qsel_to_ep[qsel];
|
||||
}
|
||||
|
||||
static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *skb,
|
||||
usb_complete_t cb, void *context)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *usbd = rtwusb->udev;
|
||||
struct urb *urb;
|
||||
unsigned int pipe;
|
||||
int ret;
|
||||
int ep = qsel_to_ep(rtwusb, qsel);
|
||||
|
||||
pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]);
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
usb_fill_bulk_urb(urb, usbd, pipe, skb->data, skb->len, cb, context);
|
||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
|
||||
{
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
struct rtw_usb_txcb *txcb;
|
||||
struct sk_buff *skb_head;
|
||||
struct sk_buff *skb_iter;
|
||||
int agg_num = 0;
|
||||
unsigned int align_next = 0;
|
||||
|
||||
if (skb_queue_empty(list))
|
||||
return false;
|
||||
|
||||
txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
|
||||
if (!txcb)
|
||||
return false;
|
||||
|
||||
txcb->rtwdev = rtwdev;
|
||||
skb_queue_head_init(&txcb->tx_ack_queue);
|
||||
|
||||
skb_iter = skb_dequeue(list);
|
||||
|
||||
if (skb_queue_empty(list)) {
|
||||
skb_head = skb_iter;
|
||||
goto queue;
|
||||
}
|
||||
|
||||
skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
|
||||
if (!skb_head) {
|
||||
skb_head = skb_iter;
|
||||
goto queue;
|
||||
}
|
||||
|
||||
while (skb_iter) {
|
||||
unsigned long flags;
|
||||
|
||||
skb_put(skb_head, align_next);
|
||||
skb_put_data(skb_head, skb_iter->data, skb_iter->len);
|
||||
|
||||
align_next = ALIGN(skb_iter->len, 8) - skb_iter->len;
|
||||
|
||||
agg_num++;
|
||||
|
||||
skb_queue_tail(&txcb->tx_ack_queue, skb_iter);
|
||||
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
|
||||
skb_iter = skb_peek(list);
|
||||
|
||||
if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
|
||||
__skb_unlink(skb_iter, list);
|
||||
else
|
||||
skb_iter = NULL;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
}
|
||||
|
||||
if (agg_num > 1)
|
||||
rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num);
|
||||
|
||||
queue:
|
||||
skb_queue_tail(&txcb->tx_ack_queue, skb_head);
|
||||
|
||||
rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
|
||||
rtw_usb_write_port_tx_complete, txcb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_handler(struct work_struct *work)
|
||||
{
|
||||
struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work);
|
||||
int i, limit;
|
||||
|
||||
for (i = ARRAY_SIZE(rtwusb->tx_queue) - 1; i >= 0; i--) {
|
||||
for (limit = 0; limit < 200; limit++) {
|
||||
struct sk_buff_head *list = &rtwusb->tx_queue[i];
|
||||
|
||||
if (!rtw_usb_tx_agg_skb(rtwusb, list))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
|
||||
skb_queue_purge(&rtwusb->tx_queue[i]);
|
||||
}
|
||||
|
||||
static void rtw_usb_write_port_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
u8 *buf)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct sk_buff *skb;
|
||||
unsigned int desclen, headsize, size;
|
||||
u8 qsel;
|
||||
int ret = 0;
|
||||
|
||||
size = pkt_info->tx_pkt_size;
|
||||
qsel = pkt_info->qsel;
|
||||
desclen = chip->tx_pkt_desc_sz;
|
||||
headsize = pkt_info->offset ? pkt_info->offset : desclen;
|
||||
|
||||
skb = dev_alloc_skb(headsize + size);
|
||||
if (unlikely(!skb))
|
||||
return -ENOMEM;
|
||||
|
||||
skb_reserve(skb, headsize);
|
||||
skb_put_data(skb, buf, size);
|
||||
skb_push(skb, headsize);
|
||||
memset(skb->data, 0, headsize);
|
||||
rtw_tx_fill_tx_desc(pkt_info, skb);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
|
||||
|
||||
ret = rtw_usb_write_port(rtwdev, qsel, skb,
|
||||
rtw_usb_write_port_complete, skb);
|
||||
if (unlikely(ret))
|
||||
rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
|
||||
u32 size)
|
||||
{
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_usb *rtwusb;
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
u32 len, desclen;
|
||||
|
||||
rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
pkt_info.tx_pkt_size = size;
|
||||
pkt_info.qsel = TX_DESC_QSEL_BEACON;
|
||||
|
||||
desclen = chip->tx_pkt_desc_sz;
|
||||
len = desclen + size;
|
||||
if (len % rtwusb->bulkout_size == 0) {
|
||||
len += RTW_USB_PACKET_OFFSET_SZ;
|
||||
pkt_info.offset = desclen + RTW_USB_PACKET_OFFSET_SZ;
|
||||
pkt_info.pkt_offset = 1;
|
||||
} else {
|
||||
pkt_info.offset = desclen;
|
||||
}
|
||||
|
||||
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
|
||||
}
|
||||
|
||||
static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
|
||||
{
|
||||
struct rtw_tx_pkt_info pkt_info = {0};
|
||||
|
||||
pkt_info.tx_pkt_size = size;
|
||||
pkt_info.qsel = TX_DESC_QSEL_H2C;
|
||||
|
||||
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
|
||||
}
|
||||
|
||||
static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 qsel;
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
|
||||
qsel = TX_DESC_QSEL_MGMT;
|
||||
else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
|
||||
qsel = skb->priority;
|
||||
else
|
||||
qsel = TX_DESC_QSEL_BEACON;
|
||||
|
||||
return qsel;
|
||||
}
|
||||
|
||||
static int rtw_usb_tx_write(struct rtw_dev *rtwdev,
|
||||
struct rtw_tx_pkt_info *pkt_info,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_usb_tx_data *tx_data;
|
||||
u8 *pkt_desc;
|
||||
int ep;
|
||||
|
||||
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
|
||||
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
|
||||
pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(skb);
|
||||
ep = qsel_to_ep(rtwusb, pkt_info->qsel);
|
||||
rtw_tx_fill_tx_desc(pkt_info, skb);
|
||||
rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
|
||||
tx_data = rtw_usb_get_tx_data(skb);
|
||||
tx_data->sn = pkt_info->sn;
|
||||
|
||||
skb_queue_tail(&rtwusb->tx_queue[ep], skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_tx_kick_off(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
queue_work(rtwusb->txwq, &rtwusb->tx_work);
|
||||
}
|
||||
|
||||
static void rtw_usb_rx_handler(struct work_struct *work)
|
||||
{
|
||||
struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work);
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
const struct rtw_chip_info *chip = rtwdev->chip;
|
||||
struct rtw_rx_pkt_stat pkt_stat;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct sk_buff *skb;
|
||||
u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
|
||||
u32 pkt_offset;
|
||||
u8 *rx_desc;
|
||||
int limit;
|
||||
|
||||
for (limit = 0; limit < 200; limit++) {
|
||||
skb = skb_dequeue(&rtwusb->rx_queue);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
rx_desc = skb->data;
|
||||
chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
|
||||
&rx_status);
|
||||
pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
|
||||
pkt_stat.shift;
|
||||
|
||||
if (pkt_stat.is_c2h) {
|
||||
skb_put(skb, pkt_stat.pkt_len + pkt_offset);
|
||||
rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
|
||||
rtw_err(rtwdev, "failed to get rx_queue, overflow\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_put(skb, pkt_stat.pkt_len);
|
||||
skb_reserve(skb, pkt_offset);
|
||||
memcpy(skb->cb, &rx_status, sizeof(rx_status));
|
||||
ieee80211_rx_irqsafe(rtwdev->hw, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_read_port_complete(struct urb *urb);
|
||||
|
||||
static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
|
||||
{
|
||||
struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
||||
int error;
|
||||
|
||||
rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
|
||||
if (!rxcb->rx_skb)
|
||||
return;
|
||||
|
||||
usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
|
||||
usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
|
||||
rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
|
||||
rtw_usb_read_port_complete, rxcb);
|
||||
|
||||
error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
|
||||
if (error) {
|
||||
kfree_skb(rxcb->rx_skb);
|
||||
if (error != -ENODEV)
|
||||
rtw_err(rtwdev, "Err sending rx data urb %d\n",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_read_port_complete(struct urb *urb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb = urb->context;
|
||||
struct rtw_dev *rtwdev = rxcb->rtwdev;
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct sk_buff *skb = rxcb->rx_skb;
|
||||
|
||||
if (urb->status == 0) {
|
||||
if (urb->actual_length >= RTW_USB_MAX_RECVBUF_SZ ||
|
||||
urb->actual_length < 24) {
|
||||
rtw_err(rtwdev, "failed to get urb length:%d\n",
|
||||
urb->actual_length);
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
skb_queue_tail(&rtwusb->rx_queue, skb);
|
||||
queue_work(rtwusb->rxwq, &rtwusb->rx_work);
|
||||
}
|
||||
rtw_usb_rx_resubmit(rtwusb, rxcb);
|
||||
} else {
|
||||
switch (urb->status) {
|
||||
case -EINVAL:
|
||||
case -EPIPE:
|
||||
case -ENODEV:
|
||||
case -ESHUTDOWN:
|
||||
case -ENOENT:
|
||||
case -EPROTO:
|
||||
case -EILSEQ:
|
||||
case -ETIME:
|
||||
case -ECOMM:
|
||||
case -EOVERFLOW:
|
||||
case -EINPROGRESS:
|
||||
break;
|
||||
default:
|
||||
rtw_err(rtwdev, "status %d\n", urb->status);
|
||||
break;
|
||||
}
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
rxcb = &rtwusb->rx_cb[i];
|
||||
if (rxcb->rx_urb)
|
||||
usb_kill_urb(rxcb->rx_urb);
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
struct rx_usb_ctrl_block *rxcb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
rxcb = &rtwusb->rx_cb[i];
|
||||
if (rxcb->rx_urb) {
|
||||
usb_kill_urb(rxcb->rx_urb);
|
||||
usb_free_urb(rxcb->rx_urb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
|
||||
|
||||
rxcb->n = i;
|
||||
rxcb->rtwdev = rtwusb->rtwdev;
|
||||
rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!rxcb->rx_urb)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
rtw_usb_free_rx_bufs(rtwusb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int rtw_usb_setup(struct rtw_dev *rtwdev)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtw_usb_start(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_stop(struct rtw_dev *rtwdev)
|
||||
{
|
||||
}
|
||||
|
||||
static void rtw_usb_deep_ps(struct rtw_dev *rtwdev, bool enter)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static void rtw_usb_link_ps(struct rtw_dev *rtwdev, bool enter)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
/* empty function for rtw_hci_ops */
|
||||
}
|
||||
|
||||
static struct rtw_hci_ops rtw_usb_ops = {
|
||||
.tx_write = rtw_usb_tx_write,
|
||||
.tx_kick_off = rtw_usb_tx_kick_off,
|
||||
.setup = rtw_usb_setup,
|
||||
.start = rtw_usb_start,
|
||||
.stop = rtw_usb_stop,
|
||||
.deep_ps = rtw_usb_deep_ps,
|
||||
.link_ps = rtw_usb_link_ps,
|
||||
.interface_cfg = rtw_usb_interface_cfg,
|
||||
|
||||
.write8 = rtw_usb_write8,
|
||||
.write16 = rtw_usb_write16,
|
||||
.write32 = rtw_usb_write32,
|
||||
.read8 = rtw_usb_read8,
|
||||
.read16 = rtw_usb_read16,
|
||||
.read32 = rtw_usb_read32,
|
||||
|
||||
.write_data_rsvd_page = rtw_usb_write_data_rsvd_page,
|
||||
.write_data_h2c = rtw_usb_write_data_h2c,
|
||||
};
|
||||
|
||||
static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
int i;
|
||||
|
||||
rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
|
||||
if (!rtwusb->rxwq) {
|
||||
rtw_err(rtwdev, "failed to create RX work queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb_queue_head_init(&rtwusb->rx_queue);
|
||||
|
||||
INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
|
||||
|
||||
for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
|
||||
struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
|
||||
|
||||
rtw_usb_rx_resubmit(rtwusb, rxcb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
skb_queue_purge(&rtwusb->rx_queue);
|
||||
|
||||
flush_workqueue(rtwusb->rxwq);
|
||||
destroy_workqueue(rtwusb->rxwq);
|
||||
}
|
||||
|
||||
static int rtw_usb_init_tx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
int i;
|
||||
|
||||
rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq");
|
||||
if (!rtwusb->txwq) {
|
||||
rtw_err(rtwdev, "failed to create TX work queue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
|
||||
skb_queue_head_init(&rtwusb->tx_queue[i]);
|
||||
|
||||
INIT_WORK(&rtwusb->tx_work, rtw_usb_tx_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
rtw_usb_tx_queue_purge(rtwusb);
|
||||
flush_workqueue(rtwusb->txwq);
|
||||
destroy_workqueue(rtwusb->txwq);
|
||||
}
|
||||
|
||||
static int rtw_usb_intf_init(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *intf)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
|
||||
int ret;
|
||||
|
||||
rtwusb->udev = udev;
|
||||
ret = rtw_usb_parse(rtwdev, intf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rtwusb->usb_data = kcalloc(RTW_USB_MAX_RXTX_COUNT, sizeof(u32),
|
||||
GFP_KERNEL);
|
||||
if (!rtwusb->usb_data)
|
||||
return -ENOMEM;
|
||||
|
||||
usb_set_intfdata(intf, rtwdev->hw);
|
||||
|
||||
SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
|
||||
spin_lock_init(&rtwusb->usb_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
|
||||
struct usb_interface *intf)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
usb_put_dev(rtwusb->udev);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
}
|
||||
|
||||
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct rtw_dev *rtwdev;
|
||||
struct ieee80211_hw *hw;
|
||||
struct rtw_usb *rtwusb;
|
||||
int drv_data_size;
|
||||
int ret;
|
||||
|
||||
drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_usb);
|
||||
hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwdev->hw = hw;
|
||||
rtwdev->dev = &intf->dev;
|
||||
rtwdev->chip = (struct rtw_chip_info *)id->driver_info;
|
||||
rtwdev->hci.ops = &rtw_usb_ops;
|
||||
rtwdev->hci.type = RTW_HCI_TYPE_USB;
|
||||
|
||||
rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
rtwusb->rtwdev = rtwdev;
|
||||
|
||||
ret = rtw_usb_alloc_rx_bufs(rtwusb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtw_core_init(rtwdev);
|
||||
if (ret)
|
||||
goto err_release_hw;
|
||||
|
||||
ret = rtw_usb_intf_init(rtwdev, intf);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB interface\n");
|
||||
goto err_deinit_core;
|
||||
}
|
||||
|
||||
ret = rtw_usb_init_tx(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB TX\n");
|
||||
goto err_destroy_usb;
|
||||
}
|
||||
|
||||
ret = rtw_usb_init_rx(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to init USB RX\n");
|
||||
goto err_destroy_txwq;
|
||||
}
|
||||
|
||||
ret = rtw_chip_info_setup(rtwdev);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to setup chip information\n");
|
||||
goto err_destroy_rxwq;
|
||||
}
|
||||
|
||||
ret = rtw_register_hw(rtwdev, rtwdev->hw);
|
||||
if (ret) {
|
||||
rtw_err(rtwdev, "failed to register hw\n");
|
||||
goto err_destroy_rxwq;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_rxwq:
|
||||
rtw_usb_deinit_rx(rtwdev);
|
||||
|
||||
err_destroy_txwq:
|
||||
rtw_usb_deinit_tx(rtwdev);
|
||||
|
||||
err_destroy_usb:
|
||||
rtw_usb_intf_deinit(rtwdev, intf);
|
||||
|
||||
err_deinit_core:
|
||||
rtw_core_deinit(rtwdev);
|
||||
|
||||
err_release_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_usb_probe);
|
||||
|
||||
void rtw_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct ieee80211_hw *hw = usb_get_intfdata(intf);
|
||||
struct rtw_dev *rtwdev;
|
||||
struct rtw_usb *rtwusb;
|
||||
|
||||
if (!hw)
|
||||
return;
|
||||
|
||||
rtwdev = hw->priv;
|
||||
rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
||||
rtw_usb_cancel_rx_bufs(rtwusb);
|
||||
|
||||
rtw_unregister_hw(rtwdev, hw);
|
||||
rtw_usb_deinit_tx(rtwdev);
|
||||
rtw_usb_deinit_rx(rtwdev);
|
||||
|
||||
if (rtwusb->udev->state != USB_STATE_NOTATTACHED)
|
||||
usb_reset_device(rtwusb->udev);
|
||||
|
||||
rtw_usb_free_rx_bufs(rtwusb);
|
||||
|
||||
rtw_usb_intf_deinit(rtwdev, intf);
|
||||
rtw_core_deinit(rtwdev);
|
||||
ieee80211_free_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw_usb_disconnect);
|
||||
|
||||
MODULE_AUTHOR("Realtek Corporation");
|
||||
MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,107 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* Copyright(c) 2018-2019 Realtek Corporation
|
||||
*/
|
||||
|
||||
#ifndef __RTW_USB_H_
|
||||
#define __RTW_USB_H_
|
||||
|
||||
#define FW_8192C_START_ADDRESS 0x1000
|
||||
#define FW_8192C_END_ADDRESS 0x5fff
|
||||
|
||||
#define RTW_USB_MAX_RXTX_COUNT 128
|
||||
#define RTW_USB_VENQT_MAX_BUF_SIZE 254
|
||||
#define MAX_USBCTRL_VENDORREQ_TIMES 10
|
||||
|
||||
#define RTW_USB_CMD_READ 0xc0
|
||||
#define RTW_USB_CMD_WRITE 0x40
|
||||
#define RTW_USB_CMD_REQ 0x05
|
||||
|
||||
#define RTW_USB_VENQT_CMD_IDX 0x00
|
||||
|
||||
#define RTW_USB_SUPER_SPEED_BULK_SIZE 1024
|
||||
#define RTW_USB_HIGH_SPEED_BULK_SIZE 512
|
||||
#define RTW_USB_FULL_SPEED_BULK_SIZE 64
|
||||
|
||||
#define RTW_USB_TX_SEL_HQ BIT(0)
|
||||
#define RTW_USB_TX_SEL_LQ BIT(1)
|
||||
#define RTW_USB_TX_SEL_NQ BIT(2)
|
||||
#define RTW_USB_TX_SEL_EQ BIT(3)
|
||||
|
||||
#define RTW_USB_BULK_IN_ADDR 0x80
|
||||
#define RTW_USB_INT_IN_ADDR 0x81
|
||||
|
||||
#define RTW_USB_HW_QUEUE_ENTRY 8
|
||||
|
||||
#define RTW_USB_PACKET_OFFSET_SZ 8
|
||||
#define RTW_USB_MAX_XMITBUF_SZ (1024 * 20)
|
||||
#define RTW_USB_MAX_RECVBUF_SZ 32768
|
||||
|
||||
#define RTW_USB_RECVBUFF_ALIGN_SZ 8
|
||||
|
||||
#define RTW_USB_RXAGG_SIZE 6
|
||||
#define RTW_USB_RXAGG_TIMEOUT 10
|
||||
|
||||
#define RTW_USB_RXCB_NUM 4
|
||||
|
||||
#define RTW_USB_EP_MAX 4
|
||||
|
||||
#define TX_DESC_QSEL_MAX 20
|
||||
|
||||
#define RTW_USB_VENDOR_ID_REALTEK 0x0bda
|
||||
|
||||
static inline struct rtw_usb *rtw_get_usb_priv(struct rtw_dev *rtwdev)
|
||||
{
|
||||
return (struct rtw_usb *)rtwdev->priv;
|
||||
}
|
||||
|
||||
struct rx_usb_ctrl_block {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct urb *rx_urb;
|
||||
struct sk_buff *rx_skb;
|
||||
int n;
|
||||
};
|
||||
|
||||
struct rtw_usb_tx_data {
|
||||
u8 sn;
|
||||
};
|
||||
|
||||
struct rtw_usb {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct usb_device *udev;
|
||||
|
||||
/* protects usb_data_index */
|
||||
spinlock_t usb_lock;
|
||||
__le32 *usb_data;
|
||||
unsigned int usb_data_index;
|
||||
|
||||
u32 bulkout_size;
|
||||
u8 pipe_interrupt;
|
||||
u8 pipe_in;
|
||||
u8 out_ep[RTW_USB_EP_MAX];
|
||||
u8 qsel_to_ep[TX_DESC_QSEL_MAX];
|
||||
u8 usb_txagg_num;
|
||||
|
||||
struct workqueue_struct *txwq, *rxwq;
|
||||
|
||||
struct sk_buff_head tx_queue[RTW_USB_EP_MAX];
|
||||
struct work_struct tx_work;
|
||||
|
||||
struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
|
||||
struct sk_buff_head rx_queue;
|
||||
struct work_struct rx_work;
|
||||
};
|
||||
|
||||
static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
|
||||
sizeof(info->status.status_driver_data));
|
||||
|
||||
return (struct rtw_usb_tx_data *)info->status.status_driver_data;
|
||||
}
|
||||
|
||||
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);
|
||||
void rtw_usb_disconnect(struct usb_interface *intf);
|
||||
|
||||
#endif
|
|
@ -105,3 +105,106 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
|
|||
*mcs = rate - DESC_RATEMCS0;
|
||||
}
|
||||
}
|
||||
|
||||
struct rtw_stas_entry {
|
||||
struct list_head list;
|
||||
struct ieee80211_sta *sta;
|
||||
};
|
||||
|
||||
struct rtw_iter_stas_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct rtw_iter_stas_data *iter_stas = data;
|
||||
struct rtw_stas_entry *stas_entry;
|
||||
|
||||
stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC);
|
||||
if (!stas_entry)
|
||||
return;
|
||||
|
||||
stas_entry->sta = sta;
|
||||
list_add_tail(&stas_entry->list, &iter_stas->list);
|
||||
}
|
||||
|
||||
void rtw_iterate_stas(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data,
|
||||
struct ieee80211_sta *sta),
|
||||
void *data)
|
||||
{
|
||||
struct rtw_iter_stas_data iter_data;
|
||||
struct rtw_stas_entry *sta_entry, *tmp;
|
||||
|
||||
/* &rtwdev->mutex makes sure no stations can be removed between
|
||||
* collecting the stations and iterating over them.
|
||||
*/
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
iter_data.rtwdev = rtwdev;
|
||||
INIT_LIST_HEAD(&iter_data.list);
|
||||
|
||||
ieee80211_iterate_stations_atomic(rtwdev->hw, rtw_collect_sta_iter,
|
||||
&iter_data);
|
||||
|
||||
list_for_each_entry_safe(sta_entry, tmp, &iter_data.list,
|
||||
list) {
|
||||
list_del_init(&sta_entry->list);
|
||||
iterator(data, sta_entry->sta);
|
||||
kfree(sta_entry);
|
||||
}
|
||||
}
|
||||
|
||||
struct rtw_vifs_entry {
|
||||
struct list_head list;
|
||||
struct ieee80211_vif *vif;
|
||||
u8 mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct rtw_iter_vifs_data {
|
||||
struct rtw_dev *rtwdev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtw_iter_vifs_data *iter_stas = data;
|
||||
struct rtw_vifs_entry *vifs_entry;
|
||||
|
||||
vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC);
|
||||
if (!vifs_entry)
|
||||
return;
|
||||
|
||||
vifs_entry->vif = vif;
|
||||
ether_addr_copy(vifs_entry->mac, mac);
|
||||
list_add_tail(&vifs_entry->list, &iter_stas->list);
|
||||
}
|
||||
|
||||
void rtw_iterate_vifs(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif),
|
||||
void *data)
|
||||
{
|
||||
struct rtw_iter_vifs_data iter_data;
|
||||
struct rtw_vifs_entry *vif_entry, *tmp;
|
||||
|
||||
/* &rtwdev->mutex makes sure no interfaces can be removed between
|
||||
* collecting the interfaces and iterating over them.
|
||||
*/
|
||||
lockdep_assert_held(&rtwdev->mutex);
|
||||
|
||||
iter_data.rtwdev = rtwdev;
|
||||
INIT_LIST_HEAD(&iter_data.list);
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
rtw_collect_vif_iter, &iter_data);
|
||||
|
||||
list_for_each_entry_safe(vif_entry, tmp, &iter_data.list,
|
||||
list) {
|
||||
list_del_init(&vif_entry->list);
|
||||
iterator(data, vif_entry->mac, vif_entry->vif);
|
||||
kfree(vif_entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
struct rtw_dev;
|
||||
|
||||
#define rtw_iterate_vifs(rtwdev, iterator, data) \
|
||||
ieee80211_iterate_active_interfaces(rtwdev->hw, \
|
||||
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
|
||||
#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \
|
||||
ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \
|
||||
IEEE80211_IFACE_ITER_NORMAL, iterator, data)
|
||||
|
@ -20,6 +17,15 @@ struct rtw_dev;
|
|||
#define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \
|
||||
ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data)
|
||||
|
||||
void rtw_iterate_vifs(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif),
|
||||
void *data);
|
||||
void rtw_iterate_stas(struct rtw_dev *rtwdev,
|
||||
void (*iterator)(void *data,
|
||||
struct ieee80211_sta *sta),
|
||||
void *data);
|
||||
|
||||
static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
|
|
@ -3420,6 +3420,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||
u32 bus_data_size,
|
||||
const struct rtw89_chip_info *chip)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
struct ieee80211_hw *hw;
|
||||
struct rtw89_dev *rtwdev;
|
||||
struct ieee80211_ops *ops;
|
||||
|
@ -3427,7 +3428,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||
u32 early_feat_map = 0;
|
||||
bool no_chanctx;
|
||||
|
||||
rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
|
||||
firmware = rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
|
||||
|
||||
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
|
||||
if (!ops)
|
||||
|
@ -3454,6 +3455,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||
rtwdev->dev = device;
|
||||
rtwdev->ops = ops;
|
||||
rtwdev->chip = chip;
|
||||
rtwdev->fw.firmware = firmware;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
|
||||
no_chanctx ? "without" : "with");
|
||||
|
@ -3462,6 +3464,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||
|
||||
err:
|
||||
kfree(ops);
|
||||
release_firmware(firmware);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
|
||||
|
@ -3469,6 +3472,7 @@ EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
|
|||
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
kfree(rtwdev->ops);
|
||||
release_firmware(rtwdev->fw.firmware);
|
||||
ieee80211_free_hw(rtwdev->hw);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_free_ieee80211_hw);
|
||||
|
|
|
@ -273,29 +273,42 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
|
|||
}
|
||||
}
|
||||
|
||||
void rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map)
|
||||
const struct firmware *
|
||||
rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map)
|
||||
{
|
||||
union {
|
||||
struct rtw89_mfw_hdr mfw_hdr;
|
||||
u8 fw_hdr[RTW89_FW_HDR_SIZE];
|
||||
} buf = {};
|
||||
union rtw89_compat_fw_hdr buf = {};
|
||||
const struct firmware *firmware;
|
||||
bool full_req = false;
|
||||
u32 ver_code;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
|
||||
device, &buf, sizeof(buf), 0);
|
||||
/* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will
|
||||
* be denied (-EPERM). Then, we don't get right firmware things as
|
||||
* expected. So, in this case, we have to request full firmware here.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE))
|
||||
full_req = true;
|
||||
|
||||
if (full_req)
|
||||
ret = request_firmware(&firmware, chip->fw_name, device);
|
||||
else
|
||||
ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
|
||||
device, &buf, sizeof(buf),
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
dev_err(device, "failed to early request firmware: %d\n", ret);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ver_code = buf.mfw_hdr.sig != RTW89_MFW_SIG ?
|
||||
RTW89_FW_HDR_VER_CODE(&buf.fw_hdr) :
|
||||
RTW89_MFW_HDR_VER_CODE(&buf.mfw_hdr);
|
||||
if (full_req)
|
||||
ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data);
|
||||
else
|
||||
ver_code = rtw89_compat_fw_hdr_ver_code(&buf);
|
||||
|
||||
if (!ver_code)
|
||||
goto out;
|
||||
|
||||
|
@ -310,7 +323,11 @@ void rtw89_early_fw_feature_recognize(struct device *device,
|
|||
}
|
||||
|
||||
out:
|
||||
if (full_req)
|
||||
return firmware;
|
||||
|
||||
release_firmware(firmware);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
|
||||
|
@ -617,6 +634,13 @@ int rtw89_load_firmware(struct rtw89_dev *rtwdev)
|
|||
fw->rtwdev = rtwdev;
|
||||
init_completion(&fw->completion);
|
||||
|
||||
if (fw->firmware) {
|
||||
rtw89_debug(rtwdev, RTW89_DBG_FW,
|
||||
"full firmware has been early requested\n");
|
||||
complete_all(&fw->completion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev,
|
||||
GFP_KERNEL, fw, rtw89_load_firmware_cb);
|
||||
if (ret) {
|
||||
|
@ -633,8 +657,14 @@ void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
|
|||
|
||||
rtw89_wait_firmware_completion(rtwdev);
|
||||
|
||||
if (fw->firmware)
|
||||
if (fw->firmware) {
|
||||
release_firmware(fw->firmware);
|
||||
|
||||
/* assign NULL back in case rtw89_free_ieee80211_hw()
|
||||
* try to release the same one again.
|
||||
*/
|
||||
fw->firmware = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define H2C_CAM_LEN 60
|
||||
|
|
|
@ -3291,6 +3291,21 @@ struct fwcmd_hdr {
|
|||
__le32 hdr1;
|
||||
};
|
||||
|
||||
union rtw89_compat_fw_hdr {
|
||||
struct rtw89_mfw_hdr mfw_hdr;
|
||||
u8 fw_hdr[RTW89_FW_HDR_SIZE];
|
||||
};
|
||||
|
||||
static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf)
|
||||
{
|
||||
const union rtw89_compat_fw_hdr *compat = (typeof(compat))fw_buf;
|
||||
|
||||
if (compat->mfw_hdr.sig == RTW89_MFW_SIG)
|
||||
return RTW89_MFW_HDR_VER_CODE(&compat->mfw_hdr);
|
||||
else
|
||||
return RTW89_FW_HDR_VER_CODE(&compat->fw_hdr);
|
||||
}
|
||||
|
||||
#define RTW89_H2C_RF_PAGE_SIZE 500
|
||||
#define RTW89_H2C_RF_PAGE_NUM 3
|
||||
struct rtw89_fw_h2c_rf_reg_info {
|
||||
|
@ -3429,9 +3444,10 @@ struct rtw89_fw_h2c_rf_get_mccch {
|
|||
|
||||
int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev);
|
||||
int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
|
||||
void rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map);
|
||||
const struct firmware *
|
||||
rtw89_early_fw_feature_recognize(struct device *device,
|
||||
const struct rtw89_chip_info *chip,
|
||||
u32 *early_feat_map);
|
||||
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
|
||||
int rtw89_load_firmware(struct rtw89_dev *rtwdev);
|
||||
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
|
||||
|
|
|
@ -3877,11 +3877,16 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev,
|
|||
}
|
||||
|
||||
static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif)
|
||||
struct rtw89_vif *rtwvif, bool enable)
|
||||
{
|
||||
const struct rtw89_port_reg *p = &rtw_port_base;
|
||||
|
||||
rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN);
|
||||
if (enable)
|
||||
rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg,
|
||||
B_AX_PORT_FUNC_EN);
|
||||
else
|
||||
rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg,
|
||||
B_AX_PORT_FUNC_EN);
|
||||
}
|
||||
|
||||
static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev,
|
||||
|
@ -3913,6 +3918,49 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
|
|||
B_AX_TBTT_SHIFT_OFST_MASK, val);
|
||||
}
|
||||
|
||||
static void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev,
|
||||
struct rtw89_vif *rtwvif,
|
||||
struct rtw89_vif *rtwvif_src, u8 offset,
|
||||
int *n_offset)
|
||||
{
|
||||
u32 val, reg;
|
||||
|
||||
if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src)
|
||||
return;
|
||||
|
||||
/* adjust offset randomly to avoid beacon conflict */
|
||||
offset = offset - offset / 4 + get_random_u32() % (offset / 2);
|
||||
val = RTW89_PORT_OFFSET_MS_TO_32US((*n_offset)++, offset);
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_PORT0_TSF_SYNC + rtwvif->port * 4,
|
||||
rtwvif->mac_idx);
|
||||
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port);
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val);
|
||||
rtw89_write32_set(rtwdev, reg, B_AX_SYNC_NOW);
|
||||
}
|
||||
|
||||
static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_vif *src = NULL, *tmp;
|
||||
u8 offset = 100, vif_aps = 0;
|
||||
int n_offset = 1;
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, tmp) {
|
||||
if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA)
|
||||
src = tmp;
|
||||
if (tmp->net_type == RTW89_NET_TYPE_AP_MODE)
|
||||
vif_aps++;
|
||||
}
|
||||
|
||||
if (vif_aps == 0)
|
||||
return;
|
||||
|
||||
offset /= (vif_aps + 1);
|
||||
|
||||
rtw89_for_each_rtwvif(rtwdev, tmp)
|
||||
rtw89_mac_port_tsf_sync(rtwdev, tmp, src, offset, &n_offset);
|
||||
}
|
||||
|
||||
int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
int ret;
|
||||
|
@ -3932,6 +3980,10 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rtw89_cam_init(rtwdev, rtwvif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -3990,7 +4042,8 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
|||
rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_func_en(rtwdev, rtwvif);
|
||||
rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true);
|
||||
rtw89_mac_port_tsf_resync_all(rtwdev);
|
||||
fsleep(BCN_ERLY_SET_DLY);
|
||||
rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif);
|
||||
|
||||
|
@ -4041,6 +4094,11 @@ void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
|
|||
rtw89_write32_set(rtwdev, reg, B_AX_RXTRIG_RU26_DIS);
|
||||
}
|
||||
|
||||
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, false);
|
||||
}
|
||||
|
||||
int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -168,6 +168,8 @@ enum rtw89_mac_ax_l0_to_l1_event {
|
|||
MAC_AX_L0_TO_L1_EVENT_MAX = 15,
|
||||
};
|
||||
|
||||
#define RTW89_PORT_OFFSET_MS_TO_32US(n, shift_ms) ((n) * (shift_ms) * 1000 / 32)
|
||||
|
||||
enum rtw89_mac_dbg_port_sel {
|
||||
/* CMAC 0 related */
|
||||
RTW89_DBG_PORT_SEL_PTCL_C0 = 0,
|
||||
|
@ -906,6 +908,7 @@ int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
|
|||
int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
|
||||
void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_vif *vif);
|
||||
void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
|
||||
int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif);
|
||||
void rtw89_mac_disable_cpu(struct rtw89_dev *rtwdev);
|
||||
int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw);
|
||||
|
|
|
@ -125,6 +125,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
|
|||
RTW89_PORT_NUM);
|
||||
if (rtwvif->port == RTW89_PORT_NUM) {
|
||||
ret = -ENOSPC;
|
||||
list_del_init(&rtwvif->list);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -138,6 +139,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
|
|||
ret = rtw89_mac_add_vif(rtwdev, rtwvif);
|
||||
if (ret) {
|
||||
rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port);
|
||||
list_del_init(&rtwvif->list);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -454,6 +456,7 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
|
||||
|
||||
mutex_lock(&rtwdev->mutex);
|
||||
rtw89_mac_stop_ap(rtwdev, rtwvif);
|
||||
rtw89_fw_h2c_assoc_cmac_tbl(rtwdev, vif, NULL);
|
||||
rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true);
|
||||
mutex_unlock(&rtwdev->mutex);
|
||||
|
|
|
@ -2048,6 +2048,23 @@
|
|||
#define B_AX_PTCL_TOP_ERR_IND BIT(1)
|
||||
#define B_AX_SCHEDULE_TOP_ERR_IND BIT(0)
|
||||
|
||||
#define R_AX_PORT0_TSF_SYNC 0xC2A0
|
||||
#define R_AX_PORT0_TSF_SYNC_C1 0xE2A0
|
||||
#define R_AX_PORT1_TSF_SYNC 0xC2A4
|
||||
#define R_AX_PORT1_TSF_SYNC_C1 0xE2A4
|
||||
#define R_AX_PORT2_TSF_SYNC 0xC2A8
|
||||
#define R_AX_PORT2_TSF_SYNC_C1 0xE2A8
|
||||
#define R_AX_PORT3_TSF_SYNC 0xC2AC
|
||||
#define R_AX_PORT3_TSF_SYNC_C1 0xE2AC
|
||||
#define R_AX_PORT4_TSF_SYNC 0xC2B0
|
||||
#define R_AX_PORT4_TSF_SYNC_C1 0xE2B0
|
||||
#define B_AX_SYNC_NOW BIT(30)
|
||||
#define B_AX_SYNC_ONCE BIT(29)
|
||||
#define B_AX_SYNC_AUTO BIT(28)
|
||||
#define B_AX_SYNC_PORT_SRC GENMASK(26, 24)
|
||||
#define B_AX_SYNC_PORT_OFFSET_SIGN BIT(18)
|
||||
#define B_AX_SYNC_PORT_OFFSET_VAL GENMASK(17, 0)
|
||||
|
||||
#define R_AX_MACID_SLEEP_0 0xC2C0
|
||||
#define R_AX_MACID_SLEEP_0_C1 0xE2C0
|
||||
#define B_AX_MACID31_0_SLEEP_SH 0
|
||||
|
|
Loading…
Reference in New Issue