summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml39
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j274.dts4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j293.dts4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j313.dts4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j456.dts4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j457.dts4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-jxxx.dtsi2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h19
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c12
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c116
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c12
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c430
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c38
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c23
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw.h13
-rw-r--r--drivers/net/wireless/intel/ipw2x00/libipw_rx.c10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/init.c9
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h3
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_cmd.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_event.c6
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/coex.c805
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c73
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h72
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c62
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c262
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h45
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c92
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h44
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c51
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c148
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h19
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c39
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h36
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c56
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852ae.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c61
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852ce.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c4
-rw-r--r--drivers/net/wireless/rndis_wlan.c5
-rw-r--r--include/linux/bcma/bcma_driver_chipcommon.h1
48 files changed, 2108 insertions, 555 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
index 53b4153d9bfc..fec1cc9b9a08 100644
--- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/net/wireless/brcm,bcm4329-fmac.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Broadcom BCM4329 family fullmac wireless SDIO devices
+title: Broadcom BCM4329 family fullmac wireless SDIO/PCIE devices
maintainers:
- Arend van Spriel <arend@broadcom.com>
@@ -41,11 +41,17 @@ properties:
- cypress,cyw4373-fmac
- cypress,cyw43012-fmac
- const: brcm,bcm4329-fmac
- - const: brcm,bcm4329-fmac
+ - enum:
+ - brcm,bcm4329-fmac
+ - pci14e4,43dc # BCM4355
+ - pci14e4,4464 # BCM4364
+ - pci14e4,4488 # BCM4377
+ - pci14e4,4425 # BCM4378
+ - pci14e4,4433 # BCM4387
reg:
- description: SDIO function number for the device, for most cases
- this will be 1.
+ description: SDIO function number for the device (for most cases
+ this will be 1) or PCI device identifier.
interrupts:
maxItems: 1
@@ -85,6 +91,31 @@ properties:
takes precedence.
type: boolean
+ brcm,cal-blob:
+ $ref: /schemas/types.yaml#/definitions/uint8-array
+ description: A per-device calibration blob for the Wi-Fi radio. This
+ should be filled in by the bootloader from platform configuration
+ data, if necessary, and will be uploaded to the device if present.
+
+ brcm,board-type:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Overrides the board type, which is normally the compatible of
+ the root node. This can be used to decouple the overall system board or
+ device name from the board type for WiFi purposes, which is used to
+ construct firmware and NVRAM configuration filenames, allowing for
+ multiple devices that share the same module or characteristics for the
+ WiFi subsystem to share the same firmware/NVRAM files. On Apple platforms,
+ this should be the Apple module-instance codename prefixed by "apple,",
+ e.g. "apple,honshu".
+
+ apple,antenna-sku:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Antenna SKU used to identify a specific antenna configuration
+ on Apple platforms. This is use to build firmware filenames, to allow
+ platforms with different antenna configs to have different firmware and/or
+ NVRAM. This would normally be filled in by the bootloader from platform
+ configuration data.
+
required:
- compatible
- reg
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index 2cd429efba5b..c1f3ba9c39f6 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -21,6 +21,10 @@
};
};
+&wifi0 {
+ brcm,board-type = "apple,atlantisb";
+};
+
/*
* Force the bus number assignments so that we can declare some of the
* on-board devices and properties that are populated by the bootloader
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 49cdf4b560a3..ecb10d237a05 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -17,6 +17,10 @@
model = "Apple MacBook Pro (13-inch, M1, 2020)";
};
+&wifi0 {
+ brcm,board-type = "apple,honshu";
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index b0ebb45bdb6f..df741737b8e6 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -17,6 +17,10 @@
model = "Apple MacBook Air (M1, 2020)";
};
+&wifi0 {
+ brcm,board-type = "apple,shikoku";
+};
+
/*
* Remove unused PCIe ports and disable the associated DARTs.
*/
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 884fddf7d363..8c6bf9592510 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -21,6 +21,10 @@
};
};
+&wifi0 {
+ brcm,board-type = "apple,capri";
+};
+
&i2c0 {
hpm2: usb-pd@3b {
compatible = "apple,cd321x";
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index d7c622931627..fe7c0aaf7d62 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -21,6 +21,10 @@
};
};
+&wifi0 {
+ brcm,board-type = "apple,santorini";
+};
+
/*
* Force the bus number assignments so that we can declare some of the
* on-board devices and properties that are populated by the bootloader
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index fe2ae40fa9dd..3d15b8e2a6c1 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -71,8 +71,10 @@
&port00 {
bus-range = <1 1>;
wifi0: network@0,0 {
+ compatible = "pci14e4,4425";
reg = <0x10000 0x0 0x0 0x0 0x0>;
/* To be filled by the loader */
local-mac-address = [00 00 00 00 00 00];
+ apple,antenna-sku = "XX";
};
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index ae5af76e2568..2208ab3aa795 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -6,6 +6,8 @@
#ifndef BRCMFMAC_BUS_H
#define BRCMFMAC_BUS_H
+#include <linux/kernel.h>
+#include <linux/firmware.h>
#include "debug.h"
/* IDs of the 6 default common rings of msgbuf protocol */
@@ -34,6 +36,11 @@ enum brcmf_bus_protocol_type {
BRCMF_PROTO_MSGBUF
};
+/* Firmware blobs that may be available */
+enum brcmf_blob_type {
+ BRCMF_BLOB_CLM,
+};
+
struct brcmf_mp_device;
struct brcmf_bus_dcmd {
@@ -60,7 +67,7 @@ struct brcmf_bus_dcmd {
* @wowl_config: specify if dongle is configured for wowl when going to suspend
* @get_ramsize: obtain size of device memory.
* @get_memdump: obtain device memory dump in provided buffer.
- * @get_fwname: obtain firmware name.
+ * @get_blob: obtain a firmware blob.
*
* This structure provides an abstract interface towards the
* bus specific driver. For control messages to common driver
@@ -77,8 +84,8 @@ struct brcmf_bus_ops {
void (*wowl_config)(struct device *dev, bool enabled);
size_t (*get_ramsize)(struct device *dev);
int (*get_memdump)(struct device *dev, void *data, size_t len);
- int (*get_fwname)(struct device *dev, const char *ext,
- unsigned char *fw_name);
+ int (*get_blob)(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type);
void (*debugfs_create)(struct device *dev);
int (*reset)(struct device *dev);
};
@@ -220,10 +227,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
}
static inline
-int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
- unsigned char *fw_name)
+int brcmf_bus_get_blob(struct brcmf_bus *bus, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
- return bus->ops->get_fwname(bus->dev, ext, fw_name);
+ return bus->ops->get_blob(bus->dev, fw, type);
}
static inline
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 23295fceb062..3026166a56c1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -733,6 +733,8 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
return 0x160000;
case CY_CC_43752_CHIP_ID:
return 0x170000;
+ case BRCM_CC_4378_CHIP_ID:
+ return 0x352000;
default:
brcmf_err("unknown chip: %s\n", ci->pub.name);
break;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 372deeb69477..74020fa10065 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -123,7 +123,6 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
struct brcmf_bus *bus = drvr->bus_if;
struct brcmf_dload_data_le *chunk_buf;
const struct firmware *clm = NULL;
- u8 clm_name[BRCMF_FW_NAME_LEN];
u32 chunk_len;
u32 datalen;
u32 cumulative_len;
@@ -133,15 +132,8 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
brcmf_dbg(TRACE, "Enter\n");
- memset(clm_name, 0, sizeof(clm_name));
- err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
- if (err) {
- bphy_err(drvr, "get CLM blob file name failed (%d)\n", err);
- return err;
- }
-
- err = firmware_request_nowarn(&clm, clm_name, bus->dev);
- if (err) {
+ err = brcmf_bus_get_blob(bus, &clm, BRCMF_BLOB_CLM);
+ if (err || !clm) {
brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
err);
return 0;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 6c5a22a32a96..aa25abffcc7d 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -53,6 +53,7 @@ struct brcmf_mp_device {
struct brcmfmac_pd_cc *country_codes;
const char *board_type;
unsigned char mac[ETH_ALEN];
+ const char *antenna_sku;
union {
struct brcmfmac_sdio_pd sdio;
} bus;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 15e99d8865bd..f2207793f6e2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -21,6 +21,8 @@
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
#define BRCMF_FW_DEFAULT_BOARDREV "boardrev=0xff"
+#define BRCMF_FW_MACADDR_FMT "macaddr=%pM"
+#define BRCMF_FW_MACADDR_LEN (7 + ETH_ALEN * 3)
enum nvram_parser_state {
IDLE,
@@ -44,6 +46,7 @@ enum nvram_parser_state {
* @multi_dev_v1: detect pcie multi device v1 (compressed).
* @multi_dev_v2: detect pcie multi device v2.
* @boardrev_found: nvram contains boardrev information.
+ * @strip_mac: strip the MAC address.
*/
struct nvram_parser {
enum nvram_parser_state state;
@@ -57,6 +60,7 @@ struct nvram_parser {
bool multi_dev_v1;
bool multi_dev_v2;
bool boardrev_found;
+ bool strip_mac;
};
/*
@@ -121,6 +125,10 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
nvp->multi_dev_v2 = true;
if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
nvp->boardrev_found = true;
+ /* strip macaddr if platform MAC overrides */
+ if (nvp->strip_mac &&
+ strncmp(&nvp->data[nvp->entry], "macaddr", 7) == 0)
+ st = COMMENT;
} else if (!is_nvram_char(c) || c == ' ') {
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
nvp->line, nvp->column);
@@ -209,6 +217,7 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
size = data_len;
/* Add space for properties we may add */
size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;
+ size += BRCMF_FW_MACADDR_LEN + 1;
/* Alloc for extra 0 byte + roundup by 4 + length field */
size += 1 + 3 + sizeof(u32);
nvp->nvram = kzalloc(size, GFP_KERNEL);
@@ -368,22 +377,37 @@ static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
nvp->nvram_len++;
}
+static void brcmf_fw_add_macaddr(struct nvram_parser *nvp, u8 *mac)
+{
+ int len;
+
+ len = scnprintf(&nvp->nvram[nvp->nvram_len], BRCMF_FW_MACADDR_LEN + 1,
+ BRCMF_FW_MACADDR_FMT, mac);
+ WARN_ON(len != BRCMF_FW_MACADDR_LEN);
+ nvp->nvram_len += len + 1;
+}
+
/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
* and ending in a NUL. Removes carriage returns, empty lines, comment lines,
* and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
* End of buffer is completed with token identifying length of buffer.
*/
static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
- u32 *new_length, u16 domain_nr, u16 bus_nr)
+ u32 *new_length, u16 domain_nr, u16 bus_nr,
+ struct device *dev)
{
struct nvram_parser nvp;
u32 pad;
u32 token;
__le32 token_le;
+ u8 mac[ETH_ALEN];
if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
return NULL;
+ if (eth_platform_get_mac_address(dev, mac) == 0)
+ nvp.strip_mac = true;
+
while (nvp.pos < data_len) {
nvp.state = nv_parser_states[nvp.state](&nvp);
if (nvp.state == END)
@@ -404,6 +428,9 @@ static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
brcmf_fw_add_defaults(&nvp);
+ if (nvp.strip_mac)
+ brcmf_fw_add_macaddr(&nvp, mac);
+
pad = nvp.nvram_len;
*new_length = roundup(nvp.nvram_len + 1, 4);
while (pad != *new_length) {
@@ -430,6 +457,7 @@ struct brcmf_fw {
struct device *dev;
struct brcmf_fw_request *req;
u32 curpos;
+ unsigned int board_index;
void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
};
@@ -537,7 +565,8 @@ static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (data)
nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
fwctx->req->domain_nr,
- fwctx->req->bus_nr);
+ fwctx->req->bus_nr,
+ fwctx->dev);
if (free_bcm47xx_nvram)
bcm47xx_nvram_release_contents(data);
@@ -587,39 +616,50 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
static char *brcm_alt_fw_path(const char *path, const char *board_type)
{
- char alt_path[BRCMF_FW_NAME_LEN];
- char suffix[5];
+ char base[BRCMF_FW_NAME_LEN];
+ const char *suffix;
+ char *ret;
+
+ if (!board_type)
+ return NULL;
- strscpy(alt_path, path, BRCMF_FW_NAME_LEN);
- /* At least one character + suffix */
- if (strlen(alt_path) < 5)
+ suffix = strrchr(path, '.');
+ if (!suffix || suffix == path)
return NULL;
- /* strip .txt or .bin at the end */
- strscpy(suffix, alt_path + strlen(alt_path) - 4, 5);
- alt_path[strlen(alt_path) - 4] = 0;
- strlcat(alt_path, ".", BRCMF_FW_NAME_LEN);
- strlcat(alt_path, board_type, BRCMF_FW_NAME_LEN);
- strlcat(alt_path, suffix, BRCMF_FW_NAME_LEN);
+ /* strip extension at the end */
+ strscpy(base, path, BRCMF_FW_NAME_LEN);
+ base[suffix - path] = 0;
- return kstrdup(alt_path, GFP_KERNEL);
+ ret = kasprintf(GFP_KERNEL, "%s.%s%s", base, board_type, suffix);
+ if (!ret)
+ brcmf_err("out of memory allocating firmware path for '%s'\n",
+ path);
+
+ brcmf_dbg(TRACE, "FW alt path: %s\n", ret);
+
+ return ret;
}
static int brcmf_fw_request_firmware(const struct firmware **fw,
struct brcmf_fw *fwctx)
{
struct brcmf_fw_item *cur = &fwctx->req->items[fwctx->curpos];
+ unsigned int i;
int ret;
- /* Files can be board-specific, first try a board-specific path */
- if (cur->type == BRCMF_FW_TYPE_NVRAM && fwctx->req->board_type) {
+ /* Files can be board-specific, first try board-specific paths */
+ for (i = 0; i < ARRAY_SIZE(fwctx->req->board_types); i++) {
char *alt_path;
- alt_path = brcm_alt_fw_path(cur->path, fwctx->req->board_type);
+ if (!fwctx->req->board_types[i])
+ goto fallback;
+ alt_path = brcm_alt_fw_path(cur->path,
+ fwctx->req->board_types[i]);
if (!alt_path)
goto fallback;
- ret = request_firmware(fw, alt_path, fwctx->dev);
+ ret = firmware_request_nowarn(fw, alt_path, fwctx->dev);
kfree(alt_path);
if (ret == 0)
return ret;
@@ -653,15 +693,40 @@ static void brcmf_fw_request_done_alt_path(const struct firmware *fw, void *ctx)
{
struct brcmf_fw *fwctx = ctx;
struct brcmf_fw_item *first = &fwctx->req->items[0];
+ const char *board_type, *alt_path;
int ret = 0;
- /* Fall back to canonical path if board firmware not found */
- if (!fw)
- ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+ if (fw) {
+ brcmf_fw_request_done(fw, ctx);
+ return;
+ }
+
+ /* Try next board firmware */
+ if (fwctx->board_index < ARRAY_SIZE(fwctx->req->board_types)) {
+ board_type = fwctx->req->board_types[fwctx->board_index++];
+ if (!board_type)
+ goto fallback;
+ alt_path = brcm_alt_fw_path(first->path, board_type);
+ if (!alt_path)
+ goto fallback;
+
+ ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
- brcmf_fw_request_done);
+ brcmf_fw_request_done_alt_path);
+ kfree(alt_path);
+
+ if (ret < 0)
+ brcmf_fw_request_done(fw, ctx);
+ return;
+ }
- if (fw || ret < 0)
+fallback:
+ /* Fall back to canonical path if board firmware not found */
+ ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+ fwctx->dev, GFP_KERNEL, fwctx,
+ brcmf_fw_request_done);
+
+ if (ret < 0)
brcmf_fw_request_done(fw, ctx);
}
@@ -705,10 +770,11 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
fwctx->done = fw_cb;
/* First try alternative board-specific path if any */
- if (fwctx->req->board_type)
+ if (fwctx->req->board_types[0])
alt_path = brcm_alt_fw_path(first->path,
- fwctx->req->board_type);
+ fwctx->req->board_types[0]);
if (alt_path) {
+ fwctx->board_index++;
ret = request_firmware_nowait(THIS_MODULE, true, alt_path,
fwctx->dev, GFP_KERNEL, fwctx,
brcmf_fw_request_done_alt_path);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index e290dec9c53d..1266cbaee072 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -11,6 +11,8 @@
#define BRCMF_FW_DEFAULT_PATH "brcm/"
+#define BRCMF_FW_MAX_BOARD_TYPES 8
+
/**
* struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
* filename and nvram filename. Each bus type implementation should create
@@ -66,7 +68,7 @@ struct brcmf_fw_request {
u16 domain_nr;
u16 bus_nr;
u32 n_items;
- const char *board_type;
+ const char *board_types[BRCMF_FW_MAX_BOARD_TYPES];
struct brcmf_fw_item items[];
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
index 2e322edbb907..6a849f4a94dd 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
@@ -8,10 +8,10 @@
#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64
-#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 1024
#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64
#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024
-#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 1024
#define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
index 79388d49c256..a83699de01ec 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -70,14 +70,24 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
{
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
struct device_node *root, *np = dev->of_node;
+ const char *prop;
int irq;
int err;
u32 irqf;
u32 val;
+ /* Apple ARM64 platforms have their own idea of board type, passed in
+ * via the device tree. They also have an antenna SKU parameter
+ */
+ if (!of_property_read_string(np, "brcm,board-type", &prop))
+ settings->board_type = prop;
+
+ if (!of_property_read_string(np, "apple,antenna-sku", &prop))
+ settings->antenna_sku = prop;
+
/* Set board-type to the first string of the machine compatible prop */
root = of_find_node_by_path("/");
- if (root) {
+ if (root && !settings->board_type) {
char *board_type;
const char *tmp;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 97f0f13dfe50..f98641bb1528 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -59,6 +59,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
+BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie");
/* firmware config files */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt");
@@ -66,6 +67,7 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.txt");
/* per-board firmware binaries */
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.bin");
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.*.clm_blob");
static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
@@ -87,6 +89,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C),
BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
+ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFFF, 4378B1), /* revision ID 3 */
};
#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */
@@ -118,6 +121,12 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140
#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144
+#define BRCMF_PCIE_64_PCIE2REG_INTMASK 0xC14
+#define BRCMF_PCIE_64_PCIE2REG_MAILBOXINT 0xC30
+#define BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK 0xC34
+#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0 0xA20
+#define BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1 0xA24
+
#define BRCMF_PCIE2_INTA 0x01
#define BRCMF_PCIE2_INTB 0x02
@@ -137,6 +146,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_MB_INT_D2H3_DB0 0x400000
#define BRCMF_PCIE_MB_INT_D2H3_DB1 0x800000
+#define BRCMF_PCIE_MB_INT_FN0 (BRCMF_PCIE_MB_INT_FN0_0 | \
+ BRCMF_PCIE_MB_INT_FN0_1)
#define BRCMF_PCIE_MB_INT_D2H_DB (BRCMF_PCIE_MB_INT_D2H0_DB0 | \
BRCMF_PCIE_MB_INT_D2H0_DB1 | \
BRCMF_PCIE_MB_INT_D2H1_DB0 | \
@@ -146,6 +157,40 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_PCIE_MB_INT_D2H3_DB0 | \
BRCMF_PCIE_MB_INT_D2H3_DB1)
+#define BRCMF_PCIE_64_MB_INT_D2H0_DB0 0x1
+#define BRCMF_PCIE_64_MB_INT_D2H0_DB1 0x2
+#define BRCMF_PCIE_64_MB_INT_D2H1_DB0 0x4
+#define BRCMF_PCIE_64_MB_INT_D2H1_DB1 0x8
+#define BRCMF_PCIE_64_MB_INT_D2H2_DB0 0x10
+#define BRCMF_PCIE_64_MB_INT_D2H2_DB1 0x20
+#define BRCMF_PCIE_64_MB_INT_D2H3_DB0 0x40
+#define BRCMF_PCIE_64_MB_INT_D2H3_DB1 0x80
+#define BRCMF_PCIE_64_MB_INT_D2H4_DB0 0x100
+#define BRCMF_PCIE_64_MB_INT_D2H4_DB1 0x200
+#define BRCMF_PCIE_64_MB_INT_D2H5_DB0 0x400
+#define BRCMF_PCIE_64_MB_INT_D2H5_DB1 0x800
+#define BRCMF_PCIE_64_MB_INT_D2H6_DB0 0x1000
+#define BRCMF_PCIE_64_MB_INT_D2H6_DB1 0x2000
+#define BRCMF_PCIE_64_MB_INT_D2H7_DB0 0x4000
+#define BRCMF_PCIE_64_MB_INT_D2H7_DB1 0x8000
+
+#define BRCMF_PCIE_64_MB_INT_D2H_DB (BRCMF_PCIE_64_MB_INT_D2H0_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H0_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H1_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H1_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H2_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H2_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H3_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H3_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H4_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H4_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H5_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H5_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H6_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H6_DB1 | \
+ BRCMF_PCIE_64_MB_INT_D2H7_DB0 | \
+ BRCMF_PCIE_64_MB_INT_D2H7_DB1)
+
#define BRCMF_PCIE_SHARED_VERSION_7 7
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
#define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7
@@ -255,12 +300,24 @@ struct brcmf_pcie_core_info {
u32 wrapbase;
};
+#define BRCMF_OTP_MAX_PARAM_LEN 16
+
+struct brcmf_otp_params {
+ char module[BRCMF_OTP_MAX_PARAM_LEN];
+ char vendor[BRCMF_OTP_MAX_PARAM_LEN];
+ char version[BRCMF_OTP_MAX_PARAM_LEN];
+ bool valid;
+};
+
struct brcmf_pciedev_info {
enum brcmf_pcie_state state;
bool in_irq;
struct pci_dev *pdev;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
+ char clm_name[BRCMF_FW_NAME_LEN];
+ const struct firmware *clm_fw;
+ const struct brcmf_pcie_reginfo *reginfo;
void __iomem *regs;
void __iomem *tcm;
u32 ram_base;
@@ -280,6 +337,7 @@ struct brcmf_pciedev_info {
void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
u16 value);
struct brcmf_mp_device *settings;
+ struct brcmf_otp_params otp;
};
struct brcmf_pcie_ringbuf {
@@ -346,11 +404,49 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
};
+struct brcmf_pcie_reginfo {
+ u32 intmask;
+ u32 mailboxint;
+ u32 mailboxmask;
+ u32 h2d_mailbox_0;
+ u32 h2d_mailbox_1;
+ u32 int_d2h_db;
+ u32 int_fn0;
+};
+
+static const struct brcmf_pcie_reginfo brcmf_reginfo_default = {
+ .intmask = BRCMF_PCIE_PCIE2REG_INTMASK,
+ .mailboxint = BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ .mailboxmask = BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+ .h2d_mailbox_0 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0,
+ .h2d_mailbox_1 = BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1,
+ .int_d2h_db = BRCMF_PCIE_MB_INT_D2H_DB,
+ .int_fn0 = BRCMF_PCIE_MB_INT_FN0,
+};
+
+static const struct brcmf_pcie_reginfo brcmf_reginfo_64 = {
+ .intmask = BRCMF_PCIE_64_PCIE2REG_INTMASK,
+ .mailboxint = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT,
+ .mailboxmask = BRCMF_PCIE_64_PCIE2REG_MAILBOXMASK,
+ .h2d_mailbox_0 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_0,
+ .h2d_mailbox_1 = BRCMF_PCIE_64_PCIE2REG_H2D_MAILBOX_1,
+ .int_d2h_db = BRCMF_PCIE_64_MB_INT_D2H_DB,
+ .int_fn0 = 0,
+};
+
static void brcmf_pcie_setup(struct device *dev, int ret,
struct brcmf_fw_request *fwreq);
static struct brcmf_fw_request *
brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo);
+static u16
+brcmf_pcie_read_reg16(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+{
+ void __iomem *address = devinfo->regs + reg_offset;
+
+ return ioread16(address);
+}
+
static u32
brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
{
@@ -496,6 +592,8 @@ brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
}
+#define READCC32(devinfo, reg) brcmf_pcie_read_reg32(devinfo, \
+ CHIPCREGOFFS(reg))
#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
CHIPCREGOFFS(reg), value)
@@ -779,30 +877,29 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo,
static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
{
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask, 0);
}
static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
{
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
- BRCMF_PCIE_MB_INT_D2H_DB |
- BRCMF_PCIE_MB_INT_FN0_0 |
- BRCMF_PCIE_MB_INT_FN0_1);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxmask,
+ devinfo->reginfo->int_d2h_db |
+ devinfo->reginfo->int_fn0);
}
static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
{
if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
brcmf_pcie_write_reg32(devinfo,
- BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
+ devinfo->reginfo->h2d_mailbox_1, 1);
}
static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
{
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
+ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint)) {
brcmf_pcie_intr_disable(devinfo);
brcmf_dbg(PCIE, "Enter\n");
return IRQ_WAKE_THREAD;
@@ -817,15 +914,14 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
u32 status;
devinfo->in_irq = true;
- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
brcmf_dbg(PCIE, "Enter %x\n", status);
if (status) {
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint,
status);
- if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
- BRCMF_PCIE_MB_INT_FN0_1))
+ if (status & devinfo->reginfo->int_fn0)
brcmf_pcie_handle_mb_data(devinfo);
- if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
+ if (status & devinfo->reginfo->int_d2h_db) {
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
brcmf_proto_msgbuf_rx_trigger(
&devinfo->pdev->dev);
@@ -884,8 +980,8 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
if (devinfo->in_irq)
brcmf_err(bus, "Still in IRQ (processing) !!!\n");
- status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
+ status = brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->mailboxint);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->mailboxint, status);
devinfo->irq_allocated = false;
}
@@ -937,7 +1033,7 @@ static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
brcmf_dbg(PCIE, "RING !\n");
/* Any arbitrary value will do, lets use 1 */
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
+ brcmf_pcie_write_reg32(devinfo, devinfo->reginfo->h2d_mailbox_0, 1);
return 0;
}
@@ -1382,23 +1478,25 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
return 0;
}
-static
-int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_pcie_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
- brcmf_pcie_fwnames,
- ARRAY_SIZE(brcmf_pcie_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
+ switch (type) {
+ case BRCMF_BLOB_CLM:
+ *fw = devinfo->clm_fw;
+ devinfo->clm_fw = NULL;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (!*fw)
+ return -ENOENT;
- kfree(fwreq);
return 0;
}
@@ -1445,7 +1543,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.wowl_config = brcmf_pcie_wowl_config,
.get_ramsize = brcmf_pcie_get_ramsize,
.get_memdump = brcmf_pcie_get_memdump,
- .get_fwname = brcmf_pcie_get_fwname,
+ .get_blob = brcmf_pcie_get_blob,
.reset = brcmf_pcie_reset,
};
@@ -1698,15 +1796,22 @@ static int brcmf_pcie_buscoreprep(void *ctx)
static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
{
struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
- u32 val;
+ struct brcmf_core *core;
+ u32 val, reg;
devinfo->ci = chip;
brcmf_pcie_reset_device(devinfo);
- val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+ /* reginfo is not ready yet */
+ core = brcmf_chip_get_core(chip, BCMA_CORE_PCIE2);
+ if (core->rev >= 64)
+ reg = BRCMF_PCIE_64_PCIE2REG_MAILBOXINT;
+ else
+ reg = BRCMF_PCIE_PCIE2REG_MAILBOXINT;
+
+ val = brcmf_pcie_read_reg32(devinfo, reg);
if (val != 0xffffffff)
- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
- val);
+ brcmf_pcie_write_reg32(devinfo, reg, val);
return 0;
}
@@ -1729,8 +1834,206 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
.write32 = brcmf_pcie_buscore_write32,
};
+#define BRCMF_OTP_SYS_VENDOR 0x15
+#define BRCMF_OTP_BRCM_CIS 0x80
+
+#define BRCMF_OTP_VENDOR_HDR 0x00000008
+
+static int
+brcmf_pcie_parse_otp_sys_vendor(struct brcmf_pciedev_info *devinfo,
+ u8 *data, size_t size)
+{
+ int idx = 4;
+ const char *chip_params;
+ const char *board_params;
+ const char *p;
+
+ /* 4-byte header and two empty strings */
+ if (size < 6)
+ return -EINVAL;
+
+ if (get_unaligned_le32(data) != BRCMF_OTP_VENDOR_HDR)
+ return -EINVAL;
+
+ chip_params = &data[idx];
+
+ /* Skip first string, including terminator */
+ idx += strnlen(chip_params, size - idx) + 1;
+ if (idx >= size)
+ return -EINVAL;
+
+ board_params = &data[idx];
+
+ /* Skip to terminator of second string */
+ idx += strnlen(board_params, size - idx);
+ if (idx >= size)
+ return -EINVAL;
+
+ /* At this point both strings are guaranteed NUL-terminated */
+ brcmf_dbg(PCIE, "OTP: chip_params='%s' board_params='%s'\n",
+ chip_params, board_params);
+
+ p = skip_spaces(board_params);
+ while (*p) {
+ char tag = *p++;
+ const char *end;
+ size_t len;
+
+ if (*p++ != '=') /* implicit NUL check */
+ return -EINVAL;
+
+ /* *p might be NUL here, if so end == p and len == 0 */
+ end = strchrnul(p, ' ');
+ len = end - p;
+
+ /* leave 1 byte for NUL in destination string */
+ if (len > (BRCMF_OTP_MAX_PARAM_LEN - 1))
+ return -EINVAL;
+
+ /* Copy len characters plus a NUL terminator */
+ switch (tag) {
+ case 'M':
+ strscpy(devinfo->otp.module, p, len + 1);
+ break;
+ case 'V':
+ strscpy(devinfo->otp.vendor, p, len + 1);
+ break;
+ case 'm':
+ strscpy(devinfo->otp.version, p, len + 1);
+ break;
+ }
+
+ /* Skip to next arg, if any */
+ p = skip_spaces(end);
+ }
+
+ brcmf_dbg(PCIE, "OTP: module=%s vendor=%s version=%s\n",
+ devinfo->otp.module, devinfo->otp.vendor,
+ devinfo->otp.version);
+
+ if (!devinfo->otp.module[0] ||
+ !devinfo->otp.vendor[0] ||
+ !devinfo->otp.version[0])
+ return -EINVAL;
+
+ devinfo->otp.valid = true;
+ return 0;
+}
+
+static int
+brcmf_pcie_parse_otp(struct brcmf_pciedev_info *devinfo, u8 *otp, size_t size)
+{
+ int p = 0;
+ int ret = -EINVAL;
+
+ brcmf_dbg(PCIE, "parse_otp size=%zd\n", size);
+
+ while (p < (size - 1)) {
+ u8 type = otp[p];
+ u8 length = otp[p + 1];
+
+ if (type == 0)
+ break;
+
+ if ((p + 2 + length) > size)
+ break;
+
+ switch (type) {
+ case BRCMF_OTP_SYS_VENDOR:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): SYS_VENDOR\n",
+ p, length);
+ ret = brcmf_pcie_parse_otp_sys_vendor(devinfo,
+ &otp[p + 2],
+ length);
+ break;
+ case BRCMF_OTP_BRCM_CIS:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): BRCM_CIS\n",
+ p, length);
+ break;
+ default:
+ brcmf_dbg(PCIE, "OTP @ 0x%x (%d): Unknown type 0x%x\n",
+ p, length, type);
+ break;
+ }
+
+ p += 2 + length;
+ }
+
+ return ret;
+}
+
+static int brcmf_pcie_read_otp(struct brcmf_pciedev_info *devinfo)
+{
+ const struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
+ u32 coreid, base, words, idx, sromctl;
+ u16 *otp;
+ struct brcmf_core *core;
+ int ret;
+
+ switch (devinfo->ci->chip) {
+ case BRCM_CC_4378_CHIP_ID:
+ coreid = BCMA_CORE_GCI;
+ base = 0x1120;
+ words = 0x170;
+ break;
+ default:
+ /* OTP not supported on this chip */
+ return 0;
+ }
+
+ core = brcmf_chip_get_core(devinfo->ci, coreid);
+ if (!core) {
+ brcmf_err(bus, "No OTP core\n");
+ return -ENODEV;
+ }
+
+ if (coreid == BCMA_CORE_CHIPCOMMON) {
+ /* Chips with OTP accessed via ChipCommon need additional
+ * handling to access the OTP
+ */
+ brcmf_pcie_select_core(devinfo, coreid);
+ sromctl = READCC32(devinfo, sromcontrol);
+
+ if (!(sromctl & BCMA_CC_SROM_CONTROL_OTP_PRESENT)) {
+ /* Chip lacks OTP, try without it... */
+ brcmf_err(bus,
+ "OTP unavailable, using default firmware\n");
+ return 0;
+ }
+
+ /* Map OTP to shadow area */
+ WRITECC32(devinfo, sromcontrol,
+ sromctl | BCMA_CC_SROM_CONTROL_OTPSEL);
+ }
+
+ otp = kcalloc(words, sizeof(u16), GFP_KERNEL);
+ if (!otp)
+ return -ENOMEM;
+
+ /* Map bus window to SROM/OTP shadow area in core */
+ base = brcmf_pcie_buscore_prep_addr(devinfo->pdev, base + core->base);
+
+ brcmf_dbg(PCIE, "OTP data:\n");
+ for (idx = 0; idx < words; idx++) {
+ otp[idx] = brcmf_pcie_read_reg16(devinfo, base + 2 * idx);
+ brcmf_dbg(PCIE, "[%8x] 0x%04x\n", base + 2 * idx, otp[idx]);
+ }
+
+ if (coreid == BCMA_CORE_CHIPCOMMON) {
+ brcmf_pcie_select_core(devinfo, coreid);
+ WRITECC32(devinfo, sromcontrol, sromctl);
+ }
+
+ ret = brcmf_pcie_parse_otp(devinfo, (u8 *)otp, 2 * words);
+ kfree(otp);
+
+ return ret;
+}
+
#define BRCMF_PCIE_FW_CODE 0
#define BRCMF_PCIE_FW_NVRAM 1
+#define BRCMF_PCIE_FW_CLM 2
static void brcmf_pcie_setup(struct device *dev, int ret,
struct brcmf_fw_request *fwreq)
@@ -1755,6 +2058,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret,
fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
+ devinfo->clm_fw = fwreq->items[BRCMF_PCIE_FW_CLM].binary;
kfree(fwreq);
ret = brcmf_chip_get_raminfo(devinfo->ci);
@@ -1830,6 +2134,7 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
struct brcmf_fw_name fwnames[] = {
{ ".bin", devinfo->fw_name },
{ ".txt", devinfo->nvram_name },
+ { ".clm_blob", devinfo->clm_name },
};
fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
@@ -1842,11 +2147,51 @@ brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
- fwreq->board_type = devinfo->settings->board_type;
+ fwreq->items[BRCMF_PCIE_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
+ fwreq->items[BRCMF_PCIE_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
fwreq->bus_nr = devinfo->pdev->bus->number;
+ /* Apple platforms with fancy firmware/NVRAM selection */
+ if (devinfo->settings->board_type &&
+ devinfo->settings->antenna_sku &&
+ devinfo->otp.valid) {
+ const struct brcmf_otp_params *otp = &devinfo->otp;
+ struct device *dev = &devinfo->pdev->dev;
+ const char **bt = fwreq->board_types;
+
+ brcmf_dbg(PCIE, "Apple board: %s\n",
+ devinfo->settings->board_type);
+
+ /* Example: apple,shikoku-RASP-m-6.11-X3 */
+ bt[0] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor, otp->version,
+ devinfo->settings->antenna_sku);
+ bt[1] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor, otp->version);
+ bt[2] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s-%s",
+ devinfo->settings->board_type,
+ otp->module, otp->vendor);
+ bt[3] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
+ devinfo->settings->board_type,
+ otp->module);
+ bt[4] = devm_kasprintf(dev, GFP_KERNEL, "%s-%s",
+ devinfo->settings->board_type,
+ devinfo->settings->antenna_sku);
+ bt[5] = devinfo->settings->board_type;
+
+ if (!bt[0] || !bt[1] || !bt[2] || !bt[3] || !bt[4]) {
+ kfree(fwreq);
+ return NULL;
+ }
+ } else {
+ brcmf_dbg(PCIE, "Board: %s\n", devinfo->settings->board_type);
+ fwreq->board_types[0] = devinfo->settings->board_type;
+ }
+
return fwreq;
}
@@ -1857,6 +2202,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct brcmf_fw_request *fwreq;
struct brcmf_pciedev_info *devinfo;
struct brcmf_pciedev *pcie_bus_dev;
+ struct brcmf_core *core;
struct brcmf_bus *bus;
brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
@@ -1876,6 +2222,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto fail;
}
+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+ if (core->rev >= 64)
+ devinfo->reginfo = &brcmf_reginfo_64;
+ else
+ devinfo->reginfo = &brcmf_reginfo_default;
+
pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
if (pcie_bus_dev == NULL) {
ret = -ENOMEM;
@@ -1918,6 +2270,12 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto fail_bus;
+ ret = brcmf_pcie_read_otp(devinfo);
+ if (ret) {
+ brcmf_err(bus, "failed to parse OTP\n");
+ goto fail_brcmf;
+ }
+
fwreq = brcmf_pcie_prepare_fw_request(devinfo);
if (!fwreq) {
ret = -ENOMEM;
@@ -1981,6 +2339,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
brcmf_pcie_release_ringbuffers(devinfo);
brcmf_pcie_reset_device(devinfo);
brcmf_pcie_release_resource(devinfo);
+ release_firmware(devinfo->clm_fw);
if (devinfo->ci)
brcmf_chip_detach(devinfo->ci);
@@ -2038,7 +2397,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
/* Check if device is still up and running, if so we are ready */
- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
+ if (brcmf_pcie_read_reg32(devinfo, devinfo->reginfo->intmask) != 0) {
brcmf_dbg(PCIE, "Try to wakeup device....\n");
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
@@ -2105,6 +2464,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = {
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),
{ /* end: all zeroes */ }
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index d7072009c47f..465d95d83759 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4131,23 +4131,24 @@ brcmf_sdio_watchdog(struct timer_list *t)
}
}
-static
-int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_sdio_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
- brcmf_sdio_fwnames,
- ARRAY_SIZE(brcmf_sdio_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
+ switch (type) {
+ case BRCMF_BLOB_CLM:
+ *fw = sdiodev->clm_fw;
+ sdiodev->clm_fw = NULL;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ if (!*fw)
+ return -ENOENT;
- kfree(fwreq);
return 0;
}
@@ -4182,13 +4183,14 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.wowl_config = brcmf_sdio_wowl_config,
.get_ramsize = brcmf_sdio_bus_get_ramsize,
.get_memdump = brcmf_sdio_bus_get_memdump,
- .get_fwname = brcmf_sdio_get_fwname,
+ .get_blob = brcmf_sdio_get_blob,
.debugfs_create = brcmf_sdio_debugfs_create,
.reset = brcmf_sdio_bus_reset
};
#define BRCMF_SDIO_FW_CODE 0
#define BRCMF_SDIO_FW_NVRAM 1
+#define BRCMF_SDIO_FW_CLM 2
static void brcmf_sdio_firmware_callback(struct device *dev, int err,
struct brcmf_fw_request *fwreq)
@@ -4211,6 +4213,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
+ sdiod->clm_fw = fwreq->items[BRCMF_SDIO_FW_CLM].binary;
kfree(fwreq);
/* try to download image and nvram to the dongle */
@@ -4409,6 +4412,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
struct brcmf_fw_name fwnames[] = {
{ ".bin", bus->sdiodev->fw_name },
{ ".txt", bus->sdiodev->nvram_name },
+ { ".clm_blob", bus->sdiodev->clm_name },
};
fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
@@ -4420,7 +4424,9 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
- fwreq->board_type = bus->sdiodev->settings->board_type;
+ fwreq->items[BRCMF_SDIO_FW_CLM].type = BRCMF_FW_TYPE_BINARY;
+ fwreq->items[BRCMF_SDIO_FW_CLM].flags = BRCMF_FW_REQF_OPTIONAL;
+ fwreq->board_types[0] = bus->sdiodev->settings->board_type;
return fwreq;
}
@@ -4576,6 +4582,8 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
if (bus->sdiodev->settings)
brcmf_release_module_param(bus->sdiodev->settings);
+ release_firmware(bus->sdiodev->clm_fw);
+ bus->sdiodev->clm_fw = NULL;
kfree(bus->rxbuf);
kfree(bus->hdrbuf);
kfree(bus);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 47351ff458ca..b76d34d36bde 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -186,9 +186,11 @@ struct brcmf_sdio_dev {
struct sg_table sgtable;
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
+ char clm_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
+ const struct firmware *clm_fw;
};
/* sdio core registers */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 9fb68c2dc7e3..85e18fb9c497 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1154,24 +1154,11 @@ error:
return NULL;
}
-static
-int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+static int brcmf_usb_get_blob(struct device *dev, const struct firmware **fw,
+ enum brcmf_blob_type type)
{
- struct brcmf_bus *bus = dev_get_drvdata(dev);
- struct brcmf_fw_request *fwreq;
- struct brcmf_fw_name fwnames[] = {
- { ext, fw_name },
- };
-
- fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
- brcmf_usb_fwnames,
- ARRAY_SIZE(brcmf_usb_fwnames),
- fwnames, ARRAY_SIZE(fwnames));
- if (!fwreq)
- return -ENOMEM;
-
- kfree(fwreq);
- return 0;
+ /* No blobs for USB devices... */
+ return -ENOENT;
}
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
@@ -1180,7 +1167,7 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
- .get_fwname = brcmf_usb_get_fwname,
+ .get_blob = brcmf_usb_get_blob,
};
#define BRCMF_USB_FW_CODE 0
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 1f225cdac9bd..1003f123ec25 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -51,6 +51,7 @@
#define BRCM_CC_43664_CHIP_ID 43664
#define BRCM_CC_43666_CHIP_ID 43666
#define BRCM_CC_4371_CHIP_ID 0x4371
+#define BRCM_CC_4378_CHIP_ID 0x4378
#define CY_CC_4373_CHIP_ID 0x4373
#define CY_CC_43012_CHIP_ID 43012
#define CY_CC_43439_CHIP_ID 43439
@@ -88,6 +89,7 @@
#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4
#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5
#define BRCM_PCIE_4371_DEVICE_ID 0x440d
+#define BRCM_PCIE_4378_DEVICE_ID 0x4425
/* brcmsmac IDs */
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h
index 7964ef7d15f0..bec7bc273748 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw.h
+++ b/drivers/net/wireless/intel/ipw2x00/libipw.h
@@ -405,7 +405,7 @@ struct libipw_auth {
__le16 transaction;
__le16 status;
/* challenge */
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
struct libipw_channel_switch {
@@ -423,7 +423,6 @@ struct libipw_action {
union {
struct libipw_action_exchange {
u8 token;
- struct libipw_info_element info_element[0];
} exchange;
struct libipw_channel_switch channel_switch;
@@ -441,7 +440,7 @@ struct libipw_disassoc {
struct libipw_probe_request {
struct libipw_hdr_3addr header;
/* SSID, supported rates */
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
struct libipw_probe_response {
@@ -451,7 +450,7 @@ struct libipw_probe_response {
__le16 capability;
/* SSID, supported rates, FH params, DS params,
* CF params, IBSS params, TIM (if beacon), RSN */
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
/* Alias beacon for probe_response */
@@ -462,7 +461,7 @@ struct libipw_assoc_request {
__le16 capability;
__le16 listen_interval;
/* SSID, supported rates, RSN */
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
struct libipw_reassoc_request {
@@ -470,7 +469,7 @@ struct libipw_reassoc_request {
__le16 capability;
__le16 listen_interval;
u8 current_ap[ETH_ALEN];
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
struct libipw_assoc_response {
@@ -479,7 +478,7 @@ struct libipw_assoc_response {
__le16 status;
__le16 aid;
/* supported rates */
- struct libipw_info_element info_element[];
+ u8 variable[];
} __packed;
struct libipw_txb {
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
index 7a684b76f39b..48d6870bbf4e 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -1329,8 +1329,8 @@ static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_as
network->wpa_ie_len = 0;
network->rsn_ie_len = 0;
- if (libipw_parse_info_param
- (frame->info_element, stats->len - sizeof(*frame), network))
+ if (libipw_parse_info_param((void *)frame->variable,
+ stats->len - sizeof(*frame), network))
return 1;
network->mode = 0;
@@ -1389,8 +1389,8 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
network->wpa_ie_len = 0;
network->rsn_ie_len = 0;
- if (libipw_parse_info_param
- (beacon->info_element, stats->len - sizeof(*beacon), network))
+ if (libipw_parse_info_param((void *)beacon->variable,
+ stats->len - sizeof(*beacon), network))
return 1;
network->mode = 0;
@@ -1510,7 +1510,7 @@ static void libipw_process_probe_response(struct libipw_device
struct libipw_network *target;
struct libipw_network *oldest = NULL;
#ifdef CONFIG_LIBIPW_DEBUG
- struct libipw_info_element *info_element = beacon->info_element;
+ struct libipw_info_element *info_element = (void *)beacon->variable;
#endif
unsigned long flags;
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 26a48d8f49be..b4f945a549f7 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -2104,7 +2104,7 @@ struct mwifiex_fw_mef_entry {
struct host_cmd_ds_mef_cfg {
__le32 criteria;
__le16 num_entries;
- struct mwifiex_fw_mef_entry mef_entry[];
+ u8 mef_entry_data[];
} __packed;
#define CONNECTION_TYPE_INFRA 0
@@ -2254,7 +2254,7 @@ struct coalesce_receive_filt_rule {
struct host_cmd_ds_coalesce_cfg {
__le16 action;
__le16 num_of_rules;
- struct coalesce_receive_filt_rule rule[];
+ u8 rule_data[];
} __packed;
struct host_cmd_ds_multi_chan_policy {
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index fc77489cc511..7dddb4b5dea1 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -51,9 +51,10 @@ static void wakeup_timer_fn(struct timer_list *t)
adapter->if_ops.card_reset(adapter);
}
-static void fw_dump_timer_fn(struct timer_list *t)
+static void fw_dump_work(struct work_struct *work)
{
- struct mwifiex_adapter *adapter = from_timer(adapter, t, devdump_timer);
+ struct mwifiex_adapter *adapter =
+ container_of(work, struct mwifiex_adapter, devdump_work.work);
mwifiex_upload_device_dump(adapter);
}
@@ -309,7 +310,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_triggered = false;
timer_setup(&adapter->wakeup_timer, wakeup_timer_fn, 0);
adapter->devdump_len = 0;
- timer_setup(&adapter->devdump_timer, fw_dump_timer_fn, 0);
+ INIT_DELAYED_WORK(&adapter->devdump_work, fw_dump_work);
}
/*
@@ -388,7 +389,7 @@ static void
mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
{
del_timer(&adapter->wakeup_timer);
- del_timer_sync(&adapter->devdump_timer);
+ cancel_delayed_work_sync(&adapter->devdump_work);
mwifiex_cancel_all_pending_cmd(adapter);
wake_up_interruptible(&adapter->cmd_wait_q.wait);
wake_up_interruptible(&adapter->hs_activate_wait_q);
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 87729d251fed..63f861e6b28a 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -37,6 +37,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/of_irq.h>
+#include <linux/workqueue.h>
#include "decl.h"
#include "ioctl.h"
@@ -1043,7 +1044,7 @@ struct mwifiex_adapter {
/* Device dump data/length */
void *devdump_data;
int devdump_len;
- struct timer_list devdump_timer;
+ struct delayed_work devdump_work;
bool ignore_btcoex_events;
};
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
index 512b5bb9cf6f..e2800a831c8e 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -1435,7 +1435,7 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
mef_entry = (struct mwifiex_fw_mef_entry *)pos;
mef_entry->mode = mef->mef_entry[i].mode;
mef_entry->action = mef->mef_entry[i].action;
- pos += sizeof(*mef_cfg->mef_entry);
+ pos += sizeof(*mef_entry);
if (mwifiex_cmd_append_rpn_expression(priv,
&mef->mef_entry[i], &pos))
@@ -1631,7 +1631,7 @@ mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
coalesce_cfg->action = cpu_to_le16(cmd_action);
coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules);
- rule = coalesce_cfg->rule;
+ rule = (void *)coalesce_cfg->rule_data;
for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index b6315fccd1bb..df9cdd10a494 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -611,8 +611,8 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
* transmission event get lost, in this cornel case,
* user would still get partial of the dump.
*/
- mod_timer(&adapter->devdump_timer,
- jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
+ schedule_delayed_work(&adapter->devdump_work,
+ msecs_to_jiffies(MWIFIEX_TIMER_10S));
}
/* Overflow check */
@@ -631,7 +631,7 @@ mwifiex_fw_dump_info_event(struct mwifiex_private *priv,
return;
upload_dump:
- del_timer_sync(&adapter->devdump_timer);
+ cancel_delayed_work_sync(&adapter->devdump_work);
mwifiex_upload_device_dump(adapter);
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 8f5772b98f58..07a6a5a9ce13 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1309,8 +1309,11 @@ void rt2x00queue_unmap_skb(struct queue_entry *entry);
*/
static inline struct data_queue *
rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev,
- const enum data_queue_qid queue)
+ enum data_queue_qid queue)
{
+ if (queue >= rt2x00dev->ops->tx_queues && queue < IEEE80211_NUM_ACS)
+ queue = rt2x00dev->ops->tx_queues - 1;
+
if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
return &rt2x00dev->tx[queue];
diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c
index 732502b64b25..bbdfa9ac203c 100644
--- a/drivers/net/wireless/realtek/rtw89/coex.c
+++ b/drivers/net/wireless/realtek/rtw89/coex.c
@@ -9,6 +9,7 @@
#include "ps.h"
#include "reg.h"
+#define RTW89_COEX_VERSION 0x06030013
#define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
enum btc_fbtc_tdma_template {
@@ -77,21 +78,21 @@ static const struct rtw89_btc_fbtc_tdma t_def[] = {
static const struct rtw89_btc_fbtc_slot s_def[] = {
[CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
- [CXST_B2W] = __DEF_FBTC_SLOT(5, 0x5a5a5a5a, SLOT_ISO),
- [CXST_W1] = __DEF_FBTC_SLOT(70, 0x5a5a5a5a, SLOT_ISO),
- [CXST_W2] = __DEF_FBTC_SLOT(70, 0x5a5a5aaa, SLOT_ISO),
- [CXST_W2B] = __DEF_FBTC_SLOT(15, 0x5a5a5a5a, SLOT_ISO),
- [CXST_B1] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
- [CXST_B2] = __DEF_FBTC_SLOT(7, 0x6a5a5a5a, SLOT_MIX),
- [CXST_B3] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
- [CXST_B4] = __DEF_FBTC_SLOT(50, 0x55555555, SLOT_MIX),
- [CXST_LK] = __DEF_FBTC_SLOT(20, 0x5a5a5a5a, SLOT_ISO),
+ [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
+ [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
+ [CXST_W2] = __DEF_FBTC_SLOT(70, 0xea5a5aaa, SLOT_ISO),
+ [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
+ [CXST_B1] = __DEF_FBTC_SLOT(100, 0xe5555555, SLOT_MIX),
+ [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
+ [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
+ [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
+ [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
[CXST_BLK] = __DEF_FBTC_SLOT(250, 0x55555555, SLOT_MIX),
- [CXST_E2G] = __DEF_FBTC_SLOT(20, 0x6a5a5a5a, SLOT_MIX),
+ [CXST_E2G] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_MIX),
[CXST_E5G] = __DEF_FBTC_SLOT(20, 0xffffffff, SLOT_MIX),
- [CXST_EBT] = __DEF_FBTC_SLOT(20, 0x55555555, SLOT_MIX),
+ [CXST_EBT] = __DEF_FBTC_SLOT(20, 0xe5555555, SLOT_MIX),
[CXST_ENULL] = __DEF_FBTC_SLOT(7, 0xaaaaaaaa, SLOT_ISO),
- [CXST_WLK] = __DEF_FBTC_SLOT(250, 0x6a5a6a5a, SLOT_MIX),
+ [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
[CXST_W1FDD] = __DEF_FBTC_SLOT(35, 0xfafafafa, SLOT_ISO),
[CXST_B1FDD] = __DEF_FBTC_SLOT(100, 0xffffffff, SLOT_MIX),
};
@@ -99,13 +100,13 @@ static const struct rtw89_btc_fbtc_slot s_def[] = {
static const u32 cxtbl[] = {
0xffffffff, /* 0 */
0xaaaaaaaa, /* 1 */
- 0x55555555, /* 2 */
- 0x66555555, /* 3 */
- 0x66556655, /* 4 */
+ 0xe5555555, /* 2 */
+ 0xee555555, /* 3 */
+ 0xd5555555, /* 4 */
0x5a5a5a5a, /* 5 */
- 0x5a5a5aaa, /* 6 */
- 0xaa5a5a5a, /* 7 */
- 0x6a5a5a5a, /* 8 */
+ 0xfa5a5a5a, /* 6 */
+ 0xda5a5a5a, /* 7 */
+ 0xea5a5a5a, /* 8 */
0x6a5a5aaa, /* 9 */
0x6a5a6a5a, /* 10 */
0x6a5a6aaa, /* 11 */
@@ -264,6 +265,9 @@ enum btc_cx_poicy_type {
/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8,
+ /* TDMA off + pri: WL_Hi-Tx = BT */
+ BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 9,
+
/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
@@ -433,7 +437,7 @@ enum btc_w2b_scoreboard {
BTC_WSCB_TDMA = BIT(9),
BTC_WSCB_FIX2M = BIT(10),
BTC_WSCB_WLRFK = BIT(11),
- BTC_WSCB_BTRFK_GNT = BIT(12), /* not used, use mailbox to inform BT */
+ BTC_WSCB_RXSCAN_PRI = BIT(12),
BTC_WSCB_BT_HILNA = BIT(13),
BTC_WSCB_BTLOG = BIT(14),
BTC_WSCB_ALL = GENMASK(23, 0),
@@ -491,6 +495,11 @@ enum btc_gnt_state {
BTC_GNT_MAX
};
+enum btc_ctr_path {
+ BTC_CTRL_BY_BT = 0,
+ BTC_CTRL_BY_WL
+};
+
enum btc_wl_max_tx_time {
BTC_MAX_TX_TIME_L1 = 500,
BTC_MAX_TX_TIME_L2 = 1000,
@@ -650,8 +659,6 @@ static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
}
-#define BTC_FWINFO_BUF 1024
-
#define BTC_RPT_HDR_SIZE 3
#define BTC_CHK_WLSLOT_DRIFT_MAX 15
#define BTC_CHK_HANG_MAX 3
@@ -916,7 +923,8 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
struct rtw89_btc_prpt *btc_prpt = NULL;
struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
- u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
+ void *rpt_content = NULL, *pfinfo = NULL;
+ u8 rpt_type = 0;
u16 wl_slot_set = 0, wl_slot_real = 0;
u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
u32 cnt_leak_slot = 0, bt_slot_real = 0, cnt_rx_imr = 0;
@@ -944,10 +952,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
case BTC_RPT_TYPE_CTRL:
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
if (chip->chip_id == RTL8852A) {
- pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
+ pfinfo = &pfwinfo->rpt_ctrl.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
} else {
- pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo_v1);
+ pfinfo = &pfwinfo->rpt_ctrl.finfo_v1;
pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo_v1);
}
pcinfo->req_fver = chip->fcxbtcrpt_ver;
@@ -957,10 +965,10 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
case BTC_RPT_TYPE_TDMA:
pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
if (chip->chip_id == RTL8852A) {
- pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo;
+ pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
} else {
- pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo_v1;
+ pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo_v1;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo_v1);
}
pcinfo->req_fver = chip->fcxtdma_ver;
@@ -969,7 +977,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_SLOT:
pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_slots.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
pcinfo->req_fver = chip->fcxslots_ver;
pcinfo->rx_len = rpt_len;
@@ -978,12 +986,12 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
case BTC_RPT_TYPE_CYSTA:
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
if (chip->chip_id == RTL8852A) {
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo;
pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
} else {
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo_v1);
+ pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo_v1);
}
@@ -993,24 +1001,37 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_STEP:
pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
- pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
- trace_step + 8;
+ if (chip->chip_id == RTL8852A) {
+ pfinfo = &pfwinfo->rpt_fbtc_step.finfo;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
+ trace_step +
+ offsetof(struct rtw89_btc_fbtc_steps, step);
+ } else {
+ pfinfo = &pfwinfo->rpt_fbtc_step.finfo_v1;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo_v1.step[0]) *
+ trace_step +
+ offsetof(struct rtw89_btc_fbtc_steps_v1, step);
+ }
pcinfo->req_fver = chip->fcxstep_ver;
pcinfo->rx_len = rpt_len;
pcinfo->rx_cnt++;
break;
case BTC_RPT_TYPE_NULLSTA:
pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
- pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
+ if (chip->chip_id == RTL8852A) {
+ pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
+ } else {
+ pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo_v1;
+ pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo_v1);
+ }
pcinfo->req_fver = chip->fcxnullsta_ver;
pcinfo->rx_len = rpt_len;
pcinfo->rx_cnt++;
break;
case BTC_RPT_TYPE_MREG:
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
pcinfo->req_fver = chip->fcxmreg_ver;
pcinfo->rx_len = rpt_len;
@@ -1018,7 +1039,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_GPIO_DBG:
pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
pcinfo->req_fver = chip->fcxgpiodbg_ver;
pcinfo->rx_len = rpt_len;
@@ -1026,7 +1047,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_BT_VER:
pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_btver.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
pcinfo->req_fver = chip->fcxbtver_ver;
pcinfo->rx_len = rpt_len;
@@ -1034,7 +1055,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_BT_SCAN:
pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
pcinfo->req_fver = chip->fcxbtscan_ver;
pcinfo->rx_len = rpt_len;
@@ -1042,7 +1063,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_BT_AFH:
pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
pcinfo->req_fver = chip->fcxbtafh_ver;
pcinfo->rx_len = rpt_len;
@@ -1050,7 +1071,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
break;
case BTC_RPT_TYPE_BT_DEVICE:
pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
- pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
+ pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
pcinfo->req_fver = chip->fcxbtdevinfo_ver;
pcinfo->rx_len = rpt_len;
@@ -1309,6 +1330,7 @@ static void _parse_btc_report(struct rtw89_dev *rtwdev,
struct rtw89_btc_btf_fwinfo *pfwinfo,
u8 *pbuf, u32 buf_len)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc_prpt *btc_prpt = NULL;
u32 index = 0, rpt_len = 0;
@@ -1318,7 +1340,7 @@ static void _parse_btc_report(struct rtw89_dev *rtwdev,
while (pbuf) {
btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
- if (index + 2 >= BTC_FWINFO_BUF)
+ if (index + 2 >= chip->btc_fwinfo_buf)
break;
/* At least 3 bytes: type(1) & len(2) */
rpt_len = le16_to_cpu(btc_prpt->len);
@@ -1616,7 +1638,7 @@ void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
}
}
-static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
+static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
{
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_dm *dm = &btc->dm;
@@ -1630,7 +1652,7 @@ static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
if (!(phy_map & BIT(i)))
continue;
- switch (state) {
+ switch (wl_state) {
case BTC_GNT_HW:
g[i].gnt_wl_sw_en = 0;
g[i].gnt_wl = 0;
@@ -1644,6 +1666,21 @@ static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
g[i].gnt_wl = 1;
break;
}
+
+ switch (bt_state) {
+ case BTC_GNT_HW:
+ g[i].gnt_bt_sw_en = 0;
+ g[i].gnt_bt = 0;
+ break;
+ case BTC_GNT_SW_LO:
+ g[i].gnt_bt_sw_en = 1;
+ g[i].gnt_bt = 0;
+ break;
+ case BTC_GNT_SW_HI:
+ g[i].gnt_bt_sw_en = 1;
+ g[i].gnt_bt = 1;
+ break;
+ }
}
rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
@@ -1702,6 +1739,7 @@ static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
@@ -1714,6 +1752,8 @@ static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): level = %d\n",
__func__, level);
+
+ chip->ops->btc_set_wl_rx_gain(rtwdev, level);
}
static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
@@ -2169,6 +2209,9 @@ void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_OFF_BWB1:
_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
break;
+ case BTC_CXP_OFF_BWB3:
+ _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
+ break;
}
break;
case BTC_CXP_OFFB: /* TDMA off + beacon protect */
@@ -2488,6 +2531,9 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
case BTC_CXP_OFF_BWB2:
_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
break;
+ case BTC_CXP_OFF_BWB3:
+ _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
+ break;
default:
break;
}
@@ -2778,39 +2824,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
}
EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
-static void _set_gnt_bt(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
-{
- struct rtw89_btc *btc = &rtwdev->btc;
- struct rtw89_btc_dm *dm = &btc->dm;
- struct rtw89_mac_ax_gnt *g = dm->gnt.band;
- u8 i;
-
- if (phy_map > BTC_PHY_ALL)
- return;
-
- for (i = 0; i < RTW89_PHY_MAX; i++) {
- if (!(phy_map & BIT(i)))
- continue;
-
- switch (state) {
- case BTC_GNT_HW:
- g[i].gnt_bt_sw_en = 0;
- g[i].gnt_bt = 0;
- break;
- case BTC_GNT_SW_LO:
- g[i].gnt_bt_sw_en = 1;
- g[i].gnt_bt = 0;
- break;
- case BTC_GNT_SW_HI:
- g[i].gnt_bt_sw_en = 1;
- g[i].gnt_bt = 1;
- break;
- }
- }
-
- rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
-}
-
static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
u8 tx_val, u8 rx_val)
{
@@ -2875,86 +2888,74 @@ static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
switch (type) {
case BTC_ANT_WPOWERON:
- rtw89_chip_cfg_ctrl_path(rtwdev, false);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
break;
case BTC_ANT_WINIT:
- if (bt->enable.now) {
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
- } else {
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
- }
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
+ if (bt->enable.now)
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
+ else
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
+
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
break;
case BTC_ANT_WONLY:
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_WOFF:
- rtw89_chip_cfg_ctrl_path(rtwdev, false);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_W2G:
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
if (rtwdev->dbcc_en) {
for (i = 0; i < RTW89_PHY_MAX; i++) {
b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
- _set_gnt_wl(rtwdev, BIT(i), gnt_wl_ctrl);
-
gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
/* BT should control by GNT_BT if WL_2G at S0 */
if (i == 1 &&
wl_dinfo->real_band[0] == RTW89_BAND_2G &&
wl_dinfo->real_band[1] == RTW89_BAND_5G)
gnt_bt_ctrl = BTC_GNT_HW;
- _set_gnt_bt(rtwdev, BIT(i), gnt_bt_ctrl);
-
+ _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
_set_bt_plut(rtwdev, BIT(i),
plt_ctrl, plt_ctrl);
}
} else {
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
_set_bt_plut(rtwdev, BTC_PHY_ALL,
BTC_PLT_BT, BTC_PLT_BT);
}
break;
case BTC_ANT_W5G:
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_W25G:
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
_set_bt_plut(rtwdev, BTC_PHY_ALL,
BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
break;
case BTC_ANT_FREERUN:
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_WRFK:
- rtw89_chip_cfg_ctrl_path(rtwdev, true);
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
break;
case BTC_ANT_BRFK:
- rtw89_chip_cfg_ctrl_path(rtwdev, false);
- _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
- _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
+ rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
+ _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
break;
default:
@@ -3066,14 +3067,19 @@ static void _action_bt_idle(struct rtw89_dev *rtwdev)
static void _action_bt_hfp(struct rtw89_dev *rtwdev)
{
struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
- if (btc->cx.wl.status.map._4way)
+ if (btc->cx.wl.status.map._4way) {
_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
- else
- _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HFP);
+ } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
+ btc->cx.bt.scan_rx_low_pri = true;
+ _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
+ } else {
+ _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
+ }
} else {
_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
}
@@ -3081,17 +3087,37 @@ static void _action_bt_hfp(struct rtw89_dev *rtwdev)
static void _action_bt_hid(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+ struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
+ u16 policy_type = BTC_CXP_OFF_BT;
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
- if (btc->mdinfo.ant.type == BTC_ANT_SHARED) /* shared-antenna */
- if (btc->cx.wl.status.map._4way)
- _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HID);
- else
- _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HID);
- else /* dedicated-antenna */
- _set_policy(rtwdev, BTC_CXP_OFF_EQ3, BTC_ACT_BT_HID);
+ if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
+ if (wl->status.map._4way) {
+ policy_type = BTC_CXP_OFF_WL;
+ } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
+ btc->cx.bt.scan_rx_low_pri = true;
+ if (hid->type & BTC_HID_BLE)
+ policy_type = BTC_CXP_OFF_BWB0;
+ else
+ policy_type = BTC_CXP_OFF_BWB2;
+ } else if (hid->type == BTC_HID_218) {
+ bt->scan_rx_low_pri = true;
+ policy_type = BTC_CXP_OFF_BWB2;
+ } else if (chip->para_ver == 0x1) {
+ policy_type = BTC_CXP_OFF_BWB3;
+ } else {
+ policy_type = BTC_CXP_OFF_BWB1;
+ }
+ } else { /* dedicated-antenna */
+ policy_type = BTC_CXP_OFF_EQ3;
+ }
+
+ _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
}
static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
@@ -3564,14 +3590,34 @@ static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
_write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
}
+static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+
+ _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
+}
+
/* TODO add these functions */
static void _action_common(struct rtw89_dev *rtwdev)
{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+
_set_btg_ctrl(rtwdev);
_set_wl_tx_limit(rtwdev);
_set_bt_afh_info(rtwdev);
_set_bt_rx_agc(rtwdev);
_set_rf_trx_para(rtwdev);
+ _set_bt_rx_scan_pri(rtwdev);
+
+ if (wl->scbd_change) {
+ rtw89_mac_cfg_sb(rtwdev, wl->scbd);
+ rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
+ wl->scbd);
+ wl->scbd_change = false;
+ btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
+ }
}
static void _action_by_bt(struct rtw89_dev *rtwdev)
@@ -3894,20 +3940,20 @@ static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
u32 scbd_val = 0;
+ u8 force_exec = false;
if (!chip->scbd)
return;
scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
- if (scbd_val == wl->scbd)
- return;
- rtw89_mac_cfg_sb(rtwdev, scbd_val);
- rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
- scbd_val);
- wl->scbd = scbd_val;
+ if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
+ force_exec = true;
- btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
+ if (scbd_val != wl->scbd || force_exec) {
+ wl->scbd = scbd_val;
+ wl->scbd_change = true;
+ }
}
static u8
@@ -4088,8 +4134,8 @@ static void _update_wl_info(struct rtw89_dev *rtwdev)
}
rtw89_debug(rtwdev, RTW89_DBG_BTC,
- "[BTC], cnt_connect = %d, link_mode = %d\n",
- cnt_connect, wl_rinfo->link_mode);
+ "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
+ cnt_connect, cnt_connecting, wl_rinfo->link_mode);
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
}
@@ -4399,6 +4445,7 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+ struct rtw89_btc_bt_info *bt = &btc->cx.bt;
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
u8 mode;
@@ -4475,6 +4522,7 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
btc->ctrl.igno_bt = false;
dm->freerun = false;
+ bt->scan_rx_low_pri = false;
if (reason == BTC_RSN_NTFY_INIT) {
_action_wl_init(rtwdev);
@@ -4517,24 +4565,30 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
_action_wl_2g_sta(rtwdev);
break;
case BTC_WLINK_2G_AP:
+ bt->scan_rx_low_pri = true;
_action_wl_2g_ap(rtwdev);
break;
case BTC_WLINK_2G_GO:
+ bt->scan_rx_low_pri = true;
_action_wl_2g_go(rtwdev);
break;
case BTC_WLINK_2G_GC:
+ bt->scan_rx_low_pri = true;
_action_wl_2g_gc(rtwdev);
break;
case BTC_WLINK_2G_SCC:
+ bt->scan_rx_low_pri = true;
if (chip->chip_id == RTL8852A)
_action_wl_2g_scc(rtwdev);
else if (chip->chip_id == RTL8852C)
_action_wl_2g_scc_v1(rtwdev);
break;
case BTC_WLINK_2G_MCC:
+ bt->scan_rx_low_pri = true;
_action_wl_2g_mcc(rtwdev);
break;
case BTC_WLINK_25G_MCC:
+ bt->scan_rx_low_pri = true;
_action_wl_25g_mcc(rtwdev);
break;
case BTC_WLINK_5G:
@@ -4631,7 +4685,7 @@ void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
_write_scbd(rtwdev,
BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
_update_bt_scbd(rtwdev, true);
- if (rtw89_mac_get_ctrl_path(rtwdev)) {
+ if (rtw89_mac_get_ctrl_path(rtwdev) && chip->chip_id == RTL8852A) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
"[BTC], %s(): PTA owner warning!!\n",
__func__);
@@ -5442,10 +5496,10 @@ static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
chip->chip_id);
- ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver);
- ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver);
- ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver);
- id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver);
+ ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
+ ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
+ ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
+ id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
"[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
@@ -5747,6 +5801,7 @@ static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
#define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
#define CASE_BTC_POLICY_STR(e) \
case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
+#define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
static const char *steps_to_str(u16 step)
{
@@ -5809,6 +5864,7 @@ static const char *steps_to_str(u16 step)
CASE_BTC_POLICY_STR(OFF_BWB0);
CASE_BTC_POLICY_STR(OFF_BWB1);
CASE_BTC_POLICY_STR(OFF_BWB2);
+ CASE_BTC_POLICY_STR(OFF_BWB3);
CASE_BTC_POLICY_STR(OFFB_BWB0);
CASE_BTC_POLICY_STR(OFFE_DEF);
CASE_BTC_POLICY_STR(OFFE_DEF2);
@@ -5860,6 +5916,32 @@ static const char *steps_to_str(u16 step)
}
}
+static const char *id_to_slot(u32 id)
+{
+ switch (id) {
+ CASE_BTC_SLOT_STR(OFF);
+ CASE_BTC_SLOT_STR(B2W);
+ CASE_BTC_SLOT_STR(W1);
+ CASE_BTC_SLOT_STR(W2);
+ CASE_BTC_SLOT_STR(W2B);
+ CASE_BTC_SLOT_STR(B1);
+ CASE_BTC_SLOT_STR(B2);
+ CASE_BTC_SLOT_STR(B3);
+ CASE_BTC_SLOT_STR(B4);
+ CASE_BTC_SLOT_STR(LK);
+ CASE_BTC_SLOT_STR(BLK);
+ CASE_BTC_SLOT_STR(E2G);
+ CASE_BTC_SLOT_STR(E5G);
+ CASE_BTC_SLOT_STR(EBT);
+ CASE_BTC_SLOT_STR(ENULL);
+ CASE_BTC_SLOT_STR(WLK);
+ CASE_BTC_SLOT_STR(W1FDD);
+ CASE_BTC_SLOT_STR(B1FDD);
+ default:
+ return "unknown";
+ }
+}
+
static
void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
@@ -5951,21 +6033,31 @@ static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
(bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
seq_printf(m,
- " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n",
+ " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
"[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
- dm->wl_tx_limit.tx_retry, btc->bt_req_len);
+ dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri);
}
static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
- struct rtw89_btc_fbtc_cysta *pcysta = NULL;
+ struct rtw89_btc_fbtc_cysta *pcysta;
+ struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1;
+ u32 except_cnt, exception_map;
- pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
+ if (chip->chip_id == RTL8852A) {
+ pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
+ except_cnt = le32_to_cpu(pcysta->except_cnt);
+ exception_map = le32_to_cpu(pcysta->exception);
+ } else {
+ pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
+ except_cnt = le32_to_cpu(pcysta_v1->except_cnt);
+ exception_map = le32_to_cpu(pcysta_v1->except_map);
+ }
- if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
- pcysta->except_cnt == 0 &&
+ if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
!pfwinfo->len_mismch && !pfwinfo->fver_mismch)
return;
@@ -5990,16 +6082,17 @@ static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
}
/* cycle statistics exceptions */
- if (pcysta->exception || pcysta->except_cnt) {
+ if (exception_map || except_cnt) {
seq_printf(m,
"exception-type: 0x%x, exception-cnt = %d",
- pcysta->exception, pcysta->except_cnt);
+ exception_map, except_cnt);
}
seq_puts(m, "\n");
}
static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
@@ -6012,7 +6105,10 @@ static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
if (!pcinfo->valid)
return;
- t = &pfwinfo->rpt_fbtc_tdma.finfo;
+ if (chip->chip_id == RTL8852A)
+ t = &pfwinfo->rpt_fbtc_tdma.finfo;
+ else
+ t = &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma;
seq_printf(m,
" %-15s : ", "[tdma_policy]");
@@ -6215,12 +6311,145 @@ static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
}
}
+static void _show_fbtc_cysta_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
+ struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
+ struct rtw89_btc_fbtc_cysta_v1 *pcysta;
+ struct rtw89_btc_rpt_cmn_info *pcinfo;
+ u8 i, cnt = 0, slot_pair, divide_cnt;
+ u16 cycle, c_begin, c_end, store_index;
+
+ pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
+ if (!pcinfo->valid)
+ return;
+
+ pcysta = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
+ seq_printf(m,
+ " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
+ "[cycle_cnt]",
+ le16_to_cpu(pcysta->cycles),
+ le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
+ le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
+ le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
+ le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
+
+ for (i = 0; i < CXST_MAX; i++) {
+ if (!le32_to_cpu(pcysta->slot_cnt[i]))
+ continue;
+
+ seq_printf(m, ", %s:%d", id_to_slot(i),
+ le32_to_cpu(pcysta->slot_cnt[i]));
+ }
+
+ if (dm->tdma_now.rxflctrl)
+ seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr));
+
+ if (le32_to_cpu(pcysta->collision_cnt))
+ seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt));
+
+ if (le32_to_cpu(pcysta->skip_cnt))
+ seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt));
+
+ seq_puts(m, "\n");
+
+ seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
+ "[cycle_time]",
+ le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
+ le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
+ le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
+ le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
+ seq_printf(m,
+ ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
+ le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
+ le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
+ le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
+ le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
+ seq_printf(m,
+ ", maxdiff_t[wl:%d/bt:%d]\n",
+ le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
+ le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
+
+ cycle = le16_to_cpu(pcysta->cycles);
+ if (cycle == 0)
+ return;
+
+ /* 1 cycle record 1 wl-slot and 1 bt-slot */
+ slot_pair = BTC_CYCLE_SLOT_MAX / 2;
+
+ if (cycle <= slot_pair)
+ c_begin = 1;
+ else
+ c_begin = cycle - slot_pair + 1;
+
+ c_end = cycle;
+
+ if (a2dp->exist)
+ divide_cnt = 3;
+ else
+ divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
+
+ for (cycle = c_begin; cycle <= c_end; cycle++) {
+ cnt++;
+ store_index = ((cycle - 1) % slot_pair) * 2;
+
+ if (cnt % divide_cnt == 1) {
+ seq_printf(m, "\n\r %-15s : ", "[cycle_step]");
+ } else {
+ seq_printf(m, "->b%02d",
+ le16_to_cpu(pcysta->slot_step_time[store_index]));
+ if (a2dp->exist) {
+ a2dp_trx = &pcysta->a2dp_trx[store_index];
+ seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
+ a2dp_trx->empty_cnt,
+ a2dp_trx->retry_cnt,
+ a2dp_trx->tx_rate ? 3 : 2,
+ a2dp_trx->tx_cnt,
+ a2dp_trx->ack_cnt,
+ a2dp_trx->nack_cnt);
+ }
+ seq_printf(m, "->w%02d",
+ le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
+ if (a2dp->exist) {
+ a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
+ seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
+ a2dp_trx->empty_cnt,
+ a2dp_trx->retry_cnt,
+ a2dp_trx->tx_rate ? 3 : 2,
+ a2dp_trx->tx_cnt,
+ a2dp_trx->ack_cnt,
+ a2dp_trx->nack_cnt);
+ }
+ }
+ if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
+ seq_puts(m, "\n");
+ }
+
+ if (a2dp->exist) {
+ seq_printf(m, "%-15s : a2dp_ept:%d, a2dp_late:%d",
+ "[a2dp_t_sta]",
+ le16_to_cpu(pcysta->a2dp_ept.cnt),
+ le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
+
+ seq_printf(m, ", avg_t:%d, max_t:%d",
+ le16_to_cpu(pcysta->a2dp_ept.tavg),
+ le16_to_cpu(pcysta->a2dp_ept.tmax));
+
+ seq_puts(m, "\n");
+ }
+}
+
static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
- struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
- struct rtw89_btc_fbtc_cynullsta *ns = NULL;
+ struct rtw89_btc_rpt_cmn_info *pcinfo;
+ struct rtw89_btc_fbtc_cynullsta *ns;
+ struct rtw89_btc_fbtc_cynullsta_v1 *ns_v1;
u8 i = 0;
if (!btc->dm.tdma_now.rxflctrl)
@@ -6230,25 +6459,58 @@ static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
if (!pcinfo->valid)
return;
- ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
+ if (chip->chip_id == RTL8852A) {
+ ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
- seq_printf(m, " %-15s : ", "[null_sta]");
+ seq_printf(m, " %-15s : ", "[null_sta]");
- for (i = 0; i < 2; i++) {
- if (i != 0)
- seq_printf(m, ", null-%d", i);
- else
- seq_printf(m, "null-%d", i);
- seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1]));
- seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0]));
- seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2]));
- seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3]));
- seq_printf(m, "avg_t:%d.%03d/",
- le32_to_cpu(ns->avg_t[i]) / 1000,
- le32_to_cpu(ns->avg_t[i]) % 1000);
- seq_printf(m, "max_t:%d.%03d]",
- le32_to_cpu(ns->max_t[i]) / 1000,
- le32_to_cpu(ns->max_t[i]) % 1000);
+ for (i = 0; i < 2; i++) {
+ if (i != 0)
+ seq_printf(m, ", null-%d", i);
+ else
+ seq_printf(m, "null-%d", i);
+ seq_printf(m, "[ok:%d/",
+ le32_to_cpu(ns->result[i][1]));
+ seq_printf(m, "fail:%d/",
+ le32_to_cpu(ns->result[i][0]));
+ seq_printf(m, "on_time:%d/",
+ le32_to_cpu(ns->result[i][2]));
+ seq_printf(m, "retry:%d/",
+ le32_to_cpu(ns->result[i][3]));
+ seq_printf(m, "avg_t:%d.%03d/",
+ le32_to_cpu(ns->avg_t[i]) / 1000,
+ le32_to_cpu(ns->avg_t[i]) % 1000);
+ seq_printf(m, "max_t:%d.%03d]",
+ le32_to_cpu(ns->max_t[i]) / 1000,
+ le32_to_cpu(ns->max_t[i]) % 1000);
+ }
+ } else {
+ ns_v1 = &pfwinfo->rpt_fbtc_nullsta.finfo_v1;
+
+ seq_printf(m, " %-15s : ", "[null_sta]");
+
+ for (i = 0; i < 2; i++) {
+ if (i != 0)
+ seq_printf(m, ", null-%d", i);
+ else
+ seq_printf(m, "null-%d", i);
+ seq_printf(m, "[Tx:%d/",
+ le32_to_cpu(ns_v1->result[i][4]));
+ seq_printf(m, "[ok:%d/",
+ le32_to_cpu(ns_v1->result[i][1]));
+ seq_printf(m, "fail:%d/",
+ le32_to_cpu(ns_v1->result[i][0]));
+ seq_printf(m, "on_time:%d/",
+ le32_to_cpu(ns_v1->result[i][2]));
+ seq_printf(m, "retry:%d/",
+ le32_to_cpu(ns_v1->result[i][3]));
+ seq_printf(m, "avg_t:%d.%03d/",
+ le32_to_cpu(ns_v1->avg_t[i]) / 1000,
+ le32_to_cpu(ns_v1->avg_t[i]) % 1000);
+ seq_printf(m, "max_t:%d.%03d]",
+ le32_to_cpu(ns_v1->max_t[i]) / 1000,
+ le32_to_cpu(ns_v1->max_t[i]) % 1000);
+ }
}
seq_puts(m, "\n");
}
@@ -6324,6 +6586,7 @@ static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
@@ -6332,11 +6595,57 @@ static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
_show_error(rtwdev, m);
_show_fbtc_tdma(rtwdev, m);
_show_fbtc_slots(rtwdev, m);
- _show_fbtc_cysta(rtwdev, m);
+
+ if (chip->chip_id == RTL8852A)
+ _show_fbtc_cysta(rtwdev, m);
+ else
+ _show_fbtc_cysta_v1(rtwdev, m);
+
_show_fbtc_nullsta(rtwdev, m);
_show_fbtc_step(rtwdev, m);
}
+static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_mac_ax_gnt *gnt;
+ u32 val, status;
+
+ if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B) {
+ rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
+ rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
+
+ gnt = &gnt_cfg->band[0];
+ gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
+ gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
+ gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
+ gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
+
+ gnt = &gnt_cfg->band[1];
+ gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
+ gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
+ gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
+ gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
+ } else if (chip->chip_id == RTL8852C) {
+ val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
+ status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
+
+ gnt = &gnt_cfg->band[0];
+ gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
+ gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
+ gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
+ gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
+
+ gnt = &gnt_cfg->band[1];
+ gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
+ gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
+ gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
+ gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
+ } else {
+ return;
+ }
+}
+
static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
@@ -6348,7 +6657,8 @@ static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
struct rtw89_btc_cx *cx = &btc->cx;
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
- struct rtw89_mac_ax_gnt gnt[2] = {0};
+ struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
+ struct rtw89_mac_ax_gnt gnt;
u8 i = 0, type = 0, cnt = 0;
u32 val, offset;
@@ -6365,45 +6675,28 @@ static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
/* To avoid I/O if WL LPS or power-off */
if (!wl->status.map.lps && !wl->status.map.rf_off) {
- rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
- if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL |
- B_AX_GNT_BT_BB_S0_SW_VAL))
- gnt[0].gnt_bt = true;
- if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL |
- B_AX_GNT_BT_BB_S0_SW_CTRL))
- gnt[0].gnt_bt_sw_en = true;
- if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL |
- B_AX_GNT_WL_BB_S0_SW_VAL))
- gnt[0].gnt_wl = true;
- if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL |
- B_AX_GNT_WL_BB_S0_SW_CTRL))
- gnt[0].gnt_wl_sw_en = true;
-
- if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL |
- B_AX_GNT_BT_BB_S1_SW_VAL))
- gnt[1].gnt_bt = true;
- if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL |
- B_AX_GNT_BT_BB_S1_SW_CTRL))
- gnt[1].gnt_bt_sw_en = true;
- if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL |
- B_AX_GNT_WL_BB_S1_SW_VAL))
- gnt[1].gnt_wl = true;
- if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL |
- B_AX_GNT_WL_BB_S1_SW_CTRL))
- gnt[1].gnt_wl_sw_en = true;
+ if (chip->chip_id == RTL8852A)
+ btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
+ else if (chip->chip_id == RTL8852C)
+ btc->dm.pta_owner = 0;
+ _get_gnt(rtwdev, &gnt_cfg);
+ gnt = gnt_cfg.band[0];
seq_printf(m,
" %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
"[gnt_status]",
- (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"),
- (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl,
- (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt);
+ chip->chip_id == RTL8852C ? "HW" :
+ btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
+ gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
+ gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
+ gnt = gnt_cfg.band[1];
seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
- (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl,
- (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt);
+ gnt.gnt_wl_sw_en ? "SW" : "HW",
+ gnt.gnt_wl,
+ gnt.gnt_bt_sw_en ? "SW" : "HW",
+ gnt.gnt_bt);
}
-
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
if (!pcinfo->valid) {
rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -6560,8 +6853,121 @@ static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
cnt[BTC_NCNT_CUSTOMERIZE]);
}
+static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
+{
+ struct rtw89_btc *btc = &rtwdev->btc;
+ struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
+ struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl;
+ struct rtw89_btc_rpt_cmn_info *pcinfo;
+ struct rtw89_btc_cx *cx = &btc->cx;
+ struct rtw89_btc_dm *dm = &btc->dm;
+ struct rtw89_btc_wl_info *wl = &cx->wl;
+ struct rtw89_btc_bt_info *bt = &cx->bt;
+ u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
+ u8 i;
+
+ if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
+ return;
+
+ seq_puts(m, "========== [Statistics] ==========\n");
+
+ pcinfo = &pfwinfo->rpt_ctrl.cinfo;
+ if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
+ prptctrl = &pfwinfo->rpt_ctrl.finfo_v1;
+
+ seq_printf(m,
+ " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
+ "[summary]", pfwinfo->cnt_h2c,
+ pfwinfo->cnt_h2c_fail,
+ le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
+ pfwinfo->cnt_c2h,
+ le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
+
+ seq_printf(m,
+ "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
+ pfwinfo->event[BTF_EVNT_RPT],
+ le32_to_cpu(prptctrl->rpt_info.cnt),
+ le32_to_cpu(prptctrl->rpt_info.en),
+ dm->error.val);
+
+ if (dm->error.map.wl_fw_hang)
+ seq_puts(m, " (WL FW Hang!!)");
+ seq_puts(m, "\n");
+ seq_printf(m,
+ " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
+ "[mailbox]",
+ le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
+ le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
+ le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
+
+ seq_printf(m,
+ "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
+ le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
+ le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
+ le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
+ le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
+ le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
+
+ seq_printf(m,
+ " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
+ "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
+ cx->cnt_wl[BTC_WCNT_RFK_GO],
+ cx->cnt_wl[BTC_WCNT_RFK_REJECT],
+ cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
+
+ seq_printf(m,
+ ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
+ le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
+ le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
+ le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
+ le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
+ le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
+
+ if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
+ bt->rfk_info.map.timeout = 1;
+ else
+ bt->rfk_info.map.timeout = 0;
+
+ dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
+ } else {
+ seq_printf(m,
+ " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
+ "[summary]", pfwinfo->cnt_h2c,
+ pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
+ pfwinfo->event[BTF_EVNT_RPT],
+ btc->fwinfo.rpt_en_map);
+ seq_puts(m, " (WL FW report invalid!!)\n");
+ }
+
+ for (i = 0; i < BTC_NCNT_NUM; i++)
+ cnt_sum += dm->cnt_notify[i];
+
+ seq_printf(m,
+ " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
+ "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
+ cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
+
+ seq_printf(m,
+ "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
+ cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
+ cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
+ cnt[BTC_NCNT_WL_STA]);
+
+ seq_printf(m,
+ " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
+ "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
+ cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
+ cnt[BTC_NCNT_SPECIAL_PACKET]);
+
+ seq_printf(m,
+ "timer=%d, control=%d, customerize=%d\n",
+ cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
+ cnt[BTC_NCNT_CUSTOMERIZE]);
+}
+
void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_cx *cx = &btc->cx;
@@ -6592,5 +6998,8 @@ void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
_show_dm_info(rtwdev, m);
_show_fw_dm_msg(rtwdev, m);
_show_mreg(rtwdev, m);
- _show_summary(rtwdev, m);
+ if (chip->chip_id == RTL8852A)
+ _show_summary(rtwdev, m);
+ else
+ _show_summary_v1(rtwdev, m);
}
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index c7405cb9ceb7..8d2cce450241 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -847,6 +847,7 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev,
rtw89_debug(rtwdev, RTW89_DBG_FW,
"ignore h2c due to power is off with firmware state=%d\n",
test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags));
+ dev_kfree_skb(skb);
return 0;
}
@@ -996,7 +997,8 @@ static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_info0_v1(struct rtw89_tx_desc_info *desc_info)
{
- u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb);
+ u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_DISDATAFB, desc_info->dis_data_fb) |
+ FIELD_PREP(RTW89_TXWD_INFO0_MULTIPORT_ID, desc_info->port);
return cpu_to_le32(dword);
}
@@ -1892,21 +1894,14 @@ static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev,
return;
spin_lock_bh(&rtwdev->ba_lock);
- if (!list_empty(&rtwtxq->list)) {
- list_del_init(&rtwtxq->list);
- goto out;
- }
-
- set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags);
+ if (!test_and_set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags))
+ list_add_tail(&rtwtxq->list, &rtwdev->forbid_ba_list);
+ spin_unlock_bh(&rtwdev->ba_lock);
- list_add_tail(&rtwtxq->list, &rtwdev->forbid_ba_list);
ieee80211_stop_tx_ba_session(sta, txq->tid);
cancel_delayed_work(&rtwdev->forbid_ba_work);
ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->forbid_ba_work,
RTW89_FORBID_BA_TIMER);
-
-out:
- spin_unlock_bh(&rtwdev->ba_lock);
}
static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
@@ -1918,6 +1913,9 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
struct ieee80211_sta *sta = txq->sta;
struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
+ if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags))
+ return;
+
if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
rtw89_core_stop_tx_ba_session(rtwdev, rtwtxq);
return;
@@ -1926,9 +1924,6 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
if (unlikely(!sta))
return;
- if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags))
- return;
-
if (unlikely(test_bit(RTW89_TXQ_F_BLOCK_BA, &rtwtxq->flags)))
return;
@@ -2555,6 +2550,53 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
return 0;
}
+static void _rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta,
+ struct cfg80211_tid_cfg *tid_conf)
+{
+ struct ieee80211_txq *txq;
+ struct rtw89_txq *rtwtxq;
+ u32 mask = tid_conf->mask;
+ u8 tids = tid_conf->tids;
+ int tids_nbit = BITS_PER_BYTE;
+ int i;
+
+ for (i = 0; i < tids_nbit; i++, tids >>= 1) {
+ if (!tids)
+ break;
+
+ if (!(tids & BIT(0)))
+ continue;
+
+ txq = sta->txq[i];
+ rtwtxq = (struct rtw89_txq *)txq->drv_priv;
+
+ if (mask & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) {
+ if (tid_conf->ampdu == NL80211_TID_CONFIG_ENABLE) {
+ clear_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags);
+ } else {
+ if (test_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags))
+ ieee80211_stop_tx_ba_session(sta, txq->tid);
+ spin_lock_bh(&rtwdev->ba_lock);
+ list_del_init(&rtwtxq->list);
+ set_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags);
+ spin_unlock_bh(&rtwdev->ba_lock);
+ }
+ }
+ }
+}
+
+void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta,
+ struct cfg80211_tid_config *tid_config)
+{
+ int i;
+
+ for (i = 0; i < tid_config->n_tid_conf; i++)
+ _rtw89_core_set_tid_config(rtwdev, sta,
+ &tid_config->tid_conf[i]);
+}
+
static void rtw89_init_ht_cap(struct rtw89_dev *rtwdev,
struct ieee80211_sta_ht_cap *ht_cap)
{
@@ -3193,6 +3235,9 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID;
hw->wiphy->max_scan_ie_len = RTW89_SCANOFLD_MAX_IE_LEN;
+ hw->wiphy->tid_config_support.vif |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
+ hw->wiphy->tid_config_support.peer |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
+
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
ret = rtw89_core_set_supported_band(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index bd2c09e69f08..3b184e3031d4 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -1308,6 +1308,7 @@ struct rtw89_btc_wl_info {
u8 port_id[RTW89_WIFI_ROLE_MLME_MAX];
u8 rssi_level;
+ bool scbd_change;
u32 scbd;
};
@@ -1393,7 +1394,8 @@ struct rtw89_btc_bt_info {
u32 pag: 1;
u32 run_patch_code: 1;
u32 hi_lna_rx: 1;
- u32 rsvd: 22;
+ u32 scan_rx_low_pri: 1;
+ u32 rsvd: 21;
};
struct rtw89_btc_cx {
@@ -1629,6 +1631,14 @@ struct rtw89_btc_fbtc_steps {
struct rtw89_btc_fbtc_step step[FCXMAX_STEP];
} __packed;
+struct rtw89_btc_fbtc_steps_v1 {
+ u8 fver;
+ u8 en;
+ __le16 rsvd;
+ __le32 cnt;
+ struct rtw89_btc_fbtc_step step[FCXMAX_STEP];
+} __packed;
+
struct rtw89_btc_fbtc_cysta { /* statistics for cycles */
u8 fver; /* chip_info::fcxcysta_ver */
u8 rsvd;
@@ -1718,6 +1728,15 @@ struct rtw89_btc_fbtc_cynullsta { /* cycle null statistics */
__le32 result[2][4]; /* 0:fail, 1:ok, 2:on_time, 3:retry */
} __packed;
+struct rtw89_btc_fbtc_cynullsta_v1 { /* cycle null statistics */
+ u8 fver; /* chip_info::fcxnullsta_ver */
+ u8 rsvd;
+ __le16 rsvd2;
+ __le32 max_t[2]; /* max_t for 0:null0/1:null1 */
+ __le32 avg_t[2]; /* avg_t for 0:null0/1:null1 */
+ __le32 result[2][5]; /* 0:fail, 1:ok, 2:on_time, 3:retry, 4:tx */
+} __packed;
+
struct rtw89_btc_fbtc_btver {
u8 fver; /* chip_info::fcxbtver_ver */
u8 rsvd;
@@ -1789,8 +1808,9 @@ struct rtw89_btc_dm {
u32 wl_btg_rx: 1;
u32 trx_para_level: 8;
u32 wl_stb_chg: 1;
+ u32 pta_owner: 1;
u32 tdma_instant_excute: 1;
- u32 rsvd: 2;
+ u32 rsvd: 1;
u16 slot_dur[CXST_MAX];
@@ -1893,12 +1913,18 @@ struct rtw89_btc_rpt_fbtc_cysta {
struct rtw89_btc_rpt_fbtc_step {
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
- struct rtw89_btc_fbtc_steps finfo; /* info from fw */
+ union {
+ struct rtw89_btc_fbtc_steps finfo; /* info from fw */
+ struct rtw89_btc_fbtc_steps_v1 finfo_v1; /* info from fw */
+ };
};
struct rtw89_btc_rpt_fbtc_nullsta {
struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
- struct rtw89_btc_fbtc_cynullsta finfo; /* info from fw */
+ union {
+ struct rtw89_btc_fbtc_cynullsta finfo; /* info from fw */
+ struct rtw89_btc_fbtc_cynullsta_v1 finfo_v1; /* info from fw */
+ };
};
struct rtw89_btc_rpt_fbtc_mreg {
@@ -2056,7 +2082,9 @@ struct rtw89_ra_info {
u8 ra_csi_rate_en:1;
u8 fixed_csi_rate_en:1;
u8 cr_tbl_sel:1;
- u8 rsvd2:5;
+ u8 fix_giltf_en:1;
+ u8 fix_giltf:3;
+ u8 rsvd2:1;
u8 csi_mcs_ss_idx;
u8 csi_mode:2;
u8 csi_gi_ltf:3;
@@ -2330,6 +2358,7 @@ struct rtw89_chip_ops {
void (*btc_update_bt_cnt)(struct rtw89_dev *rtwdev);
void (*btc_wl_s1_standby)(struct rtw89_dev *rtwdev, bool state);
void (*btc_set_policy)(struct rtw89_dev *rtwdev, u16 policy_type);
+ void (*btc_set_wl_rx_gain)(struct rtw89_dev *rtwdev, u32 level);
};
enum rtw89_dma_ch {
@@ -2642,6 +2671,7 @@ struct rtw89_chip_info {
u8 btcx_desired;
u8 scbd;
u8 mailbox;
+ u16 btc_fwinfo_buf;
u8 fcxbtcrpt_ver;
u8 fcxtdma_ver;
@@ -2734,6 +2764,7 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_SCAN_OFFLOAD,
RTW89_FW_FEATURE_TX_WAKE,
RTW89_FW_FEATURE_CRASH_TRIGGER,
+ RTW89_FW_FEATURE_PACKET_DROP,
RTW89_FW_FEATURE_NO_DEEP_PS,
};
@@ -2877,11 +2908,37 @@ enum rtw89_flags {
RTW89_FLAG_LEISURE_PS,
RTW89_FLAG_LOW_POWER_MODE,
RTW89_FLAG_INACTIVE_PS,
- RTW89_FLAG_RESTART_TRIGGER,
+ RTW89_FLAG_CRASH_SIMULATING,
NUM_OF_RTW89_FLAGS,
};
+enum rtw89_pkt_drop_sel {
+ RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_BK_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_VI_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_VO_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_ALL,
+ RTW89_PKT_DROP_SEL_MG0_ONCE,
+ RTW89_PKT_DROP_SEL_HIQ_ONCE,
+ RTW89_PKT_DROP_SEL_HIQ_PORT,
+ RTW89_PKT_DROP_SEL_HIQ_MBSSID,
+ RTW89_PKT_DROP_SEL_BAND,
+ RTW89_PKT_DROP_SEL_BAND_ONCE,
+ RTW89_PKT_DROP_SEL_REL_MACID,
+ RTW89_PKT_DROP_SEL_REL_HIQ_PORT,
+ RTW89_PKT_DROP_SEL_REL_HIQ_MBSSID,
+};
+
+struct rtw89_pkt_drop_params {
+ enum rtw89_pkt_drop_sel sel;
+ enum rtw89_mac_idx mac_band;
+ u8 macid;
+ u8 port;
+ u8 mbssid;
+ bool tf_trs;
+};
+
struct rtw89_pkt_stat {
u16 beacon_nr;
u32 rx_rate_cnt[RTW89_HW_RATE_NR];
@@ -4197,6 +4254,9 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev,
int rtw89_core_sta_remove(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev,
+ struct ieee80211_sta *sta,
+ struct cfg80211_tid_config *tid_config);
int rtw89_core_init(struct rtw89_dev *rtwdev);
void rtw89_core_deinit(struct rtw89_dev *rtwdev);
int rtw89_core_register(struct rtw89_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index eed28c3b440f..730e83d54257 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -2190,6 +2190,37 @@ out:
return count;
}
+static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_cpuio_ctrl ctrl_para = {0};
+ u16 pkt_id;
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ pkt_id = rtw89_mac_dle_buf_req(rtwdev, 0x20, true);
+ switch (pkt_id) {
+ case 0xffff:
+ return -ETIMEDOUT;
+ case 0xfff:
+ return -ENOMEM;
+ default:
+ break;
+ }
+
+ /* intentionally, enqueue two pkt, but has only one pkt id */
+ ctrl_para.cmd_type = CPUIO_OP_CMD_ENQ_TO_HEAD;
+ ctrl_para.start_pktid = pkt_id;
+ ctrl_para.end_pktid = pkt_id;
+ ctrl_para.pkt_num = 1; /* start from 0 */
+ ctrl_para.dst_pid = WDE_DLE_PORT_ID_WDRLS;
+ ctrl_para.dst_qid = WDE_DLE_QUEID_NO_REPORT;
+
+ if (rtw89_mac_set_cpuio(rtwdev, &ctrl_para, true))
+ return -EFAULT;
+
+ return 0;
+}
+
static int
rtw89_debug_priv_fw_crash_get(struct seq_file *m, void *v)
{
@@ -2197,10 +2228,15 @@ rtw89_debug_priv_fw_crash_get(struct seq_file *m, void *v)
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
seq_printf(m, "%d\n",
- test_bit(RTW89_FLAG_RESTART_TRIGGER, rtwdev->flags));
+ test_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags));
return 0;
}
+enum rtw89_dbg_crash_simulation_type {
+ RTW89_DBG_SIM_CPU_EXCEPTION = 1,
+ RTW89_DBG_SIM_CTRL_ERROR = 2,
+};
+
static ssize_t
rtw89_debug_priv_fw_crash_set(struct file *filp, const char __user *user_buf,
size_t count, loff_t *loff)
@@ -2208,22 +2244,30 @@ rtw89_debug_priv_fw_crash_set(struct file *filp, const char __user *user_buf,
struct seq_file *m = (struct seq_file *)filp->private_data;
struct rtw89_debugfs_priv *debugfs_priv = m->private;
struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
- bool fw_crash;
+ int (*sim)(struct rtw89_dev *rtwdev);
+ u8 crash_type;
int ret;
- if (!RTW89_CHK_FW_FEATURE(CRASH_TRIGGER, &rtwdev->fw))
- return -EOPNOTSUPP;
-
- ret = kstrtobool_from_user(user_buf, count, &fw_crash);
+ ret = kstrtou8_from_user(user_buf, count, 0, &crash_type);
if (ret)
return -EINVAL;
- if (!fw_crash)
+ switch (crash_type) {
+ case RTW89_DBG_SIM_CPU_EXCEPTION:
+ if (!RTW89_CHK_FW_FEATURE(CRASH_TRIGGER, &rtwdev->fw))
+ return -EOPNOTSUPP;
+ sim = rtw89_fw_h2c_trigger_cpu_exception;
+ break;
+ case RTW89_DBG_SIM_CTRL_ERROR:
+ sim = rtw89_dbg_trigger_ctrl_error;
+ break;
+ default:
return -EINVAL;
+ }
mutex_lock(&rtwdev->mutex);
- set_bit(RTW89_FLAG_RESTART_TRIGGER, rtwdev->flags);
- ret = rtw89_fw_h2c_trigger_cpu_exception(rtwdev);
+ set_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
+ ret = sim(rtwdev);
mutex_unlock(&rtwdev->mutex);
if (ret)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index f93d65c00f42..5e65f2c410bf 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -225,9 +225,12 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER),
+ __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 38, 0, PACKET_DROP),
+ __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 20, 0, PACKET_DROP),
__CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER),
};
static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
@@ -268,7 +271,7 @@ void rtw89_early_fw_feature_recognize(struct device *device,
device, &buf, sizeof(buf), 0);
if (ret) {
dev_err(device, "failed to early request firmware: %d\n", ret);
- goto out;
+ return;
}
ver_code = buf.mfw_hdr.sig != RTW89_MFW_SIG ?
@@ -615,6 +618,7 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
struct rtw89_sta *rtwsta, const u8 *scan_mac_addr)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CAM_LEN);
if (!skb) {
@@ -631,7 +635,8 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
H2C_FUNC_MAC_ADDR_CAM_UPD, 0, 1,
H2C_CAM_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -640,7 +645,7 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_DCTL_SEC_CAM_LEN 68
@@ -649,6 +654,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
struct rtw89_sta *rtwsta)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DCTL_SEC_CAM_LEN);
if (!skb) {
@@ -665,7 +671,8 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
H2C_FUNC_MAC_DCTLINFO_UD_V1, 0, 0,
H2C_DCTL_SEC_CAM_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -674,7 +681,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1);
@@ -737,7 +744,8 @@ end:
H2C_FUNC_MAC_BA_CAM, 0, 1,
H2C_BA_CAM_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -746,13 +754,14 @@ end:
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
u8 entry_idx, u8 uid)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_BA_CAM_LEN);
if (!skb) {
@@ -773,7 +782,8 @@ static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
H2C_FUNC_MAC_BA_CAM, 0, 1,
H2C_BA_CAM_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -782,7 +792,7 @@ static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
@@ -805,6 +815,7 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
struct sk_buff *skb;
u32 comp = enable ? BIT(RTW89_FW_LOG_COMP_INIT) | BIT(RTW89_FW_LOG_COMP_TASK) |
BIT(RTW89_FW_LOG_COMP_PS) | BIT(RTW89_FW_LOG_COMP_ERROR) : 0;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LOG_CFG_LEN);
if (!skb) {
@@ -824,7 +835,8 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
H2C_FUNC_LOG_CFG, 0, 0,
H2C_LOG_CFG_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -833,7 +845,7 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_GENERAL_PKT_LEN 6
@@ -841,6 +853,7 @@ fail:
int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN);
if (!skb) {
@@ -861,7 +874,8 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid)
H2C_FUNC_MAC_GENERAL_PKT, 0, 1,
H2C_GENERAL_PKT_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -870,7 +884,7 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LPS_PARM_LEN 8
@@ -878,6 +892,7 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
struct rtw89_lps_parm *lps_param)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LPS_PARM_LEN);
if (!skb) {
@@ -903,7 +918,8 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
H2C_FUNC_MAC_LPS_PARM, 0, 1,
H2C_LPS_PARM_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -912,7 +928,7 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
@@ -936,6 +952,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
const struct rtw89_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
u8 macid = rtwvif->mac_id;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
if (!skb) {
@@ -963,7 +980,8 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
chip->h2c_cctl_func_id, 0, 1,
H2C_CMC_TBL_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -972,7 +990,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
@@ -1043,6 +1061,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
struct sk_buff *skb;
u8 pads[RTW89_PPE_BW_NUM];
u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
+ int ret;
memset(pads, 0, sizeof(pads));
if (sta)
@@ -1091,7 +1110,8 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
chip->h2c_cctl_func_id, 0, 1,
H2C_CMC_TBL_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1100,7 +1120,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
@@ -1108,6 +1128,7 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
{
const struct rtw89_chip_info *chip = rtwdev->chip;
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
if (!skb) {
@@ -1131,7 +1152,8 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
chip->h2c_cctl_func_id, 0, 1,
H2C_CMC_TBL_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1140,7 +1162,7 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
@@ -1192,6 +1214,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
struct sk_buff *skb_beacon;
u16 tim_offset;
int bcn_total_len;
+ int ret;
skb_beacon = ieee80211_beacon_get_tim(rtwdev->hw, vif, &tim_offset,
NULL, 0);
@@ -1227,10 +1250,11 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
H2C_FUNC_MAC_BCN_UPD, 0, 1,
bcn_total_len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
return 0;
@@ -1245,6 +1269,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
struct sk_buff *skb;
u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
u8 self_role;
+ int ret;
if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
if (rtwsta)
@@ -1271,7 +1296,8 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
H2C_FUNC_MAC_FWROLE_MAINTAIN, 0, 1,
H2C_ROLE_MAINTAIN_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1280,7 +1306,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_JOIN_INFO_LEN 4
@@ -1291,6 +1317,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
u8 self_role = rtwvif->self_role;
u8 net_type = rtwvif->net_type;
+ int ret;
if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) {
self_role = RTW89_SELF_ROLE_AP_CLIENT;
@@ -1322,7 +1349,8 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
H2C_FUNC_MAC_JOININFO, 0, 1,
H2C_JOIN_INFO_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1331,7 +1359,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
@@ -1340,6 +1368,7 @@ int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
struct rtw89_fw_macid_pause_grp h2c = {{0}};
u8 len = sizeof(struct rtw89_fw_macid_pause_grp);
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_JOIN_INFO_LEN);
if (!skb) {
@@ -1356,7 +1385,8 @@ int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
H2C_FUNC_MAC_MACID_PAUSE, 1, 0,
len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1365,7 +1395,7 @@ int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_EDCA_LEN 12
@@ -1373,6 +1403,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
u8 ac, u32 val)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_EDCA_LEN);
if (!skb) {
@@ -1391,7 +1422,8 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
H2C_FUNC_USR_EDCA, 0, 1,
H2C_EDCA_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1400,7 +1432,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_OFLD_CFG_LEN 8
@@ -1408,6 +1440,7 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev)
{
static const u8 cfg[] = {0x09, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00};
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_OFLD_CFG_LEN);
if (!skb) {
@@ -1421,7 +1454,8 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev)
H2C_FUNC_OFLD_CFG, 0, 1,
H2C_OFLD_CFG_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1430,7 +1464,7 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_RA_LEN 16
@@ -1438,6 +1472,7 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi
{
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_RA_LEN);
if (!skb) {
@@ -1468,6 +1503,8 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi
RTW89_SET_FWCMD_RA_MASK_2(cmd, FIELD_GET(MASKBYTE2, ra->ra_mask));
RTW89_SET_FWCMD_RA_MASK_3(cmd, FIELD_GET(MASKBYTE3, ra->ra_mask));
RTW89_SET_FWCMD_RA_MASK_4(cmd, FIELD_GET(MASKBYTE4, ra->ra_mask));
+ RTW89_SET_FWCMD_RA_FIX_GILTF_EN(cmd, ra->fix_giltf_en);
+ RTW89_SET_FWCMD_RA_FIX_GILTF(cmd, ra->fix_giltf);
if (csi) {
RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(cmd, 1);
@@ -1486,7 +1523,8 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi
H2C_FUNC_OUTSRC_RA_MACIDCFG, 0, 0,
H2C_RA_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1495,7 +1533,7 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_CXDRVHDR 2
@@ -1509,6 +1547,7 @@ int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev)
struct rtw89_btc_ant_info *ant = &module->ant;
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_INIT);
if (!skb) {
@@ -1545,7 +1584,8 @@ int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev)
SET_DRV_INFO, 0, 0,
H2C_LEN_CXDRVINFO_INIT);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1554,7 +1594,7 @@ int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define PORT_DATA_OFFSET 4
@@ -1573,6 +1613,7 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
struct sk_buff *skb;
u8 offset = 0;
u8 *cmd;
+ int ret;
int i;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_ROLE);
@@ -1623,7 +1664,8 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
SET_DRV_INFO, 0, 0,
H2C_LEN_CXDRVINFO_ROLE);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1632,7 +1674,7 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
@@ -1644,6 +1686,7 @@ int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
struct rtw89_btc_wl_active_role_v1 *active = role_info->active_role_v1;
struct sk_buff *skb;
u8 *cmd, offset;
+ int ret;
int i;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_ROLE_V1);
@@ -1704,7 +1747,8 @@ int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
SET_DRV_INFO, 0, 0,
H2C_LEN_CXDRVINFO_ROLE_V1);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1713,16 +1757,18 @@ int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_btc *btc = &rtwdev->btc;
struct rtw89_btc_ctrl *ctrl = &btc->ctrl;
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_CTRL);
if (!skb) {
@@ -1738,14 +1784,16 @@ int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev)
RTW89_SET_FWCMD_CXCTRL_MANUAL(cmd, ctrl->manual);
RTW89_SET_FWCMD_CXCTRL_IGNORE_BT(cmd, ctrl->igno_bt);
RTW89_SET_FWCMD_CXCTRL_ALWAYS_FREERUN(cmd, ctrl->always_freerun);
- RTW89_SET_FWCMD_CXCTRL_TRACE_STEP(cmd, ctrl->trace_step);
+ if (chip->chip_id == RTL8852A)
+ RTW89_SET_FWCMD_CXCTRL_TRACE_STEP(cmd, ctrl->trace_step);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, BTFC_SET,
SET_DRV_INFO, 0, 0,
H2C_LEN_CXDRVINFO_CTRL);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1754,7 +1802,7 @@ int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_CXDRVINFO_RFK (4 + H2C_LEN_CXDRVHDR)
@@ -1765,6 +1813,7 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev)
struct rtw89_btc_wl_rfk_info *rfk_info = &wl->rfk_info;
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_RFK);
if (!skb) {
@@ -1788,7 +1837,8 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev)
SET_DRV_INFO, 0, 0,
H2C_LEN_CXDRVINFO_RFK);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1797,7 +1847,7 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_PKT_OFLD 4
@@ -1805,6 +1855,7 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
{
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_PKT_OFLD);
if (!skb) {
@@ -1822,7 +1873,8 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1831,7 +1883,7 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
@@ -1840,6 +1892,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
struct sk_buff *skb;
u8 *cmd;
u8 alloc_id;
+ int ret;
alloc_id = rtw89_core_acquire_bit_map(rtwdev->pkt_offload,
RTW89_MAX_PKT_OFLD_NUM);
@@ -1866,7 +1919,8 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
H2C_FUNC_PACKET_OFLD, 1, 1,
H2C_LEN_PKT_OFLD + skb_ofld->len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1875,7 +1929,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_SCAN_LIST_OFFLOAD 4
@@ -1886,6 +1940,7 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
struct sk_buff *skb;
int skb_len = H2C_LEN_SCAN_LIST_OFFLOAD + len * RTW89_MAC_CHINFO_SIZE;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, skb_len);
if (!skb) {
@@ -1930,7 +1985,8 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
H2C_FUNC_ADD_SCANOFLD_CH, 1, 1, skb_len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1939,7 +1995,7 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int len,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
#define H2C_LEN_SCAN_OFFLOAD 28
@@ -1950,6 +2006,7 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
struct sk_buff *skb;
u8 *cmd;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_SCAN_OFFLOAD);
if (!skb) {
@@ -1982,7 +2039,8 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
H2C_FUNC_SCANOFLD, 1, 1,
H2C_LEN_SCAN_OFFLOAD);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -1991,7 +2049,7 @@ int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
@@ -2001,6 +2059,7 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
struct sk_buff *skb;
u8 class = info->rf_path == RF_PATH_A ?
H2C_CL_OUTSRC_RF_REG_A : H2C_CL_OUTSRC_RF_REG_B;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
@@ -2013,7 +2072,8 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
H2C_CAT_OUTSRC, class, page, 0, 0,
len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -2022,7 +2082,7 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
@@ -2031,6 +2091,7 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
struct rtw89_fw_h2c_rf_get_mccch *mccch;
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, sizeof(*mccch));
if (!skb) {
@@ -2052,7 +2113,8 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
H2C_FUNC_OUTSRC_RF_GET_MCCCH, 0, 0,
sizeof(*mccch));
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -2061,7 +2123,7 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc);
@@ -2070,6 +2132,7 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
bool rack, bool dack)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
if (!skb) {
@@ -2082,7 +2145,8 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
H2C_CAT_OUTSRC, h2c_class, h2c_func, rack, dack,
len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -2091,12 +2155,13 @@ int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_no_hdr(rtwdev, len);
if (!skb) {
@@ -2105,7 +2170,8 @@ int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len)
}
skb_put_data(skb, buf, len);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -2114,7 +2180,7 @@ int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
}
void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev)
@@ -2533,6 +2599,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
{
struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
struct cfg80211_scan_request *req = &scan_req->req;
+ u32 rx_fltr = rtwdev->hal.rx_fltr;
u8 mac_addr[ETH_ALEN];
rtwdev->scan_info.scanning_vif = vif;
@@ -2548,13 +2615,13 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
ether_addr_copy(mac_addr, vif->addr);
rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true);
- rtwdev->hal.rx_fltr &= ~B_AX_A_BCN_CHK_EN;
- rtwdev->hal.rx_fltr &= ~B_AX_A_BC;
- rtwdev->hal.rx_fltr &= ~B_AX_A_A1_MATCH;
+ rx_fltr &= ~B_AX_A_BCN_CHK_EN;
+ rx_fltr &= ~B_AX_A_BC;
+ rx_fltr &= ~B_AX_A_A1_MATCH;
rtw89_write32_mask(rtwdev,
rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
B_AX_RX_FLTR_CFG_MASK,
- rtwdev->hal.rx_fltr);
+ rx_fltr);
}
void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
@@ -2568,9 +2635,6 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
if (!vif)
return;
- rtwdev->hal.rx_fltr |= B_AX_A_BCN_CHK_EN;
- rtwdev->hal.rx_fltr |= B_AX_A_BC;
- rtwdev->hal.rx_fltr |= B_AX_A_A1_MATCH;
rtw89_write32_mask(rtwdev,
rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0),
B_AX_RX_FLTR_CFG_MASK,
@@ -2643,6 +2707,7 @@ void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev)
{
struct sk_buff *skb;
+ int ret;
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_FW_CPU_EXCEPTION_LEN);
if (!skb) {
@@ -2661,7 +2726,8 @@ int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev)
H2C_FUNC_CPU_EXCEPTION, 0, 0,
H2C_FW_CPU_EXCEPTION_LEN);
- if (rtw89_h2c_tx(rtwdev, skb, false)) {
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
rtw89_err(rtwdev, "failed to send h2c\n");
goto fail;
}
@@ -2670,5 +2736,59 @@ int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev)
fail:
dev_kfree_skb_any(skb);
- return -EBUSY;
+ return ret;
+}
+
+#define H2C_PKT_DROP_LEN 24
+int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
+ const struct rtw89_pkt_drop_params *params)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_PKT_DROP_LEN);
+ if (!skb) {
+ rtw89_err(rtwdev,
+ "failed to alloc skb for packet drop\n");
+ return -ENOMEM;
+ }
+
+ switch (params->sel) {
+ case RTW89_PKT_DROP_SEL_MACID_BE_ONCE:
+ case RTW89_PKT_DROP_SEL_MACID_BK_ONCE:
+ case RTW89_PKT_DROP_SEL_MACID_VI_ONCE:
+ case RTW89_PKT_DROP_SEL_MACID_VO_ONCE:
+ break;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "H2C of pkt drop might not fully support sel: %d yet\n",
+ params->sel);
+ break;
+ }
+
+ skb_put(skb, H2C_PKT_DROP_LEN);
+ RTW89_SET_FWCMD_PKT_DROP_SEL(skb->data, params->sel);
+ RTW89_SET_FWCMD_PKT_DROP_MACID(skb->data, params->macid);
+ RTW89_SET_FWCMD_PKT_DROP_BAND(skb->data, params->mac_band);
+ RTW89_SET_FWCMD_PKT_DROP_PORT(skb->data, params->port);
+ RTW89_SET_FWCMD_PKT_DROP_MBSSID(skb->data, params->mbssid);
+ RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(skb->data, params->tf_trs);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC,
+ H2C_CL_MAC_FW_OFLD,
+ H2C_FUNC_PKT_DROP, 0, 0,
+ H2C_PKT_DROP_LEN);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ dev_kfree_skb_any(skb);
+ return ret;
}
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index a055ea55b2ad..249a46340853 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -361,6 +361,16 @@ static inline void RTW89_SET_FWCMD_RA_CR_TBL_SEL(void *cmd, u32 val)
le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(10));
}
+static inline void RTW89_SET_FWCMD_RA_FIX_GILTF_EN(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(11));
+}
+
+static inline void RTW89_SET_FWCMD_RA_FIX_GILTF(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(14, 12));
+}
+
static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(void *cmd, u32 val)
{
le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(23, 16));
@@ -1813,6 +1823,36 @@ static inline void RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(void *cmd, u32 val)
le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 0));
}
+static inline void RTW89_SET_FWCMD_PKT_DROP_SEL(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd, val, GENMASK(7, 0));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_MACID(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd, val, GENMASK(15, 8));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_BAND(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd, val, GENMASK(23, 16));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_PORT(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 24));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_MBSSID(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd + 1, val, GENMASK(7, 0));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(void *cmd, u32 val)
+{
+ le32p_replace_bits((__le32 *)cmd + 1, val, GENMASK(15, 8));
+}
+
enum rtw89_btc_btf_h2c_class {
BTFC_SET = 0x10,
BTFC_GET = 0x11,
@@ -2581,6 +2621,7 @@ struct rtw89_fw_h2c_rf_reg_info {
#define H2C_FUNC_OFLD_CFG 0x14
#define H2C_FUNC_ADD_SCANOFLD_CH 0x16
#define H2C_FUNC_SCANOFLD 0x17
+#define H2C_FUNC_PKT_DROP 0x1b
/* CLASS 10 - Security CAM */
#define H2C_CL_MAC_SEC_CAM 0xa
@@ -2611,7 +2652,7 @@ struct rtw89_fw_h2c_rf_get_mccch {
#define RTW89_FW_RSVD_PLE_SIZE 0x800
-#define RTW89_WCPU_BASE_ADDR 0xA0000000
+#define RTW89_WCPU_BASE_MASK GENMASK(27, 0)
#define RTW89_FW_BACKTRACE_INFO_SIZE 8
#define RTW89_VALID_FW_BACKTRACE_SIZE(_size) \
@@ -2708,6 +2749,8 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
bool enable);
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
+int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
+ const struct rtw89_pkt_drop_params *params);
static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
{
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index dd9dbe5ad6d3..dad55952e6bd 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1936,7 +1936,7 @@ static int nav_ctrl_init(struct rtw89_dev *rtwdev)
rtw89_write32_set(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_PLCP_UP_NAV_EN |
B_AX_WMAC_TF_UP_NAV_EN |
B_AX_WMAC_NAV_UPPER_EN);
- rtw89_write32_mask(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_NAV_UPPER_MASK, NAV_12MS);
+ rtw89_write32_mask(rtwdev, R_AX_WMAC_NAV_CTL, B_AX_WMAC_NAV_UPPER_MASK, NAV_25MS);
return 0;
}
@@ -2173,6 +2173,25 @@ static int ptcl_init(struct rtw89_dev *rtwdev, u8 mac_idx)
return 0;
}
+static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx)
+{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ u32 reg;
+ int ret;
+
+ if (chip_id != RTL8852A && chip_id != RTL8852B)
+ return 0;
+
+ ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
+ if (ret)
+ return ret;
+
+ reg = rtw89_mac_reg_by_idx(R_AX_RXDMA_CTRL_0, mac_idx);
+ rtw89_write8_clr(rtwdev, reg, RX_FULL_MODE);
+
+ return 0;
+}
+
static int cmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
{
int ret;
@@ -2248,6 +2267,12 @@ static int cmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
return ret;
}
+ ret = cmac_dma_init(rtwdev, mac_idx);
+ if (ret) {
+ rtw89_err(rtwdev, "[ERR]CMAC%d DMA init %d\n", mac_idx, ret);
+ return ret;
+ }
+
return ret;
}
@@ -2487,8 +2512,7 @@ int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
}
EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v1);
-static u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len,
- bool wd)
+u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd)
{
u32 val, reg;
int ret;
@@ -2508,9 +2532,8 @@ static u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len,
return FIELD_GET(B_AX_WD_BUF_STAT_PKTID_MASK, val);
}
-static int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
- struct rtw89_cpuio_ctrl *ctrl_para,
- bool wd)
+int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
+ struct rtw89_cpuio_ctrl *ctrl_para, bool wd)
{
u32 val, cmd_type, reg;
int ret;
@@ -3084,6 +3107,8 @@ static int rtw89_mac_enable_cpu(struct rtw89_dev *rtwdev, u8 boot_reason,
rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, 0);
rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, 0);
+ rtw89_write32(rtwdev, R_AX_HALT_H2C, 0);
+ rtw89_write32(rtwdev, R_AX_HALT_C2H, 0);
rtw89_write32_set(rtwdev, R_AX_SYS_CLK_CTRL, B_AX_CPU_CLK_EN);
@@ -3161,14 +3186,6 @@ dle:
return ret;
}
-static void rtw89_mac_hci_func_en(struct rtw89_dev *rtwdev)
-{
- const struct rtw89_chip_info *chip = rtwdev->chip;
-
- rtw89_write32_set(rtwdev, chip->hci_func_en_addr,
- B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN);
-}
-
int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
{
rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN,
@@ -3205,7 +3222,7 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev)
return ret;
}
- rtw89_mac_hci_func_en(rtwdev);
+ rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
ret = rtw89_mac_dmac_pre_init(rtwdev);
if (ret)
@@ -4716,3 +4733,48 @@ int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val)
return 0;
}
+
+static
+void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
+{
+ static const enum rtw89_pkt_drop_sel sels[] = {
+ RTW89_PKT_DROP_SEL_MACID_BE_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_BK_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_VI_ONCE,
+ RTW89_PKT_DROP_SEL_MACID_VO_ONCE,
+ };
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_pkt_drop_params params = {0};
+ int i;
+
+ params.mac_band = RTW89_MAC_0;
+ params.macid = rtwsta->mac_id;
+ params.port = rtwvif->port;
+ params.mbssid = 0;
+ params.tf_trs = rtwvif->trigger;
+
+ for (i = 0; i < ARRAY_SIZE(sels); i++) {
+ params.sel = sels[i];
+ rtw89_fw_h2c_pkt_drop(rtwdev, &params);
+ }
+}
+
+static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+ struct rtw89_vif *target = data;
+
+ if (rtwvif != target)
+ return;
+
+ rtw89_mac_pkt_drop_sta(rtwdev, rtwsta);
+}
+
+void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+{
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_mac_pkt_drop_vif_iter,
+ rtwvif);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 986e359a8223..22db80716b56 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -6,6 +6,7 @@
#define __RTW89_MAC_H__
#include "core.h"
+#include "reg.h"
#define MAC_MEM_DUMP_PAGE_SIZE 0x40000
#define ADDR_CAM_ENT_SIZE 0x40
@@ -912,6 +913,45 @@ static inline int rtw89_mac_txpwr_write32_mask(struct rtw89_dev *rtwdev,
return 0;
}
+static inline void rtw89_mac_ctrl_hci_dma_tx(struct rtw89_dev *rtwdev,
+ bool enable)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (enable)
+ rtw89_write32_set(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_TXDMA_EN);
+ else
+ rtw89_write32_clr(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_TXDMA_EN);
+}
+
+static inline void rtw89_mac_ctrl_hci_dma_rx(struct rtw89_dev *rtwdev,
+ bool enable)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (enable)
+ rtw89_write32_set(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_RXDMA_EN);
+ else
+ rtw89_write32_clr(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_RXDMA_EN);
+}
+
+static inline void rtw89_mac_ctrl_hci_dma_trx(struct rtw89_dev *rtwdev,
+ bool enable)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (enable)
+ rtw89_write32_set(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN);
+ else
+ rtw89_write32_clr(rtwdev, chip->hci_func_en_addr,
+ B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN);
+}
+
int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
bool resume, u32 tx_time);
int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
@@ -963,5 +1003,9 @@ enum rtw89_mac_xtal_si_offset {
int rtw89_mac_write_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 mask);
int rtw89_mac_read_xtal_si(struct rtw89_dev *rtwdev, u8 offset, u8 *val);
+void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd);
+int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
+ struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index a8c711ea5d45..e82be57f291c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -13,6 +13,7 @@
#include "reg.h"
#include "sar.h"
#include "ser.h"
+#include "util.h"
static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
@@ -610,6 +611,20 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}
+static
+void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
+{
+ struct rtw89_vif *rtwvif;
+
+ if (vif) {
+ rtwvif = (struct rtw89_vif *)vif->drv_priv;
+ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif);
+ } else {
+ rtw89_for_each_rtwvif(rtwdev, rtwvif)
+ rtw89_mac_pkt_drop_vif(rtwdev, rtwvif);
+ }
+}
+
static void rtw89_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
@@ -618,7 +633,12 @@ static void rtw89_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&rtwdev->mutex);
rtw89_leave_lps(rtwdev);
rtw89_hci_flush_queues(rtwdev, queues, drop);
- rtw89_mac_flush_txq(rtwdev, queues, drop);
+
+ if (drop && RTW89_CHK_FW_FEATURE(PACKET_DROP, &rtwdev->fw))
+ __rtw89_drop_packets(rtwdev, vif);
+ else
+ rtw89_mac_flush_txq(rtwdev, queues, drop);
+
mutex_unlock(&rtwdev->mutex);
}
@@ -841,6 +861,34 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&rtwdev->mutex);
}
+static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct cfg80211_tid_config *tid_config = data;
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_dev *rtwdev = rtwsta->rtwvif->rtwdev;
+
+ rtw89_core_set_tid_config(rtwdev, sta, tid_config);
+}
+
+static int rtw89_ops_set_tid_config(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct cfg80211_tid_config *tid_config)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+
+ mutex_lock(&rtwdev->mutex);
+ if (sta)
+ rtw89_core_set_tid_config(rtwdev, sta, tid_config);
+ else
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_set_tid_config_iter,
+ tid_config);
+ mutex_unlock(&rtwdev->mutex);
+
+ return 0;
+}
+
const struct ieee80211_ops rtw89_ops = {
.tx = rtw89_ops_tx,
.wake_tx_queue = rtw89_ops_wake_tx_queue,
@@ -876,5 +924,6 @@ const struct ieee80211_ops rtw89_ops = {
.unassign_vif_chanctx = rtw89_ops_unassign_vif_chanctx,
.set_sar_specs = rtw89_ops_set_sar_specs,
.sta_rc_update = rtw89_ops_sta_rc_update,
+ .set_tid_config = rtw89_ops_set_tid_config,
};
EXPORT_SYMBOL(rtw89_ops);
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index d2cbe0468cd7..3e8e477d32f7 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -169,6 +169,23 @@ static int rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
return 0;
}
+static void rtw89_pci_ctrl_txdma_ch_pcie(struct rtw89_dev *rtwdev, bool enable)
+{
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
+ const struct rtw89_reg_def *dma_stop1 = &info->dma_stop1;
+ const struct rtw89_reg_def *dma_stop2 = &info->dma_stop2;
+
+ if (enable) {
+ rtw89_write32_clr(rtwdev, dma_stop1->addr, dma_stop1->mask);
+ if (dma_stop2->addr)
+ rtw89_write32_clr(rtwdev, dma_stop2->addr, dma_stop2->mask);
+ } else {
+ rtw89_write32_set(rtwdev, dma_stop1->addr, dma_stop1->mask);
+ if (dma_stop2->addr)
+ rtw89_write32_set(rtwdev, dma_stop2->addr, dma_stop2->mask);
+ }
+}
+
static bool
rtw89_skb_put_rx_data(struct rtw89_dev *rtwdev, bool fs, bool ls,
struct sk_buff *new,
@@ -1607,35 +1624,41 @@ static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data)
writel(data, rtwpci->mmap + addr);
}
-static void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
+static void rtw89_pci_ctrl_dma_trx(struct rtw89_dev *rtwdev, bool enable)
{
- enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
const struct rtw89_pci_info *info = rtwdev->pci_info;
- u32 txhci_en = info->txhci_en_bit;
- u32 rxhci_en = info->rxhci_en_bit;
- if (enable) {
- if (chip_id != RTL8852C)
- rtw89_write32_clr(rtwdev, info->dma_stop1_reg,
- B_AX_STOP_PCIEIO);
- rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
- txhci_en | rxhci_en);
- if (chip_id == RTL8852C)
- rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
- B_AX_STOP_AXI_MST);
+ if (enable)
+ rtw89_write32_set(rtwdev, info->init_cfg_reg,
+ info->rxhci_en_bit | info->txhci_en_bit);
+ else
+ rtw89_write32_clr(rtwdev, info->init_cfg_reg,
+ info->rxhci_en_bit | info->txhci_en_bit);
+}
+
+static void rtw89_pci_ctrl_dma_io(struct rtw89_dev *rtwdev, bool enable)
+{
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ u32 reg, mask;
+
+ if (chip_id == RTL8852C) {
+ reg = R_AX_HAXI_INIT_CFG1;
+ mask = B_AX_STOP_AXI_MST;
} else {
- if (chip_id != RTL8852C)
- rtw89_write32_set(rtwdev, info->dma_stop1_reg,
- B_AX_STOP_PCIEIO);
- else
- rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
- B_AX_STOP_AXI_MST);
- rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
- txhci_en | rxhci_en);
- if (chip_id == RTL8852C)
- rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
- B_AX_STOP_AXI_MST);
+ reg = R_AX_PCIE_DMA_STOP1;
+ mask = B_AX_STOP_PCIEIO;
}
+
+ if (enable)
+ rtw89_write32_clr(rtwdev, reg, mask);
+ else
+ rtw89_write32_set(rtwdev, reg, mask);
+}
+
+static void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
+{
+ rtw89_pci_ctrl_dma_io(rtwdev, enable);
+ rtw89_pci_ctrl_dma_trx(rtwdev, enable);
}
static int rtw89_pci_check_mdio(struct rtw89_dev *rtwdev, u8 addr, u8 speed, u16 rw_bit)
@@ -2437,7 +2460,7 @@ static int rtw89_pci_ops_mac_pre_init(struct rtw89_dev *rtwdev)
rtw89_pci_set_dbg(rtwdev);
rtw89_pci_set_keep_reg(rtwdev);
- rtw89_write32_set(rtwdev, info->dma_stop1_reg, B_AX_STOP_WPDMA);
+ rtw89_write32_set(rtwdev, info->dma_stop1.addr, B_AX_STOP_WPDMA);
/* stop DMA activities */
rtw89_pci_ctrl_dma_all(rtwdev, false);
@@ -2460,10 +2483,9 @@ static int rtw89_pci_ops_mac_pre_init(struct rtw89_dev *rtwdev)
return ret;
}
- /* enable FW CMD queue to download firmware */
- rtw89_write32_set(rtwdev, info->dma_stop1_reg, B_AX_TX_STOP1_ALL);
- rtw89_write32_clr(rtwdev, info->dma_stop1_reg, B_AX_STOP_CH12);
- rtw89_write32_set(rtwdev, info->dma_stop2_reg, B_AX_TX_STOP2_ALL);
+ /* disable all channels except to FW CMD channel to download firmware */
+ rtw89_pci_ctrl_txdma_ch_pcie(rtwdev, false);
+ rtw89_write32_clr(rtwdev, info->dma_stop1.addr, B_AX_STOP_CH12);
/* start DMA activities */
rtw89_pci_ctrl_dma_all(rtwdev, true);
@@ -2491,15 +2513,15 @@ int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en)
if (rtw89_pci_ltr_is_err_reg_val(val))
return -EINVAL;
- rtw89_write32_clr(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_HW_EN);
- rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_EN);
+ rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_HW_EN | B_AX_LTR_EN |
+ B_AX_LTR_WD_NOEMP_CHK);
rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_SPACE_IDX_MASK,
PCI_LTR_SPC_500US);
rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_0, B_AX_LTR_IDLE_TIMER_IDX_MASK,
- PCI_LTR_IDLE_TIMER_800US);
+ PCI_LTR_IDLE_TIMER_3_2MS);
rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX0_TH_MASK, 0x28);
rtw89_write32_mask(rtwdev, R_AX_LTR_CTRL_1, B_AX_LTR_RX1_TH_MASK, 0x28);
- rtw89_write32(rtwdev, R_AX_LTR_IDLE_LATENCY, 0x88e088e0);
+ rtw89_write32(rtwdev, R_AX_LTR_IDLE_LATENCY, 0x90039003);
rtw89_write32(rtwdev, R_AX_LTR_ACTIVE_LATENCY, 0x880b880b);
return 0;
@@ -2576,11 +2598,10 @@ static int rtw89_pci_ops_mac_post_init(struct rtw89_dev *rtwdev)
}
/* enable DMA for all queues */
- rtw89_write32_clr(rtwdev, info->dma_stop1_reg, B_AX_TX_STOP1_ALL);
- rtw89_write32_clr(rtwdev, info->dma_stop2_reg, B_AX_TX_STOP2_ALL);
+ rtw89_pci_ctrl_txdma_ch_pcie(rtwdev, true);
/* Release PCI IO */
- rtw89_write32_clr(rtwdev, info->dma_stop1_reg,
+ rtw89_write32_clr(rtwdev, info->dma_stop1.addr,
B_AX_STOP_WPDMA | B_AX_STOP_PCIEIO);
return 0;
@@ -3478,26 +3499,6 @@ static void rtw89_pci_l1ss_cfg(struct rtw89_dev *rtwdev)
rtw89_pci_l1ss_set(rtwdev, true);
}
-static void rtw89_pci_ctrl_dma_all_pcie(struct rtw89_dev *rtwdev, u8 en)
-{
- const struct rtw89_pci_info *info = rtwdev->pci_info;
- u32 val32;
-
- if (en == MAC_AX_FUNC_EN) {
- val32 = B_AX_STOP_PCIEIO;
- rtw89_write32_clr(rtwdev, info->dma_stop1_reg, val32);
-
- val32 = B_AX_TXHCI_EN | B_AX_RXHCI_EN;
- rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1, val32);
- } else {
- val32 = B_AX_STOP_PCIEIO;
- rtw89_write32_set(rtwdev, info->dma_stop1_reg, val32);
-
- val32 = B_AX_TXHCI_EN | B_AX_RXHCI_EN;
- rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1, val32);
- }
-}
-
static int rtw89_pci_poll_io_idle(struct rtw89_dev *rtwdev)
{
int ret = 0;
@@ -3517,10 +3518,13 @@ static int rtw89_pci_poll_io_idle(struct rtw89_dev *rtwdev)
static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
{
- u32 val, dma_rst = 0;
+ u32 val;
int ret;
- rtw89_pci_ctrl_dma_all_pcie(rtwdev, MAC_AX_FUNC_DIS);
+ if (rtwdev->chip->chip_id == RTL8852C)
+ return 0;
+
+ rtw89_pci_ctrl_dma_all(rtwdev, false);
ret = rtw89_pci_poll_io_idle(rtwdev);
if (ret) {
val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG);
@@ -3528,12 +3532,10 @@ static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
"[PCIe] poll_io_idle fail, before 0x%08x: 0x%08x\n",
R_AX_DBG_ERR_FLAG, val);
if (val & B_AX_TX_STUCK || val & B_AX_PCIE_TXBD_LEN0)
- dma_rst |= B_AX_HCI_TXDMA_EN;
+ rtw89_mac_ctrl_hci_dma_tx(rtwdev, false);
if (val & B_AX_RX_STUCK)
- dma_rst |= B_AX_HCI_RXDMA_EN;
- val = rtw89_read32(rtwdev, R_AX_HCI_FUNC_EN);
- rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val & ~dma_rst);
- rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val | dma_rst);
+ rtw89_mac_ctrl_hci_dma_rx(rtwdev, false);
+ rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
ret = rtw89_pci_poll_io_idle(rtwdev);
val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG);
rtw89_debug(rtwdev, RTW89_DBG_HCI,
@@ -3544,18 +3546,7 @@ static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
return ret;
}
-static void rtw89_pci_ctrl_hci_dma_en(struct rtw89_dev *rtwdev, u8 en)
-{
- u32 val32;
- if (en == MAC_AX_FUNC_EN) {
- val32 = B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN;
- rtw89_write32_set(rtwdev, R_AX_HCI_FUNC_EN, val32);
- } else {
- val32 = B_AX_HCI_TXDMA_EN | B_AX_HCI_RXDMA_EN;
- rtw89_write32_clr(rtwdev, R_AX_HCI_FUNC_EN, val32);
- }
-}
static int rtw89_pci_rst_bdram(struct rtw89_dev *rtwdev)
{
@@ -3575,15 +3566,18 @@ static int rtw89_pci_lv1rst_start_dma(struct rtw89_dev *rtwdev)
{
u32 ret;
- rtw89_pci_ctrl_hci_dma_en(rtwdev, MAC_AX_FUNC_DIS);
- rtw89_pci_ctrl_hci_dma_en(rtwdev, MAC_AX_FUNC_EN);
+ if (rtwdev->chip->chip_id == RTL8852C)
+ return 0;
+
+ rtw89_mac_ctrl_hci_dma_trx(rtwdev, false);
+ rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
rtw89_pci_clr_idx_all(rtwdev);
ret = rtw89_pci_rst_bdram(rtwdev);
if (ret)
return ret;
- rtw89_pci_ctrl_dma_all_pcie(rtwdev, MAC_AX_FUNC_EN);
+ rtw89_pci_ctrl_dma_all(rtwdev, true);
return ret;
}
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index 63dc6d4db602..af6f6d5c4770 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -410,6 +410,16 @@
#define B_AX_STOP_RPQ BIT(1)
#define B_AX_STOP_RXQ BIT(0)
#define B_AX_TX_STOP1_ALL GENMASK(18, 8)
+#define B_AX_TX_STOP1_MASK (B_AX_STOP_ACH0 | B_AX_STOP_ACH1 | \
+ B_AX_STOP_ACH2 | B_AX_STOP_ACH3 | \
+ B_AX_STOP_ACH4 | B_AX_STOP_ACH5 | \
+ B_AX_STOP_ACH6 | B_AX_STOP_ACH7 | \
+ B_AX_STOP_CH8 | B_AX_STOP_CH9 | \
+ B_AX_STOP_CH12)
+#define B_AX_TX_STOP1_MASK_V1 (B_AX_STOP_ACH0 | B_AX_STOP_ACH1 | \
+ B_AX_STOP_ACH2 | B_AX_STOP_ACH3 | \
+ B_AX_STOP_CH8 | B_AX_STOP_CH9 | \
+ B_AX_STOP_CH12)
#define R_AX_PCIE_DMA_STOP2 0x1310
#define B_AX_STOP_CH11 BIT(1)
@@ -564,11 +574,6 @@ enum rtw89_pcie_phy {
PCIE_PHY_GEN1_UNDEFINE = 0x7F,
};
-enum mac_ax_func_sw {
- MAC_AX_FUNC_DIS,
- MAC_AX_FUNC_EN,
-};
-
enum rtw89_pcie_l0sdly {
PCIE_L0SDLY_1US = 0,
PCIE_L0SDLY_2US = 1,
@@ -747,8 +752,8 @@ struct rtw89_pci_info {
u32 max_tag_num_mask;
u32 rxbd_rwptr_clr_reg;
u32 txbd_rwptr_clr2_reg;
- u32 dma_stop1_reg;
- u32 dma_stop2_reg;
+ struct rtw89_reg_def dma_stop1;
+ struct rtw89_reg_def dma_stop2;
u32 dma_busy1_reg;
u32 dma_busy2_reg;
u32 dma_busy3_reg;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 094f41cd0928..be2c3715bbf4 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -193,6 +193,40 @@ static const u64
rtw89_ra_mask_he_rates[4] = {RA_MASK_HE_1SS_RATES, RA_MASK_HE_2SS_RATES,
RA_MASK_HE_3SS_RATES, RA_MASK_HE_4SS_RATES};
+static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
+ struct rtw89_sta *rtwsta,
+ bool *fix_giltf_en, u8 *fix_giltf)
+{
+ const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+ struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
+ u8 band = chan->band_type;
+ enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+ u8 he_gi = mask->control[nl_band].he_gi;
+ u8 he_ltf = mask->control[nl_band].he_ltf;
+
+ if (!rtwsta->use_cfg_mask)
+ return;
+
+ if (he_ltf == 2 && he_gi == 2) {
+ *fix_giltf = RTW89_GILTF_LGI_4XHE32;
+ } else if (he_ltf == 2 && he_gi == 0) {
+ *fix_giltf = RTW89_GILTF_SGI_4XHE08;
+ } else if (he_ltf == 1 && he_gi == 1) {
+ *fix_giltf = RTW89_GILTF_2XHE16;
+ } else if (he_ltf == 1 && he_gi == 0) {
+ *fix_giltf = RTW89_GILTF_2XHE08;
+ } else if (he_ltf == 0 && he_gi == 1) {
+ *fix_giltf = RTW89_GILTF_1XHE16;
+ } else if (he_ltf == 0 && he_gi == 0) {
+ *fix_giltf = RTW89_GILTF_1XHE08;
+ } else {
+ *fix_giltf_en = false;
+ return;
+ }
+
+ *fix_giltf_en = true;
+}
+
static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
struct ieee80211_sta *sta, bool csi)
{
@@ -210,8 +244,10 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
u8 bw_mode = 0;
u8 stbc_en = 0;
u8 ldpc_en = 0;
+ u8 fix_giltf = 0;
u8 i;
bool sgi = false;
+ bool fix_giltf_en = false;
memset(ra, 0, sizeof(*ra));
/* Set the ra mask from sta's capability */
@@ -226,6 +262,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
ldpc_en = 1;
+ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, &fix_giltf_en, &fix_giltf);
} else if (sta->deflink.vht_cap.vht_supported) {
u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map);
@@ -335,6 +372,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
ra->en_sgi = sgi;
ra->ra_mask = ra_mask;
+ ra->fix_giltf_en = fix_giltf_en;
+ ra->fix_giltf = fix_giltf;
if (!csi)
return;
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 19e5e09bf726..9426b53e663b 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -479,6 +479,7 @@
#define R_AX_LTR_CTRL_0 0x8410
#define B_AX_LTR_SPACE_IDX_MASK GENMASK(13, 12)
#define B_AX_LTR_IDLE_TIMER_IDX_MASK GENMASK(10, 8)
+#define B_AX_LTR_WD_NOEMP_CHK BIT(6)
#define B_AX_APP_LTR_ACT BIT(5)
#define B_AX_APP_LTR_IDLE BIT(4)
#define B_AX_LTR_EN BIT(1)
@@ -2332,6 +2333,28 @@
#define B_AX_DLE_IMR_SET (B_AX_RXSTS_FSM_HANG_ERROR_IMR | \
B_AX_RXDATA_FSM_HANG_ERROR_IMR)
+#define R_AX_RXDMA_CTRL_0 0xC804
+#define R_AX_RXDMA_CTRL_0_C1 0xE804
+#define B_AX_RXDMA_DBGOUT_EN BIT(31)
+#define B_AX_RXDMA_DBG_SEL_MASK GENMASK(30, 29)
+#define B_AX_RXDMA_FIFO_DBG_SEL_MASK GENMASK(28, 25)
+#define B_AX_RXDMA_DEFAULT_PAGE_MASK GENMASK(22, 21)
+#define B_AX_RXDMA_BUFF_REQ_PRI_MASK GENMASK(20, 19)
+#define B_AX_RXDMA_TGT_QUEID_MASK GENMASK(18, 13)
+#define B_AX_RXDMA_TGT_PRID_MASK GENMASK(12, 10)
+#define B_AX_RXDMA_DIS_CSI_RELEASE BIT(9)
+#define B_AX_RXDMA_DIS_RXSTS_WAIT_PTR_CLR BIT(7)
+#define B_AX_RXDMA_DIS_CSI_WAIT_PTR_CLR BIT(6)
+#define B_AX_RXSTS_PTR_FULL_MODE BIT(5)
+#define B_AX_CSI_PTR_FULL_MODE BIT(4)
+#define B_AX_RU3_PTR_FULL_MODE BIT(3)
+#define B_AX_RU2_PTR_FULL_MODE BIT(2)
+#define B_AX_RU1_PTR_FULL_MODE BIT(1)
+#define B_AX_RU0_PTR_FULL_MODE BIT(0)
+#define RX_FULL_MODE (B_AX_RU0_PTR_FULL_MODE | B_AX_RU1_PTR_FULL_MODE | \
+ B_AX_RU2_PTR_FULL_MODE | B_AX_RU3_PTR_FULL_MODE | \
+ B_AX_CSI_PTR_FULL_MODE | B_AX_RXSTS_PTR_FULL_MODE)
+
#define R_AX_RXDMA_PKT_INFO_0 0xC814
#define R_AX_RXDMA_PKT_INFO_1 0xC818
#define R_AX_RXDMA_PKT_INFO_2 0xC81C
@@ -2596,6 +2619,7 @@
#define B_AX_WMAC_TF_UP_NAV_EN BIT(16)
#define B_AX_WMAC_NAV_UPPER_MASK GENMASK(15, 8)
#define NAV_12MS 0xBC
+#define NAV_25MS 0xC4
#define B_AX_WMAC_RTS_RST_DUR_MASK GENMASK(7, 0)
#define R_AX_RXTRIG_TEST_USER_2 0xCCB0
@@ -3156,6 +3180,18 @@
#define B_AX_GNT_WL_BB_VAL BIT(1)
#define B_AX_GNT_WL_BB_SWCTRL BIT(0)
+#define R_AX_GNT_VAL 0x0054
+#define B_AX_GNT_BT_RFC_S1_STA BIT(5)
+#define B_AX_GNT_WL_RFC_S1_STA BIT(4)
+#define B_AX_GNT_BT_RFC_S0_STA BIT(3)
+#define B_AX_GNT_WL_RFC_S0_STA BIT(2)
+
+#define R_AX_GNT_VAL_V1 0xDA4C
+#define B_AX_GNT_BT_RFC_S1 BIT(4)
+#define B_AX_GNT_BT_RFC_S0 BIT(3)
+#define B_AX_GNT_WL_RFC_S1 BIT(2)
+#define B_AX_GNT_WL_RFC_S0 BIT(1)
+
#define R_AX_TDMA_MODE 0xDA4C
#define R_AX_TDMA_MODE_C1 0xFA4C
#define B_AX_R_BT_CMD_RPT_MASK GENMASK(31, 16)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 4eddfa23dcad..be3ec41dc55c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -1843,6 +1843,9 @@ static void rtw8852a_btc_init_cfg(struct rtw89_dev *rtwdev)
RF_PATH_A, BTC_BT_SS_GROUP, 0x5ff);
rtw8852a_set_trx_mask(rtwdev,
RF_PATH_B, BTC_BT_SS_GROUP, 0x5ff);
+ /* set path-A(S0) Tx/Rx no-mask if GNT_WL=0 && BT_S1=tx group */
+ rtw8852a_set_trx_mask(rtwdev,
+ RF_PATH_A, BTC_BT_TX_GROUP, 0x5ff);
} else { /* set WL Tx stb if GNT_WL = 0 && BT_S1 = ss group for 3-ant */
rtw8852a_set_trx_mask(rtwdev,
RF_PATH_A, BTC_BT_SS_GROUP, 0x5df);
@@ -2056,6 +2059,51 @@ void rtw8852a_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
}
+static void rtw8852a_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level)
+{
+ /* level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB
+ * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
+ * To improve BT ACI in co-rx
+ */
+
+ switch (level) {
+ case 0: /* default */
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x1000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x17);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x2);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
+ break;
+ case 1: /* Fix LNA2=5 */
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x1000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x5);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x2);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
+ break;
+ }
+}
+
+static void rtw8852a_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
+{
+ switch (level) {
+ case 0: /* original */
+ rtw8852a_bb_ctrl_btc_preagc(rtwdev, false);
+ rtw8852a_set_wl_lna2(rtwdev, 0);
+ break;
+ case 1: /* for FDD free-run */
+ rtw8852a_bb_ctrl_btc_preagc(rtwdev, true);
+ rtw8852a_set_wl_lna2(rtwdev, 0);
+ break;
+ case 2: /* for BTG Co-Rx*/
+ rtw8852a_bb_ctrl_btc_preagc(rtwdev, false);
+ rtw8852a_set_wl_lna2(rtwdev, 1);
+ break;
+ }
+}
+
static void rtw8852a_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status)
@@ -2132,6 +2180,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.btc_bt_aci_imp = rtw8852a_btc_bt_aci_imp,
.btc_update_bt_cnt = rtw8852a_btc_update_bt_cnt,
.btc_wl_s1_standby = rtw8852a_btc_wl_s1_standby,
+ .btc_set_wl_rx_gain = rtw8852a_btc_set_wl_rx_gain,
.btc_set_policy = rtw89_btc_set_policy,
};
@@ -2185,11 +2234,12 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.dav_log_efuse_size = 0,
.phycap_addr = 0x580,
.phycap_size = 128,
- .para_ver = 0x05050864,
- .wlcx_desired = 0x05050000,
- .btcx_desired = 0x5,
+ .para_ver = 0x0,
+ .wlcx_desired = 0x06000000,
+ .btcx_desired = 0x7,
.scbd = 0x1,
.mailbox = 0x1,
+ .btc_fwinfo_buf = 1024,
.fcxbtcrpt_ver = 1,
.fcxtdma_ver = 1,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
index 190c4aefb02e..d600100db9eb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
@@ -33,8 +33,8 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR,
.txbd_rwptr_clr2_reg = R_AX_TXBD_RWPTR_CLR2,
- .dma_stop1_reg = R_AX_PCIE_DMA_STOP1,
- .dma_stop2_reg = R_AX_PCIE_DMA_STOP2,
+ .dma_stop1 = {R_AX_PCIE_DMA_STOP1, B_AX_TX_STOP1_MASK},
+ .dma_stop2 = {R_AX_PCIE_DMA_STOP2, B_AX_TX_STOP2_ALL},
.dma_busy1_reg = R_AX_PCIE_DMA_BUSY1,
.dma_busy2_reg = R_AX_PCIE_DMA_BUSY2,
.dma_busy3_reg = R_AX_PCIE_DMA_BUSY1,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 0d92518a1e0d..5dff65dbc142 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -2854,6 +2854,59 @@ void rtw8852c_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state)
rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
}
+static void rtw8852c_set_wl_lna2(struct rtw89_dev *rtwdev, u8 level)
+{
+ /* level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB
+ * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB
+ * To improve BT ACI in co-rx
+ */
+
+ switch (level) {
+ case 0: /* default */
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x1000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x17);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x2);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x17);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
+ break;
+ case 1: /* Fix LNA2=5 */
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x1000);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x1);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x5);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x2);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x15);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWA, RFREG_MASK, 0x3);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWD0, RFREG_MASK, 0x5);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_LUTWE, RFREG_MASK, 0x0);
+ break;
+ }
+}
+
+static void rtw8852c_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
+{
+ switch (level) {
+ case 0: /* original */
+ rtw8852c_bb_ctrl_btc_preagc(rtwdev, false);
+ rtw8852c_set_wl_lna2(rtwdev, 0);
+ break;
+ case 1: /* for FDD free-run */
+ rtw8852c_bb_ctrl_btc_preagc(rtwdev, true);
+ rtw8852c_set_wl_lna2(rtwdev, 0);
+ break;
+ case 2: /* for BTG Co-Rx*/
+ rtw8852c_bb_ctrl_btc_preagc(rtwdev, false);
+ rtw8852c_set_wl_lna2(rtwdev, 1);
+ break;
+ }
+}
+
static void rtw8852c_fill_freq_with_ppdu(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct ieee80211_rx_status *status)
@@ -2974,6 +3027,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.btc_bt_aci_imp = rtw8852c_btc_bt_aci_imp,
.btc_update_bt_cnt = rtw8852c_btc_update_bt_cnt,
.btc_wl_s1_standby = rtw8852c_btc_wl_s1_standby,
+ .btc_set_wl_rx_gain = rtw8852c_btc_set_wl_rx_gain,
.btc_set_policy = rtw89_btc_set_policy_v1,
};
@@ -3030,11 +3084,12 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.dav_log_efuse_size = 16,
.phycap_addr = 0x590,
.phycap_size = 0x60,
- .para_ver = 0x05050764,
- .wlcx_desired = 0x05050000,
- .btcx_desired = 0x5,
+ .para_ver = 0x1,
+ .wlcx_desired = 0x06000000,
+ .btcx_desired = 0x7,
.scbd = 0x1,
.mailbox = 0x1,
+ .btc_fwinfo_buf = 1280,
.fcxbtcrpt_ver = 4,
.fcxtdma_ver = 3,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
index fc0394494013..be6b4e4d6491 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
@@ -42,8 +42,8 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
.max_tag_num_mask = B_AX_MAX_TAG_NUM_V1_MASK,
.rxbd_rwptr_clr_reg = R_AX_RXBD_RWPTR_CLR_V1,
.txbd_rwptr_clr2_reg = R_AX_TXBD_RWPTR_CLR2_V1,
- .dma_stop1_reg = R_AX_HAXI_DMA_STOP1,
- .dma_stop2_reg = R_AX_HAXI_DMA_STOP2,
+ .dma_stop1 = {R_AX_HAXI_DMA_STOP1, B_AX_TX_STOP1_MASK},
+ .dma_stop2 = {R_AX_HAXI_DMA_STOP2, B_AX_TX_STOP2_ALL},
.dma_busy1_reg = R_AX_HAXI_DMA_BUSY1,
.dma_busy2_reg = R_AX_HAXI_DMA_BUSY2,
.dma_busy3_reg = R_AX_HAXI_DMA_BUSY3,
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index ee0ae2816860..c1a4bc1c64d1 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -396,6 +396,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt)
switch (evt) {
case SER_EV_STATE_IN:
rtw89_hci_recovery_complete(rtwdev);
+ clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags);
break;
case SER_EV_L1_RESET:
ser_state_goto(ser, SER_RESET_TRX_ST);
@@ -539,7 +540,7 @@ static int rtw89_ser_fw_backtrace_dump(struct rtw89_dev *rtwdev, u8 *buf,
const struct __fw_backtrace_entry *ent)
{
struct __fw_backtrace_info *ptr = (struct __fw_backtrace_info *)buf;
- u32 fwbt_addr = ent->wcpu_addr - RTW89_WCPU_BASE_ADDR;
+ u32 fwbt_addr = ent->wcpu_addr & RTW89_WCPU_BASE_MASK;
u32 fwbt_size = ent->size;
u32 fwbt_key = ent->key;
u32 i;
@@ -632,7 +633,6 @@ static void ser_l2_reset_st_hdl(struct rtw89_ser *ser, u8 evt)
fallthrough;
case SER_EV_L2_RECFG_DONE:
ser_state_goto(ser, SER_IDLE_ST);
- clear_bit(RTW89_FLAG_RESTART_TRIGGER, rtwdev->flags);
break;
case SER_EV_STATE_OUT:
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 325933217b41..82a7458e01ae 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -251,7 +251,7 @@ struct ndis_80211_bssid_ex {
struct ndis_80211_bssid_list_ex {
__le32 num_items;
- struct ndis_80211_bssid_ex bssid[];
+ u8 bssid_data[];
} __packed;
struct ndis_80211_fixed_ies {
@@ -2084,7 +2084,8 @@ resize_buf:
netdev_dbg(usbdev->net, "%s(): buflen: %d\n", __func__, len);
bssid_len = 0;
- bssid = next_bssid_list_item(bssid_list->bssid, &bssid_len, buf, len);
+ bssid = next_bssid_list_item((void *)bssid_list->bssid_data,
+ &bssid_len, buf, len);
/* Device returns incorrect 'num_items'. Workaround by ignoring the
* received 'num_items' and walking through full bssid buffer instead.
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index e3314f746bfa..2d94c30ed439 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -271,6 +271,7 @@
#define BCMA_CC_SROM_CONTROL_OP_WRDIS 0x40000000
#define BCMA_CC_SROM_CONTROL_OP_WREN 0x60000000
#define BCMA_CC_SROM_CONTROL_OTPSEL 0x00000010
+#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
#define BCMA_CC_SROM_CONTROL_LOCK 0x00000008
#define BCMA_CC_SROM_CONTROL_SIZE_MASK 0x00000006
#define BCMA_CC_SROM_CONTROL_SIZE_1K 0x00000000