From 24f0bd136264ec0284749fc65b2aca2671cd2b23 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Sun, 26 Jan 2020 19:33:39 +0000 Subject: [PATCH 001/168] brcmfmac: add the BRCM 4364 found in MacBook Pro 15,2 The 2018 13" MacBook Pro (MacBookPro15,2) has a Broadcom chip, the 4364. This chip appears to be specific to Apple and is not found in other hardware. Add this chip to the brcmfmac driver so that it can be recognized automatically. Note that the PCI device id is 4464 even though the chip is referred to as the 4364. Signed-off-by: brian m. carlson Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 3 +++ drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 282d0bc14e8e..a3a257089696 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -723,6 +723,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) return 0x200000; case BRCM_CC_4359_CHIP_ID: return (ci->pub.chiprev < 9) ? 0x180000 : 0x160000; + case BRCM_CC_4364_CHIP_ID: case CY_CC_4373_CHIP_ID: return 0x160000; default: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 5105f62767fb..39381cbde89e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -52,6 +52,7 @@ BRCMF_FW_DEF(4356, "brcmfmac4356-pcie"); BRCMF_FW_DEF(43570, "brcmfmac43570-pcie"); BRCMF_FW_DEF(4358, "brcmfmac4358-pcie"); BRCMF_FW_DEF(4359, "brcmfmac4359-pcie"); +BRCMF_FW_DEF(4364, "brcmfmac4364-pcie"); BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie"); BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); @@ -70,6 +71,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570), BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), + BRCMF_FW_ENTRY(BRCM_CC_4364_CHIP_ID, 0xFFFFFFFF, 4364), BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B), BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C), BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), @@ -2105,6 +2107,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), 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 d1037b6ef2d6..c6c4be05159d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h @@ -44,6 +44,7 @@ #define BRCM_CC_4358_CHIP_ID 0x4358 #define BRCM_CC_4359_CHIP_ID 0x4359 #define BRCM_CC_43602_CHIP_ID 43602 +#define BRCM_CC_4364_CHIP_ID 0x4364 #define BRCM_CC_4365_CHIP_ID 0x4365 #define BRCM_CC_4366_CHIP_ID 0x4366 #define BRCM_CC_43664_CHIP_ID 43664 @@ -74,6 +75,7 @@ #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc #define BRCM_PCIE_43602_RAW_DEVICE_ID 43602 +#define BRCM_PCIE_4364_DEVICE_ID 0x4464 #define BRCM_PCIE_4365_DEVICE_ID 0x43ca #define BRCM_PCIE_4365_2G_DEVICE_ID 0x43cb #define BRCM_PCIE_4365_5G_DEVICE_ID 0x43cc From 57f0a29c3e089b74a42ff62289a47512ab3f8eba Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sun, 26 Jan 2020 21:00:13 +0100 Subject: [PATCH 002/168] DTS: bindings: wl1251: mark ti,power-gpio as optional It is now only useful for SPI interface. Power control of SDIO mode is done through mmc core. Suggested by: Ulf Hansson Signed-off-by: H. Nikolaus Schaller Signed-off-by: Kalle Valo --- Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt b/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt index f38950560982..88fd28d15eac 100644 --- a/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt +++ b/Documentation/devicetree/bindings/net/wireless/ti,wl1251.txt @@ -9,11 +9,12 @@ Required properties: - spi-max-frequency : Maximum SPI clocking speed of device in Hz - interrupts : Should contain interrupt line - vio-supply : phandle to regulator providing VIO -- ti,power-gpio : GPIO connected to chip's PMEN pin Optional properties: - ti,wl1251-has-eeprom : boolean, the wl1251 has an eeprom connected, which provides configuration data (calibration, MAC, ...) +- ti,power-gpio : GPIO connected to chip's PMEN pin if operated in + SPI mode - Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional SPI connection related properties, From 346bdd8e979d03ba1a2d3040130b751b6bc26138 Mon Sep 17 00:00:00 2001 From: "H. Nikolaus Schaller" Date: Sun, 26 Jan 2020 21:00:14 +0100 Subject: [PATCH 003/168] wl1251: remove ti,power-gpio for SDIO mode Remove handling of this property from code. Note that wl->power_gpio is still needed in the header file for SPI mode (N900). Suggested by: Ulf Hansson Signed-off-by: H. Nikolaus Schaller Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl1251/sdio.c | 32 ++------------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index 94569cd695c8..c9a4e9a43400 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include "wl1251.h" @@ -160,15 +158,6 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) int ret; if (enable) { - /* - * Power is controlled by runtime PM, but we still call board - * callback in case it wants to do any additional setup, - * for example enabling clock buffer for the module. - */ - if (gpio_is_valid(wl->power_gpio)) - gpio_set_value(wl->power_gpio, true); - - ret = pm_runtime_get_sync(&func->dev); if (ret < 0) { pm_runtime_put_sync(&func->dev); @@ -186,9 +175,6 @@ static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) ret = pm_runtime_put_sync(&func->dev); if (ret < 0) goto out; - - if (gpio_is_valid(wl->power_gpio)) - gpio_set_value(wl->power_gpio, false); } out: @@ -241,31 +227,17 @@ static int wl1251_sdio_probe(struct sdio_func *func, wl1251_board_data = wl1251_get_platform_data(); if (!IS_ERR(wl1251_board_data)) { - wl->power_gpio = wl1251_board_data->power_gpio; wl->irq = wl1251_board_data->irq; wl->use_eeprom = wl1251_board_data->use_eeprom; } else if (np) { - wl->use_eeprom = of_property_read_bool(np, - "ti,wl1251-has-eeprom"); - wl->power_gpio = of_get_named_gpio(np, "ti,power-gpio", 0); + wl->use_eeprom = of_property_read_bool(np, "ti,wl1251-has-eeprom"); wl->irq = of_irq_get(np, 0); - - if (wl->power_gpio == -EPROBE_DEFER || - wl->irq == -EPROBE_DEFER) { + if (wl->irq == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto disable; } } - if (gpio_is_valid(wl->power_gpio)) { - ret = devm_gpio_request(&func->dev, wl->power_gpio, - "wl1251 power"); - if (ret) { - wl1251_error("Failed to request gpio: %d\n", ret); - goto disable; - } - } - if (wl->irq) { irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); From a3ebb0335c545e05fb7693e246b91946276b83fe Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:44 +0000 Subject: [PATCH 004/168] qtnfmac: use MAJOR.MINOR format for firmware protocol Use MAJOR.MINOR format for QLink firmware protocol. MAJOR part is incremented when backward compatibility is broken. Normally this part should not be incremented unless there is a good reason for that. MINOR part is incremented each time when new features are added to qlink.h, e.g. new TLVs, events, commands. These changes should not break backward compatibility. For instance, older firmware versions may not be able to parse new flags or send new types of events, but this does not impact normal system operations. As part of initialization sequence, driver requests protocol version from firmware and refuses to start in case there is a mismatch in MAJOR part of the version. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 59 ++++++++++++------- drivers/net/wireless/quantenna/qtnfmac/core.c | 16 ++--- drivers/net/wireless/quantenna/qtnfmac/core.h | 2 +- .../net/wireless/quantenna/qtnfmac/qlink.h | 42 ++++++++++++- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index d0d7ec8794c4..4f52e2fd7f38 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -900,7 +900,6 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, hwinfo->num_mac = resp->num_mac; hwinfo->mac_bitmap = resp->mac_bitmap; hwinfo->fw_ver = le32_to_cpu(resp->fw_ver); - hwinfo->ql_proto_ver = le16_to_cpu(resp->ql_proto_ver); hwinfo->total_tx_chain = resp->total_tx_chain; hwinfo->total_rx_chain = resp->total_rx_chain; hwinfo->hw_capab = le32_to_cpu(resp->hw_capab); @@ -954,25 +953,29 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - pr_info("fw_version=%d, MACs map %#x, chains Tx=%u Rx=%u, capab=0x%x\n", - hwinfo->fw_ver, hwinfo->mac_bitmap, - hwinfo->total_tx_chain, hwinfo->total_rx_chain, - hwinfo->hw_capab); - - pr_info("\nBuild name: %s" \ - "\nBuild revision: %s" \ - "\nBuild type: %s" \ - "\nBuild label: %s" \ - "\nBuild timestamp: %lu" \ - "\nPlatform ID: %lu" \ - "\nHardware ID: %s" \ - "\nCalibration version: %s" \ - "\nU-Boot version: %s" \ - "\nHardware version: 0x%08x\n", + pr_info("\nBuild name: %s\n" + "Build revision: %s\n" + "Build type: %s\n" + "Build label: %s\n" + "Build timestamp: %lu\n" + "Platform ID: %lu\n" + "Hardware ID: %s\n" + "Calibration version: %s\n" + "U-Boot version: %s\n" + "Hardware version: 0x%08x\n" + "Qlink ver: %u.%u\n" + "MACs map: %#x\n" + "Chains Rx-Tx: %ux%u\n" + "FW version: 0x%x\n", bld_name, bld_rev, bld_type, bld_label, (unsigned long)bld_tmstamp, (unsigned long)plat_id, - hw_id, calibration_ver, uboot_ver, hw_ver); + hw_id, calibration_ver, uboot_ver, hw_ver, + QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver), + QLINK_VER_MINOR(bus->hw_info.ql_proto_ver), + hwinfo->mac_bitmap, + hwinfo->total_rx_chain, hwinfo->total_tx_chain, + hwinfo->fw_ver); strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version)); hwinfo->hw_version = hw_ver; @@ -1866,23 +1869,35 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) int qtnf_cmd_send_init_fw(struct qtnf_bus *bus) { + struct sk_buff *resp_skb = NULL; + struct qlink_resp_init_fw *resp; + struct qlink_cmd_init_fw *cmd; struct sk_buff *cmd_skb; - int ret = 0; + size_t info_len = 0; + int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(QLINK_MACID_RSVD, QLINK_VIFID_RSVD, QLINK_CMD_FW_INIT, - sizeof(struct qlink_cmd)); + sizeof(*cmd)); if (!cmd_skb) return -ENOMEM; + cmd = (struct qlink_cmd_init_fw *)cmd_skb->data; + cmd->qlink_proto_ver = cpu_to_le32(QLINK_PROTO_VER); + qtnf_bus_lock(bus); - ret = qtnf_cmd_send(bus, cmd_skb); + ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb, + sizeof(*resp), &info_len); + qtnf_bus_unlock(bus); + if (ret) goto out; -out: - qtnf_bus_unlock(bus); + resp = (struct qlink_resp_init_fw *)resp_skb->data; + bus->hw_info.ql_proto_ver = le32_to_cpu(resp->qlink_proto_ver); +out: + consume_skb(resp_skb); return ret; } diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 4320180f8c07..a21b09afd103 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -756,6 +756,15 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } + if (QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver) != + QLINK_PROTO_VER_MAJOR) { + pr_err("qlink driver vs FW version mismatch: %u vs %u\n", + QLINK_PROTO_VER_MAJOR, + QLINK_VER_MAJOR(bus->hw_info.ql_proto_ver)); + ret = -EPROTONOSUPPORT; + goto error; + } + bus->fw_state = QTNF_FW_STATE_ACTIVE; ret = qtnf_cmd_get_hw_info(bus); if (ret) { @@ -763,13 +772,6 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } - if (bus->hw_info.ql_proto_ver != QLINK_PROTO_VER) { - pr_err("qlink version mismatch %u != %u\n", - QLINK_PROTO_VER, bus->hw_info.ql_proto_ver); - ret = -EPROTONOSUPPORT; - goto error; - } - if ((bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) && bus->bus_ops->data_tx_use_meta_set) bus->bus_ops->data_tx_use_meta_set(bus, true); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index d715e1cd0006..78fee516cea4 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -117,7 +117,7 @@ struct qtnf_wmac { }; struct qtnf_hw_info { - u16 ql_proto_ver; + u32 ql_proto_ver; u8 num_mac; u8 mac_bitmap; u32 fw_ver; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index b2edb03819d1..3722e707232c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -6,7 +6,18 @@ #include -#define QLINK_PROTO_VER 16 +#define QLINK_PROTO_VER_MAJOR_M 0xFFFF +#define QLINK_PROTO_VER_MAJOR_S 16 +#define QLINK_PROTO_VER_MINOR_M 0xFFFF +#define QLINK_VER_MINOR(_ver) ((_ver) & QLINK_PROTO_VER_MINOR_M) +#define QLINK_VER_MAJOR(_ver) \ + (((_ver) >> QLINK_PROTO_VER_MAJOR_S) & QLINK_PROTO_VER_MAJOR_M) +#define QLINK_VER(_maj, _min) (((_maj) << QLINK_PROTO_VER_MAJOR_S) | (_min)) + +#define QLINK_PROTO_VER_MAJOR 18 +#define QLINK_PROTO_VER_MINOR 0 +#define QLINK_PROTO_VER \ + QLINK_VER(QLINK_PROTO_VER_MAJOR, QLINK_PROTO_VER_MINOR) #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -326,6 +337,23 @@ struct qlink_cmd { u8 vifid; } __packed; +/** + * struct qlink_cmd_init_fw - data for QLINK_CMD_FW_INIT + * + * Initialize firmware based on specified host configuration. This is the first + * command sent to wifi card and it's fixed part should never be changed, any + * additions must be done by appending TLVs. + * If wifi card can not operate with a specified parameters it will return + * error. + * + * @qlink_proto_ver: QLINK protocol version used by host driver. + */ +struct qlink_cmd_init_fw { + struct qlink_cmd chdr; + __le32 qlink_proto_ver; + u8 var_info[0]; +} __packed; + /** * struct qlink_cmd_manage_intf - interface management command * @@ -895,6 +923,16 @@ struct qlink_resp { u8 vifid; } __packed; +/** + * struct qlink_resp_init_fw - response for QLINK_CMD_FW_INIT + * + * @qlink_proto_ver: QLINK protocol version used by wifi card firmware. + */ +struct qlink_resp_init_fw { + struct qlink_resp rhdr; + __le32 qlink_proto_ver; +} __packed; + /** * enum qlink_dfs_regions - regulatory DFS regions * @@ -953,7 +991,6 @@ struct qlink_resp_get_mac_info { * * @fw_ver: wireless hardware firmware version. * @hw_capab: Bitmap of capabilities supported by firmware. - * @ql_proto_ver: Version of QLINK protocol used by firmware. * @num_mac: Number of separate physical radio devices provided by hardware. * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware. * @total_tx_chains: total number of transmit chains used by device. @@ -967,7 +1004,6 @@ struct qlink_resp_get_hw_info { __le32 bld_tmstamp; __le32 plat_id; __le32 hw_ver; - __le16 ql_proto_ver; u8 num_mac; u8 mac_bitmap; u8 total_tx_chain; From 310cd5dd50702d5668ca97fd8755374aeb3c52ef Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:46 +0000 Subject: [PATCH 005/168] qtnfmac: pass hardware capabilities in TLV element To support any number of capabilities bits in the future, replace u32 capabilities bitmask by array. Pass capabilities from firmware using TLV element. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/cfg80211.c | 20 ++++----- .../net/wireless/quantenna/qtnfmac/commands.c | 19 ++++---- drivers/net/wireless/quantenna/qtnfmac/core.c | 9 ++-- drivers/net/wireless/quantenna/qtnfmac/core.h | 10 ++++- .../net/wireless/quantenna/qtnfmac/qlink.h | 45 ++++++++++++------- 5 files changed, 63 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 8849faa5bc10..bc7ed8f4a813 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -248,7 +248,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, goto error_del_vif; } - if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { + if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) { ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); if (ret) { unregister_netdevice(vif->netdev); @@ -1080,10 +1080,10 @@ struct wiphy *qtnf_wiphy_allocate(struct qtnf_bus *bus) struct wiphy *wiphy; if (qtnf_dfs_offload_get() && - (bus->hw_info.hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) + qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD)) qtn_cfg80211_ops.start_radar_detection = NULL; - if (!(bus->hw_info.hw_capab & QLINK_HW_CAPAB_PWR_MGMT)) + if (!qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_PWR_MGMT)) qtn_cfg80211_ops.set_power_mgmt = NULL; wiphy = wiphy_new(&qtn_cfg80211_ops, sizeof(struct qtnf_wmac)); @@ -1166,10 +1166,10 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; if (qtnf_dfs_offload_get() && - (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD)) + qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_DFS_OFFLOAD)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD); - if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_DWELL) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_DWELL)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); @@ -1185,16 +1185,16 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) ether_addr_copy(wiphy->perm_addr, mac->macaddr); - if (hw_info->hw_capab & QLINK_HW_CAPAB_STA_INACT_TIMEOUT) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_STA_INACT_TIMEOUT)) wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; - if (hw_info->hw_capab & QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR)) wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; - if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN)) + if (!qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_OBSS_SCAN)) wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; - if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE) + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_SAE)) wiphy->features |= NL80211_FEATURE_SAE; #ifdef CONFIG_PM @@ -1205,7 +1205,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) regdomain_is_known = isalpha(mac->rd->alpha2[0]) && isalpha(mac->rd->alpha2[1]); - if (hw_info->hw_capab & QLINK_HW_CAPAB_REG_UPDATE) { + if (qtnf_hwcap_is_set(hw_info, QLINK_HW_CAPAB_REG_UPDATE)) { wiphy->reg_notifier = qtnf_cfg80211_reg_notifier; if (mac->rd->alpha2[0] == '9' && mac->rd->alpha2[1] == '9') { diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 4f52e2fd7f38..4d494732b2d2 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -599,7 +599,7 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, tlv_len = le16_to_cpu(tlv->len); switch (le16_to_cpu(tlv->type)) { - case QTN_TLV_ID_STA_STATS_MAP: + case QTN_TLV_ID_BITMAP: map_len = tlv_len; map = tlv->val; break; @@ -895,14 +895,13 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, const char *uboot_ver = NULL; u32 hw_ver = 0; u16 tlv_type; - u16 tlv_value_len; + u16 tlv_len; hwinfo->num_mac = resp->num_mac; hwinfo->mac_bitmap = resp->mac_bitmap; hwinfo->fw_ver = le32_to_cpu(resp->fw_ver); hwinfo->total_tx_chain = resp->total_tx_chain; hwinfo->total_rx_chain = resp->total_rx_chain; - hwinfo->hw_capab = le32_to_cpu(resp->hw_capab); bld_tmstamp = le32_to_cpu(resp->bld_tmstamp); plat_id = le32_to_cpu(resp->plat_id); @@ -912,11 +911,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, while (info_len >= sizeof(*tlv)) { tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); + tlv_len = le16_to_cpu(tlv->len); - if (tlv_value_len + sizeof(*tlv) > info_len) { + if (tlv_len + sizeof(*tlv) > info_len) { pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); + tlv_type, tlv_len); return -EINVAL; } @@ -945,12 +944,16 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, case QTN_TLV_ID_MAX_SCAN_SSIDS: hwinfo->max_scan_ssids = *tlv->val; break; + case QTN_TLV_ID_BITMAP: + memcpy(hwinfo->hw_capab, tlv->val, + min(sizeof(hwinfo->hw_capab), (size_t)tlv_len)); + break; default: break; } - info_len -= tlv_value_len + sizeof(*tlv); - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); + info_len -= tlv_len + sizeof(*tlv); + tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_len); } pr_info("\nBuild name: %s\n" diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index a21b09afd103..853429de57c9 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -497,7 +497,7 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif, dev->tx_queue_len = 100; dev->ethtool_ops = &qtnf_ethtool_ops; - if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) + if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info); qdev_vif = netdev_priv(dev); @@ -639,7 +639,7 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) goto error_del_vif; } - if (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) { + if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) { ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); if (ret) goto error; @@ -705,7 +705,8 @@ static int qtnf_core_netdevice_event(struct notifier_block *nb, info->linking ? "add" : "del"); if (IS_ENABLED(CONFIG_NET_SWITCHDEV) && - (bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)) { + qtnf_hwcap_is_set(&bus->hw_info, + QLINK_HW_CAPAB_HW_BRIDGE)) { if (info->linking) br_domain = brdev->ifindex; else @@ -772,7 +773,7 @@ int qtnf_core_attach(struct qtnf_bus *bus) goto error; } - if ((bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) && + if (qtnf_hwcap_is_set(&bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE) && bus->bus_ops->data_tx_use_meta_set) bus->bus_ops->data_tx_use_meta_set(bus, true); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 78fee516cea4..cdefe24c2f27 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -23,6 +23,7 @@ #include "qlink.h" #include "trans.h" +#include "qlink_util.h" #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__ @@ -121,12 +122,12 @@ struct qtnf_hw_info { u8 num_mac; u8 mac_bitmap; u32 fw_ver; - u32 hw_capab; u8 total_tx_chain; u8 total_rx_chain; char fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; u8 max_scan_ssids; + u8 hw_capab[QLINK_HW_CAPAB_NUM / BITS_PER_BYTE + 1]; }; struct qtnf_vif *qtnf_mac_get_free_vif(struct qtnf_wmac *mac); @@ -160,4 +161,11 @@ static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev) return *((void **)netdev_priv(dev)); } +static inline bool qtnf_hwcap_is_set(const struct qtnf_hw_info *info, + unsigned int bit) +{ + return qtnf_utils_is_bit_set(info->hw_capab, bit, + sizeof(info->hw_capab)); +} + #endif /* _QTN_FMAC_CORE_H_ */ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 3722e707232c..20b9e90e377c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -73,15 +73,24 @@ struct qlink_msg_header { * @QLINK_HW_CAPAB_HW_BRIDGE: device has hardware switch capabilities. */ enum qlink_hw_capab { - QLINK_HW_CAPAB_REG_UPDATE = BIT(0), - QLINK_HW_CAPAB_STA_INACT_TIMEOUT = BIT(1), - QLINK_HW_CAPAB_DFS_OFFLOAD = BIT(2), - QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR = BIT(3), - QLINK_HW_CAPAB_PWR_MGMT = BIT(4), - QLINK_HW_CAPAB_OBSS_SCAN = BIT(5), - QLINK_HW_CAPAB_SCAN_DWELL = BIT(6), - QLINK_HW_CAPAB_SAE = BIT(8), - QLINK_HW_CAPAB_HW_BRIDGE = BIT(9), + QLINK_HW_CAPAB_REG_UPDATE = 0, + QLINK_HW_CAPAB_STA_INACT_TIMEOUT, + QLINK_HW_CAPAB_DFS_OFFLOAD, + QLINK_HW_CAPAB_SCAN_RANDOM_MAC_ADDR, + QLINK_HW_CAPAB_PWR_MGMT, + QLINK_HW_CAPAB_OBSS_SCAN, + QLINK_HW_CAPAB_SCAN_DWELL, + QLINK_HW_CAPAB_SAE, + QLINK_HW_CAPAB_HW_BRIDGE, + QLINK_HW_CAPAB_NUM +}; + +/** + * enum qlink_driver_capab - host driver capabilities. + * + */ +enum qlink_driver_capab { + QLINK_DRV_CAPAB_NUM = 0 }; enum qlink_iface_type { @@ -990,7 +999,6 @@ struct qlink_resp_get_mac_info { * Description of wireless hardware capabilities and features. * * @fw_ver: wireless hardware firmware version. - * @hw_capab: Bitmap of capabilities supported by firmware. * @num_mac: Number of separate physical radio devices provided by hardware. * @mac_bitmap: Bitmap of MAC IDs that are active and can be used in firmware. * @total_tx_chains: total number of transmit chains used by device. @@ -1000,7 +1008,6 @@ struct qlink_resp_get_mac_info { struct qlink_resp_get_hw_info { struct qlink_resp rhdr; __le32 fw_ver; - __le32 hw_capab; __le32 bld_tmstamp; __le32 plat_id; __le32 hw_ver; @@ -1337,11 +1344,15 @@ struct qlink_event_mic_failure { /** * enum qlink_tlv_id - list of TLVs that Qlink messages can carry * - * @QTN_TLV_ID_STA_STATS_MAP: a bitmap of &enum qlink_sta_info, used to - * indicate which statistic carried in QTN_TLV_ID_STA_STATS is valid. + * @QTN_TLV_ID_BITMAP: a data representing a bitmap that is used together with + * other TLVs: + * &enum qlink_sta_info used to indicate which statistic carried in + * QTN_TLV_ID_STA_STATS is valid. + * &enum qlink_hw_capab listing wireless card capabilities. + * &enum qlink_driver_capab listing driver/host system capabilities. * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * &struct qlink_sta_stats. Valid values are marked as such in a bitmap - * carried by QTN_TLV_ID_STA_STATS_MAP. + * carried by QTN_TLV_ID_BITMAP. * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan * for in any given scan. * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active @@ -1361,7 +1372,7 @@ enum qlink_tlv_id { QTN_TLV_ID_REG_RULE = 0x0207, QTN_TLV_ID_CHANNEL = 0x020F, QTN_TLV_ID_CHANDEF = 0x0210, - QTN_TLV_ID_STA_STATS_MAP = 0x0211, + QTN_TLV_ID_BITMAP = 0x0211, QTN_TLV_ID_STA_STATS = 0x0212, QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_IFACE_LIMIT = 0x0214, @@ -1596,7 +1607,7 @@ struct qlink_chan_stats { * * Used to indicate which statistics values in &struct qlink_sta_stats * are valid. Individual values are used to fill a bitmap carried in a - * payload of QTN_TLV_ID_STA_STATS_MAP. + * payload of QTN_TLV_ID_BITMAP. * * @QLINK_STA_INFO_CONNECTED_TIME: connected_time value is valid. * @QLINK_STA_INFO_INACTIVE_TIME: inactive_time value is valid. @@ -1660,7 +1671,7 @@ struct qlink_sta_info_rate { * Carries statistics of a STA. Not all fields may be filled with * valid values. Valid fields should be indicated as such using a bitmap of * &enum qlink_sta_info. Bitmap is carried separately in a payload of - * QTN_TLV_ID_STA_STATS_MAP. + * QTN_TLV_ID_BITMAP. */ struct qlink_sta_stats { __le64 rx_bytes; From e70cf22bc7b2ba9eccc501ce37775ac4051809c9 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:47 +0000 Subject: [PATCH 006/168] qtnfmac: merge PHY_PARAMS_GET into MAC_INFO QLINK_CMD_PHY_PARAMS_GET command does not need to be separate, it can be included into GET_MAC_INFO command. Merge these two commands adding all the missing wiphy data. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 102 ++---------------- drivers/net/wireless/quantenna/qtnfmac/core.c | 18 ++-- drivers/net/wireless/quantenna/qtnfmac/core.h | 3 +- .../net/wireless/quantenna/qtnfmac/qlink.h | 64 ++++++----- 4 files changed, 49 insertions(+), 138 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 4d494732b2d2..ca7d59a0a848 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1291,7 +1291,12 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, mac_info->radar_detect_widths = qlink_chan_width_mask_to_nl(le16_to_cpu( resp_info->radar_detect_widths)); - mac_info->max_acl_mac_addrs = le32_to_cpu(resp_info->max_acl_mac_addrs); + mac_info->max_acl_mac_addrs = le16_to_cpu(resp_info->max_acl_mac_addrs); + mac_info->frag_thr = le32_to_cpu(resp_info->frag_threshold); + mac_info->rts_thr = le32_to_cpu(resp_info->rts_threshold); + mac_info->sretry_limit = resp_info->retry_short; + mac_info->lretry_limit = resp_info->retry_long; + mac_info->coverage_class = resp_info->coverage_class; memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask, sizeof(mac_info->ht_cap_mod_mask)); @@ -1576,72 +1581,6 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, return ret; } -static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac, - const u8 *payload, size_t payload_len) -{ - struct qtnf_mac_info *mac_info; - struct qlink_tlv_frag_rts_thr *phy_thr; - struct qlink_tlv_rlimit *limit; - struct qlink_tlv_cclass *class; - u16 tlv_type; - u16 tlv_value_len; - size_t tlv_full_len; - const struct qlink_tlv_hdr *tlv; - - mac_info = &mac->macinfo; - - tlv = (struct qlink_tlv_hdr *)payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) { - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", - mac->macid, tlv_type, tlv_value_len); - return -EINVAL; - } - - switch (tlv_type) { - case QTN_TLV_ID_FRAG_THRESH: - phy_thr = (void *)tlv; - mac_info->frag_thr = le32_to_cpu(phy_thr->thr); - break; - case QTN_TLV_ID_RTS_THRESH: - phy_thr = (void *)tlv; - mac_info->rts_thr = le32_to_cpu(phy_thr->thr); - break; - case QTN_TLV_ID_SRETRY_LIMIT: - limit = (void *)tlv; - mac_info->sretry_limit = limit->rlimit; - break; - case QTN_TLV_ID_LRETRY_LIMIT: - limit = (void *)tlv; - mac_info->lretry_limit = limit->rlimit; - break; - case QTN_TLV_ID_COVERAGE_CLASS: - class = (void *)tlv; - mac_info->coverage_class = class->cclass; - break; - default: - pr_err("MAC%u: Unknown TLV type: %#x\n", mac->macid, - le16_to_cpu(tlv->type)); - break; - } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); - } - - if (payload_len) { - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", - mac->macid, payload_len); - return -EINVAL; - } - - return 0; -} - static int qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats, const u8 *payload, size_t payload_len) @@ -1799,35 +1738,6 @@ int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, return ret; } -int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac) -{ - struct sk_buff *cmd_skb, *resp_skb = NULL; - struct qlink_resp_phy_params *resp; - size_t response_size = 0; - int ret = 0; - - cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, - QLINK_CMD_PHY_PARAMS_GET, - sizeof(struct qlink_cmd)); - if (!cmd_skb) - return -ENOMEM; - - qtnf_bus_lock(mac->bus); - ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, - sizeof(*resp), &response_size); - if (ret) - goto out; - - resp = (struct qlink_resp_phy_params *)resp_skb->data; - ret = qtnf_cmd_resp_proc_phy_params(mac, resp->info, response_size); - -out: - qtnf_bus_unlock(mac->bus); - consume_skb(resp_skb); - - return ret; -} - int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) { struct wiphy *wiphy = priv_to_wiphy(mac); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 853429de57c9..74c9aa297ec9 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -585,16 +585,6 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) return PTR_ERR(mac); } - ret = qtnf_cmd_get_mac_info(mac); - if (ret) { - pr_err("MAC%u: failed to get info\n", macid); - goto error; - } - - /* Use MAC address of the first active radio as a unique device ID */ - if (is_zero_ether_addr(mac->bus->hw_id)) - ether_addr_copy(mac->bus->hw_id, mac->macaddr); - vif = qtnf_mac_get_base_vif(mac); if (!vif) { pr_err("MAC%u: primary VIF is not ready\n", macid); @@ -609,12 +599,16 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) goto error; } - ret = qtnf_cmd_send_get_phy_params(mac); + ret = qtnf_cmd_get_mac_info(mac); if (ret) { - pr_err("MAC%u: failed to get PHY settings\n", macid); + pr_err("MAC%u: failed to get MAC info\n", macid); goto error_del_vif; } + /* Use MAC address of the first active radio as a unique device ID */ + if (is_zero_ether_addr(mac->bus->hw_id)) + ether_addr_copy(mac->bus->hw_id, mac->macaddr); + ret = qtnf_mac_init_bands(mac); if (ret) { pr_err("MAC%u: failed to init bands\n", macid); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index cdefe24c2f27..d7491e965691 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -84,7 +84,7 @@ struct qtnf_mac_info { u8 sretry_limit; u8 coverage_class; u8 radar_detect_widths; - u32 max_acl_mac_addrs; + u16 max_acl_mac_addrs; struct ieee80211_ht_cap ht_cap_mod_mask; struct ieee80211_vht_cap vht_cap_mod_mask; struct ieee80211_iface_combination *if_comb; @@ -141,7 +141,6 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *priv, const char *name, unsigned char name_assign_type); void qtnf_main_work_queue(struct work_struct *work); int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed); -int qtnf_cmd_send_get_phy_params(struct qtnf_wmac *mac); struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid); struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb); diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 20b9e90e377c..9838ea6b212a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -289,7 +289,6 @@ enum qlink_cmd_type { QLINK_CMD_REGISTER_MGMT = 0x0003, QLINK_CMD_SEND_FRAME = 0x0004, QLINK_CMD_MGMT_SET_APPIE = 0x0005, - QLINK_CMD_PHY_PARAMS_GET = 0x0011, QLINK_CMD_PHY_PARAMS_SET = 0x0012, QLINK_CMD_GET_HW_INFO = 0x0013, QLINK_CMD_MAC_INFO = 0x0014, @@ -982,14 +981,48 @@ struct qlink_resp_get_mac_info { u8 num_rx_chain; struct ieee80211_vht_cap vht_cap_mod_mask; struct ieee80211_ht_cap ht_cap_mod_mask; + __le16 max_ap_assoc_sta; + __le32 hw_version; + __le32 probe_resp_offload; + __le32 bss_select_support; + __le16 n_addresses; __le16 radar_detect_widths; - __le32 max_acl_mac_addrs; + __le16 max_remain_on_channel_duration; + __le16 max_acl_mac_addrs; + + __le32 frag_threshold; + __le32 rts_threshold; + u8 retry_short; + u8 retry_long; + u8 coverage_class; + + u8 max_scan_ssids; + u8 max_sched_scan_reqs; + u8 max_sched_scan_ssids; + u8 max_match_sets; + u8 max_adj_channel_rssi_comp; + + __le16 max_scan_ie_len; + __le16 max_sched_scan_ie_len; + __le32 max_sched_scan_plans; + __le32 max_sched_scan_plan_interval; + __le32 max_sched_scan_plan_iterations; + + u8 n_cipher_suites; + u8 n_akm_suites; + u8 max_num_pmkids; + u8 num_iftype_ext_capab; + u8 extended_capabilities_len; + u8 max_data_retry_count; + u8 n_iface_combinations; + u8 max_num_csa_counters; + u8 bands_cap; u8 alpha2[2]; u8 n_reg_rules; u8 dfs_region; - u8 rsvd[1]; + u8 rsvd[3]; u8 var_info[0]; } __packed; @@ -1073,16 +1106,6 @@ struct qlink_resp_band_info_get { u8 info[0]; } __packed; -/** - * struct qlink_resp_phy_params - response for QLINK_CMD_PHY_PARAMS_GET command - * - * @info: variable-length array of PHY params. - */ -struct qlink_resp_phy_params { - struct qlink_resp rhdr; - u8 info[0]; -} __packed; - /** * struct qlink_resp_get_chan_stats - response for QLINK_CMD_CHAN_STATS cmd * @@ -1425,21 +1448,6 @@ struct qlink_iface_limit_record { #define QLINK_RSSI_OFFSET 120 -struct qlink_tlv_frag_rts_thr { - struct qlink_tlv_hdr hdr; - __le32 thr; -} __packed; - -struct qlink_tlv_rlimit { - struct qlink_tlv_hdr hdr; - u8 rlimit; -} __packed; - -struct qlink_tlv_cclass { - struct qlink_tlv_hdr hdr; - u8 cclass; -} __packed; - /** * enum qlink_reg_rule_flags - regulatory rule flags * From bc5db734c1c4d4618811d99a72f6e91a0daedad8 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:49 +0000 Subject: [PATCH 007/168] qtnfmac: drop QTN_TLV_ID_NUM_IFACE_COMB TLV type Information about interface combinations is now available in a fixed portion of struct qlink_resp_get_mac_info. Use that information to get interface combinations. TLV type QTN_TLV_ID_NUM_IFACE_COMB is not needed anymore and can be dropped. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 48 +++++++------------ .../net/wireless/quantenna/qtnfmac/qlink.h | 5 -- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index ca7d59a0a848..1cba0182a5b8 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1023,10 +1023,9 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, size_t tlv_buf_size) { const u8 *tlv_buf = resp->var_info; - struct ieee80211_iface_combination *comb = NULL; + struct ieee80211_iface_combination *comb = mac->macinfo.if_comb; size_t n_comb = 0; struct ieee80211_iface_limit *limits; - const struct qlink_iface_comb_num *comb_num; const struct qlink_iface_limit_record *rec; const struct qlink_iface_limit *lim; const struct qlink_wowlan_capab_data *wowlan; @@ -1084,32 +1083,6 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, } switch (tlv_type) { - case QTN_TLV_ID_NUM_IFACE_COMB: - if (tlv_value_len != sizeof(*comb_num)) - return -EINVAL; - - comb_num = (void *)tlv->val; - - /* free earlier iface comb memory */ - qtnf_mac_iface_comb_free(mac); - - mac->macinfo.n_if_comb = - le32_to_cpu(comb_num->iface_comb_num); - - mac->macinfo.if_comb = - kcalloc(mac->macinfo.n_if_comb, - sizeof(*mac->macinfo.if_comb), - GFP_KERNEL); - - if (!mac->macinfo.if_comb) - return -ENOMEM; - - comb = mac->macinfo.if_comb; - - pr_debug("MAC%u: %zu iface combinations\n", - mac->macid, mac->macinfo.n_if_comb); - - break; case QTN_TLV_ID_IFACE_LIMIT: if (unlikely(!comb)) { pr_warn("MAC%u: no combinations advertised\n", @@ -1266,13 +1239,15 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, return 0; } -static void +static int qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, const struct qlink_resp_get_mac_info *resp_info) { struct qtnf_mac_info *mac_info; struct qtnf_vif *vif; + qtnf_mac_iface_comb_free(mac); + mac_info = &mac->macinfo; mac_info->bands_cap = resp_info->bands_cap; @@ -1302,6 +1277,16 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, sizeof(mac_info->ht_cap_mod_mask)); memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask, sizeof(mac_info->vht_cap_mod_mask)); + + mac_info->n_if_comb = resp_info->n_iface_combinations; + mac_info->if_comb = kcalloc(mac->macinfo.n_if_comb, + sizeof(*mac->macinfo.if_comb), + GFP_KERNEL); + + if (!mac->macinfo.if_comb) + return -ENOMEM; + + return 0; } static void qtnf_cmd_resp_band_fill_htcap(const u8 *info, @@ -1657,7 +1642,10 @@ int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) goto out; resp = (const struct qlink_resp_get_mac_info *)resp_skb->data; - qtnf_cmd_resp_proc_mac_info(mac, resp); + ret = qtnf_cmd_resp_proc_mac_info(mac, resp); + if (ret) + goto out; + ret = qtnf_parse_variable_mac_info(mac, resp, var_data_len); out: diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 9838ea6b212a..8966fb68a61a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -1399,7 +1399,6 @@ enum qlink_tlv_id { QTN_TLV_ID_STA_STATS = 0x0212, QTN_TLV_ID_COVERAGE_CLASS = 0x0213, QTN_TLV_ID_IFACE_LIMIT = 0x0214, - QTN_TLV_ID_NUM_IFACE_COMB = 0x0215, QTN_TLV_ID_CHANNEL_STATS = 0x0216, QTN_TLV_ID_KEY = 0x0302, QTN_TLV_ID_SEQ = 0x0303, @@ -1430,10 +1429,6 @@ struct qlink_tlv_hdr { u8 val[0]; } __packed; -struct qlink_iface_comb_num { - __le32 iface_comb_num; -} __packed; - struct qlink_iface_limit { __le16 max_num; __le16 type; From 601ce21ff88d00f09b92bdc9be4d1a0c4c80735a Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:50 +0000 Subject: [PATCH 008/168] qtnfmac: implement extendable channel survey dump Switch to extendable implementation of channel survey dump to make sure that any new channel statistics can be added in the future without any backwards compatibility issues. For this purpose use a separate variable length bitmap to pass the list of valid statistics in firmware response. Besides, switch to using channel frequency instead of IEEE channel number to prepare for adding support of 6GHz band. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/cfg80211.c | 42 +---- .../net/wireless/quantenna/qtnfmac/commands.c | 174 +++++++++++------- .../net/wireless/quantenna/qtnfmac/commands.h | 4 +- drivers/net/wireless/quantenna/qtnfmac/core.h | 9 - .../net/wireless/quantenna/qtnfmac/qlink.h | 66 ++++++- 5 files changed, 173 insertions(+), 122 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index bc7ed8f4a813..a53ffe04a903 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -739,7 +739,6 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_supported_band *sband; const struct cfg80211_chan_def *chandef = &wdev->chandef; struct ieee80211_channel *chan; - struct qtnf_chan_stats stats; int ret; sband = wiphy->bands[NL80211_BAND_2GHZ]; @@ -755,49 +754,16 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; chan = &sband->channels[idx]; - memset(&stats, 0, sizeof(stats)); - survey->channel = chan; survey->filled = 0x0; - if (chandef->chan) { - if (chan->hw_value == chandef->chan->hw_value) - survey->filled = SURVEY_INFO_IN_USE; - } + if (chan == chandef->chan) + survey->filled = SURVEY_INFO_IN_USE; - ret = qtnf_cmd_get_chan_stats(mac, chan->hw_value, &stats); - switch (ret) { - case 0: - if (unlikely(stats.chan_num != chan->hw_value)) { - pr_err("received stats for channel %d instead of %d\n", - stats.chan_num, chan->hw_value); - ret = -EINVAL; - break; - } - - survey->filled |= SURVEY_INFO_TIME | - SURVEY_INFO_TIME_SCAN | - SURVEY_INFO_TIME_BUSY | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_TX | - SURVEY_INFO_NOISE_DBM; - - survey->time_scan = stats.cca_try; - survey->time = stats.cca_try; - survey->time_tx = stats.cca_tx; - survey->time_rx = stats.cca_rx; - survey->time_busy = stats.cca_busy; - survey->noise = stats.chan_noise; - break; - case -ENOENT: - pr_debug("no stats for channel %u\n", chan->hw_value); - ret = 0; - break; - default: + ret = qtnf_cmd_get_chan_stats(mac, chan->center_freq, survey); + if (ret) pr_debug("failed to get chan(%d) stats from card\n", chan->hw_value); - break; - } return ret; } diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 1cba0182a5b8..6a13b29bf814 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1566,62 +1566,6 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, return ret; } -static int -qtnf_cmd_resp_proc_chan_stat_info(struct qtnf_chan_stats *stats, - const u8 *payload, size_t payload_len) -{ - struct qlink_chan_stats *qlink_stats; - const struct qlink_tlv_hdr *tlv; - size_t tlv_full_len; - u16 tlv_value_len; - u16 tlv_type; - - tlv = (struct qlink_tlv_hdr *)payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > payload_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -EINVAL; - } - switch (tlv_type) { - case QTN_TLV_ID_CHANNEL_STATS: - if (unlikely(tlv_value_len != sizeof(*qlink_stats))) { - pr_err("invalid CHANNEL_STATS entry size\n"); - return -EINVAL; - } - - qlink_stats = (void *)tlv->val; - - stats->chan_num = le32_to_cpu(qlink_stats->chan_num); - stats->cca_tx = le32_to_cpu(qlink_stats->cca_tx); - stats->cca_rx = le32_to_cpu(qlink_stats->cca_rx); - stats->cca_busy = le32_to_cpu(qlink_stats->cca_busy); - stats->cca_try = le32_to_cpu(qlink_stats->cca_try); - stats->chan_noise = qlink_stats->chan_noise; - - pr_debug("chan(%u) try(%u) busy(%u) noise(%d)\n", - stats->chan_num, stats->cca_try, - stats->cca_busy, stats->chan_noise); - break; - default: - pr_warn("Unknown TLV type: %#x\n", - le16_to_cpu(tlv->type)); - } - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); - } - - if (payload_len) { - pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len); - return -EINVAL; - } - - return 0; -} - int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac) { struct sk_buff *cmd_skb, *resp_skb = NULL; @@ -2468,8 +2412,104 @@ int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, return ret; } -int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, - struct qtnf_chan_stats *stats) +static int +qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey, + const u8 *payload, size_t payload_len) +{ + const struct qlink_chan_stats *stats = NULL; + const struct qlink_tlv_hdr *tlv; + size_t tlv_full_len; + u16 tlv_value_len; + u16 tlv_type; + const u8 *map = NULL; + unsigned int map_len = 0; + unsigned int stats_len = 0; + + tlv = (struct qlink_tlv_hdr *)payload; + + while (payload_len >= sizeof(*tlv)) { + tlv_type = le16_to_cpu(tlv->type); + tlv_value_len = le16_to_cpu(tlv->len); + tlv_full_len = tlv_value_len + sizeof(*tlv); + + if (tlv_full_len > payload_len) { + pr_warn("malformed TLV 0x%.2X; LEN: %u\n", + tlv_type, tlv_value_len); + return -ENOSPC; + } + + switch (tlv_type) { + case QTN_TLV_ID_BITMAP: + map = tlv->val; + map_len = tlv_value_len; + break; + case QTN_TLV_ID_CHANNEL_STATS: + stats = (struct qlink_chan_stats *)tlv->val; + stats_len = tlv_value_len; + break; + default: + pr_info("Unknown TLV type: %#x\n", tlv_type); + break; + } + + payload_len -= tlv_full_len; + tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); + } + + if (payload_len) { + pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len); + return -EINVAL; + } + + if (!map || !stats) + return 0; + +#define qtnf_chan_stat_avail(stat_name, bitn) \ + (qtnf_utils_is_bit_set(map, bitn, map_len) && \ + (offsetofend(struct qlink_chan_stats, stat_name) <= stats_len)) + + if (qtnf_chan_stat_avail(time_on, QLINK_CHAN_STAT_TIME_ON)) { + survey->filled |= SURVEY_INFO_TIME; + survey->time = le64_to_cpu(stats->time_on); + } + + if (qtnf_chan_stat_avail(time_tx, QLINK_CHAN_STAT_TIME_TX)) { + survey->filled |= SURVEY_INFO_TIME_TX; + survey->time_tx = le64_to_cpu(stats->time_tx); + } + + if (qtnf_chan_stat_avail(time_rx, QLINK_CHAN_STAT_TIME_RX)) { + survey->filled |= SURVEY_INFO_TIME_RX; + survey->time_rx = le64_to_cpu(stats->time_rx); + } + + if (qtnf_chan_stat_avail(cca_busy, QLINK_CHAN_STAT_CCA_BUSY)) { + survey->filled |= SURVEY_INFO_TIME_BUSY; + survey->time_busy = le64_to_cpu(stats->cca_busy); + } + + if (qtnf_chan_stat_avail(cca_busy_ext, QLINK_CHAN_STAT_CCA_BUSY_EXT)) { + survey->filled |= SURVEY_INFO_TIME_EXT_BUSY; + survey->time_ext_busy = le64_to_cpu(stats->cca_busy_ext); + } + + if (qtnf_chan_stat_avail(time_scan, QLINK_CHAN_STAT_TIME_SCAN)) { + survey->filled |= SURVEY_INFO_TIME_SCAN; + survey->time_scan = le64_to_cpu(stats->time_scan); + } + + if (qtnf_chan_stat_avail(chan_noise, QLINK_CHAN_STAT_CHAN_NOISE)) { + survey->filled |= SURVEY_INFO_NOISE_DBM; + survey->noise = stats->chan_noise; + } + +#undef qtnf_chan_stat_avail + + return 0; +} + +int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq, + struct survey_info *survey) { struct sk_buff *cmd_skb, *resp_skb = NULL; struct qlink_cmd_get_chan_stats *cmd; @@ -2483,22 +2523,30 @@ int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); - cmd = (struct qlink_cmd_get_chan_stats *)cmd_skb->data; - cmd->channel = cpu_to_le16(channel); + cmd->channel_freq = cpu_to_le32(chan_freq); + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send_with_reply(mac->bus, cmd_skb, &resp_skb, sizeof(*resp), &var_data_len); + qtnf_bus_unlock(mac->bus); + if (ret) goto out; resp = (struct qlink_resp_get_chan_stats *)resp_skb->data; - ret = qtnf_cmd_resp_proc_chan_stat_info(stats, resp->info, + + if (le32_to_cpu(resp->chan_freq) != chan_freq) { + pr_err("[MAC%u] channel stats freq %u != requested %u\n", + mac->macid, le32_to_cpu(resp->chan_freq), chan_freq); + ret = -EINVAL; + goto out; + } + + ret = qtnf_cmd_resp_proc_chan_stat_info(survey, resp->info, var_data_len); out: - qtnf_bus_unlock(mac->bus); consume_skb(resp_skb); return ret; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index ab273257b078..9db695101d28 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -59,8 +59,8 @@ int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, bool up); int qtnf_cmd_reg_notify(struct qtnf_wmac *mac, struct regulatory_request *req, bool slave_radar, bool dfs_offload); -int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u16 channel, - struct qtnf_chan_stats *stats); +int qtnf_cmd_get_chan_stats(struct qtnf_wmac *mac, u32 chan_freq, + struct survey_info *survey); int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct cfg80211_csa_settings *params); int qtnf_cmd_get_channel(struct qtnf_vif *vif, struct cfg80211_chan_def *chdef); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index d7491e965691..6fe82179df7f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -95,15 +95,6 @@ struct qtnf_mac_info { struct wiphy_wowlan_support *wowlan; }; -struct qtnf_chan_stats { - u32 chan_num; - u32 cca_tx; - u32 cca_rx; - u32 cca_busy; - u32 cca_try; - s8 chan_noise; -}; - struct qtnf_wmac { u8 macid; u8 wiphy_registered; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 8966fb68a61a..38d3d60926ff 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -632,11 +632,11 @@ struct qlink_cmd_band_info_get { /** * struct qlink_cmd_get_chan_stats - data for QLINK_CMD_CHAN_STATS command * - * @channel: channel number according to 802.11 17.3.8.3.2 and Annex J + * @channel_freq: channel center frequency */ struct qlink_cmd_get_chan_stats { struct qlink_cmd chdr; - __le16 channel; + __le32 channel_freq; } __packed; /** @@ -1077,8 +1077,6 @@ enum qlink_sta_info_rate_flags { * * Response data containing statistics for specified STA. * - * @filled: a bitmask of &enum qlink_sta_info, specifies which info in response - * is valid. * @sta_addr: MAC address of STA the response carries statistic for. * @info: variable statistics for specified STA. */ @@ -1109,10 +1107,12 @@ struct qlink_resp_band_info_get { /** * struct qlink_resp_get_chan_stats - response for QLINK_CMD_CHAN_STATS cmd * + * @chan_freq: center frequency for a channel the report is sent for. * @info: variable-length channel info. */ struct qlink_resp_get_chan_stats { - struct qlink_cmd rhdr; + struct qlink_resp rhdr; + __le32 chan_freq; u8 info[0]; } __packed; @@ -1373,6 +1373,8 @@ struct qlink_event_mic_failure { * QTN_TLV_ID_STA_STATS is valid. * &enum qlink_hw_capab listing wireless card capabilities. * &enum qlink_driver_capab listing driver/host system capabilities. + * &enum qlink_chan_stat used to indicate which statistic carried in + * QTN_TLV_ID_CHANNEL_STATS is valid. * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * &struct qlink_sta_stats. Valid values are marked as such in a bitmap * carried by QTN_TLV_ID_BITMAP. @@ -1596,13 +1598,57 @@ struct qlink_tlv_iftype_data { struct qlink_sband_iftype_data iftype_data[0]; } __packed; +/** + * enum qlink_chan_stat - channel statistics bitmap + * + * Used to indicate which statistics values in &struct qlink_chan_stats + * are valid. Individual values are used to fill a bitmap carried in a + * payload of QTN_TLV_ID_BITMAP. + * + * @QLINK_CHAN_STAT_TIME_ON: time_on value is valid. + * @QLINK_CHAN_STAT_TIME_TX: time_tx value is valid. + * @QLINK_CHAN_STAT_TIME_RX: time_rx value is valid. + * @QLINK_CHAN_STAT_CCA_BUSY: cca_busy value is valid. + * @QLINK_CHAN_STAT_CCA_BUSY_EXT: cca_busy_ext value is valid. + * @QLINK_CHAN_STAT_TIME_SCAN: time_scan value is valid. + * @QLINK_CHAN_STAT_CHAN_NOISE: chan_noise value is valid. + */ +enum qlink_chan_stat { + QLINK_CHAN_STAT_TIME_ON, + QLINK_CHAN_STAT_TIME_TX, + QLINK_CHAN_STAT_TIME_RX, + QLINK_CHAN_STAT_CCA_BUSY, + QLINK_CHAN_STAT_CCA_BUSY_EXT, + QLINK_CHAN_STAT_TIME_SCAN, + QLINK_CHAN_STAT_CHAN_NOISE, + QLINK_CHAN_STAT_NUM, +}; + +/** + * struct qlink_chan_stats - data for QTN_TLV_ID_CHANNEL_STATS + * + * Carries a per-channel statistics. Not all fields may be filled with + * valid values. Valid fields should be indicated as such using a bitmap of + * &enum qlink_chan_stat. Bitmap is carried separately in a payload of + * QTN_TLV_ID_BITMAP. + * + * @time_on: amount of time radio operated on that channel. + * @time_tx: amount of time radio spent transmitting on the channel. + * @time_rx: amount of time radio spent receiving on the channel. + * @cca_busy: amount of time the the primary channel was busy. + * @cca_busy_ext: amount of time the the secondary channel was busy. + * @time_scan: amount of radio spent scanning on the channel. + * @chan_noise: channel noise. + */ struct qlink_chan_stats { - __le32 chan_num; - __le32 cca_tx; - __le32 cca_rx; - __le32 cca_busy; - __le32 cca_try; + __le64 time_on; + __le64 time_tx; + __le64 time_rx; + __le64 cca_busy; + __le64 cca_busy_ext; + __le64 time_scan; s8 chan_noise; + u8 rsvd[3]; } __packed; /** From 0d18a9c0a387652c51fd78e945ab47efd8afc220 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:52 +0000 Subject: [PATCH 009/168] qtnfmac: pass max scan SSIDs limit on per-radio basis Each radio on a given wifi device may have different max scan SSIDs limitation, so take this information from a per-radio info structure. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +- drivers/net/wireless/quantenna/qtnfmac/commands.c | 4 +--- drivers/net/wireless/quantenna/qtnfmac/core.h | 2 +- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 4 +--- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index a53ffe04a903..73d5014a4234 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -1108,7 +1108,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->coverage_class = macinfo->coverage_class; wiphy->max_scan_ssids = - (hw_info->max_scan_ssids) ? hw_info->max_scan_ssids : 1; + (macinfo->max_scan_ssids) ? macinfo->max_scan_ssids : 1; wiphy->max_scan_ie_len = QTNF_MAX_VSIE_LEN; wiphy->mgmt_stypes = qtnf_mgmt_stypes; wiphy->max_remain_on_channel_duration = 5000; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 6a13b29bf814..a4be2aa19997 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -941,9 +941,6 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, case QTN_TLV_ID_UBOOT_VER: uboot_ver = (const void *)tlv->val; break; - case QTN_TLV_ID_MAX_SCAN_SSIDS: - hwinfo->max_scan_ssids = *tlv->val; - break; case QTN_TLV_ID_BITMAP: memcpy(hwinfo->hw_capab, tlv->val, min(sizeof(hwinfo->hw_capab), (size_t)tlv_len)); @@ -1272,6 +1269,7 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, mac_info->sretry_limit = resp_info->retry_short; mac_info->lretry_limit = resp_info->retry_long; mac_info->coverage_class = resp_info->coverage_class; + mac_info->max_scan_ssids = resp_info->max_scan_ssids; memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask, sizeof(mac_info->ht_cap_mod_mask)); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 6fe82179df7f..b993f9ca14c5 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -84,6 +84,7 @@ struct qtnf_mac_info { u8 sretry_limit; u8 coverage_class; u8 radar_detect_widths; + u8 max_scan_ssids; u16 max_acl_mac_addrs; struct ieee80211_ht_cap ht_cap_mod_mask; struct ieee80211_vht_cap vht_cap_mod_mask; @@ -117,7 +118,6 @@ struct qtnf_hw_info { u8 total_rx_chain; char fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; - u8 max_scan_ssids; u8 hw_capab[QLINK_HW_CAPAB_NUM / BITS_PER_BYTE + 1]; }; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 38d3d60926ff..16acb10386ad 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -965,6 +965,7 @@ enum qlink_dfs_regions { * @num_rx_chain: Number of receive chains used by WMAC. * @vht_cap_mod_mask: mask specifying which VHT capabilities can be altered. * @ht_cap_mod_mask: mask specifying which HT capabilities can be altered. + * @max_scan_ssids: maximum number of SSIDs the device can scan for in any scan. * @bands_cap: wireless bands WMAC can operate in, bitmap of &enum qlink_band. * @max_ap_assoc_sta: Maximum number of associations supported by WMAC. * @radar_detect_widths: bitmask of channels BW for which WMAC can detect radar. @@ -1378,8 +1379,6 @@ struct qlink_event_mic_failure { * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * &struct qlink_sta_stats. Valid values are marked as such in a bitmap * carried by QTN_TLV_ID_BITMAP. - * @QTN_TLV_ID_MAX_SCAN_SSIDS: maximum number of SSIDs the device can scan - * for in any given scan. * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active * scan. * @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive @@ -1415,7 +1414,6 @@ enum qlink_tlv_id { QTN_TLV_ID_CALIBRATION_VER = 0x0406, QTN_TLV_ID_UBOOT_VER = 0x0407, QTN_TLV_ID_RANDOM_MAC_ADDR = 0x0408, - QTN_TLV_ID_MAX_SCAN_SSIDS = 0x0409, QTN_TLV_ID_WOWLAN_CAPAB = 0x0410, QTN_TLV_ID_WOWLAN_PATTERN = 0x0411, QTN_TLV_ID_SCAN_FLUSH = 0x0412, From 8b0b5f1ba9e02191aedb496abbfdae174c24c85b Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:53 +0000 Subject: [PATCH 010/168] qtnfmac: cleanup alignment in firmware communication protocol Make sure that all elements in QLINK protocol message are aligned to 4 bytes. For this purpose add necessary amount of padding bytes to each message. Besides, add padding for non-aligned variable length fields, e.g. SSID, so that the first byte of the next variable length element is aligned. to 4 bytes. Finally, introduce TLV parsing helpers to reduce boilerplate TLV parsing code. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 142 +++++++----------- .../net/wireless/quantenna/qtnfmac/event.c | 58 ++----- .../net/wireless/quantenna/qtnfmac/qlink.h | 29 +++- .../wireless/quantenna/qtnfmac/qlink_util.h | 37 ++--- 4 files changed, 104 insertions(+), 162 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index a4be2aa19997..1271d38e4c7a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -175,7 +175,8 @@ static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, { struct qlink_tlv_ie_set *tlv; - tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); + tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + + round_up(len, QLINK_ALIGN)); tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); tlv->type = frame_type; @@ -190,20 +191,24 @@ static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, { unsigned int len = sizeof(struct qlink_cmd_start_ap); - len += s->ssid_len; - len += s->beacon.head_len; - len += s->beacon.tail_len; - len += s->beacon.beacon_ies_len; - len += s->beacon.proberesp_ies_len; - len += s->beacon.assocresp_ies_len; - len += s->beacon.probe_resp_len; + len += round_up(s->ssid_len, QLINK_ALIGN); + len += round_up(s->beacon.head_len, QLINK_ALIGN); + len += round_up(s->beacon.tail_len, QLINK_ALIGN); + len += round_up(s->beacon.beacon_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.proberesp_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.assocresp_ies_len, QLINK_ALIGN); + len += round_up(s->beacon.probe_resp_len, QLINK_ALIGN); if (cfg80211_chandef_valid(&s->chandef)) len += sizeof(struct qlink_tlv_chandef); - if (s->acl) + if (s->acl) { + unsigned int acl_len = struct_size(s->acl, mac_addrs, + s->acl->n_acl_entries); + len += sizeof(struct qlink_tlv_hdr) + - struct_size(s->acl, mac_addrs, s->acl->n_acl_entries); + round_up(acl_len, QLINK_ALIGN); + } if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) { pr_err("VIF%u.%u: can not fit AP settings: %u\n", @@ -315,7 +320,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, if (s->ht_cap) { struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *) - skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap)); + skb_put(cmd_skb, sizeof(*tlv) + + round_up(sizeof(*s->ht_cap), QLINK_ALIGN)); tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); tlv->len = cpu_to_le16(sizeof(*s->ht_cap)); @@ -339,7 +345,8 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, size_t acl_size = struct_size(s->acl, mac_addrs, s->acl->n_acl_entries); struct qlink_tlv_hdr *tlv = - skb_put(cmd_skb, sizeof(*tlv) + acl_size); + skb_put(cmd_skb, + sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); tlv->len = cpu_to_le16(acl_size); @@ -581,10 +588,10 @@ qtnf_sta_info_parse_flags(struct nl80211_sta_flag_update *dst, } static void -qtnf_cmd_sta_info_parse(struct station_info *sinfo, - const struct qlink_tlv_hdr *tlv, +qtnf_cmd_sta_info_parse(struct station_info *sinfo, const u8 *data, size_t resp_size) { + const struct qlink_tlv_hdr *tlv; const struct qlink_sta_stats *stats = NULL; const u8 *map = NULL; unsigned int map_len = 0; @@ -595,7 +602,7 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, (qtnf_utils_is_bit_set(map, bitn, map_len) && \ (offsetofend(struct qlink_sta_stats, stat_name) <= stats_len)) - while (resp_size >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, data, resp_size) { tlv_len = le16_to_cpu(tlv->len); switch (le16_to_cpu(tlv->type)) { @@ -610,9 +617,11 @@ qtnf_cmd_sta_info_parse(struct station_info *sinfo, default: break; } + } - resp_size -= tlv_len + sizeof(*tlv); - tlv = (const struct qlink_tlv_hdr *)(tlv->val + tlv_len); + if (!qlink_tlv_parsing_ok(tlv, data, resp_size)) { + pr_err("Malformed TLV buffer\n"); + return; } if (!map || !stats) @@ -736,9 +745,7 @@ int qtnf_cmd_get_sta_info(struct qtnf_vif *vif, const u8 *sta_mac, goto out; } - qtnf_cmd_sta_info_parse(sinfo, - (const struct qlink_tlv_hdr *)resp->info, - var_resp_len); + qtnf_cmd_sta_info_parse(sinfo, resp->info, var_resp_len); out: qtnf_bus_unlock(vif->mac->bus); @@ -907,18 +914,10 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, plat_id = le32_to_cpu(resp->plat_id); hw_ver = le32_to_cpu(resp->hw_ver); - tlv = (const struct qlink_tlv_hdr *)resp->info; - - while (info_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, resp->info, info_len) { tlv_type = le16_to_cpu(tlv->type); tlv_len = le16_to_cpu(tlv->len); - if (tlv_len + sizeof(*tlv) > info_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_len); - return -EINVAL; - } - switch (tlv_type) { case QTN_TLV_ID_BUILD_NAME: bld_name = (const void *)tlv->val; @@ -948,9 +947,11 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, default: break; } + } - info_len -= tlv_len + sizeof(*tlv); - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_len); + if (!qlink_tlv_parsing_ok(tlv, resp->info, info_len)) { + pr_err("Malformed TLV buffer\n"); + return -EINVAL; } pr_info("\nBuild name: %s\n" @@ -1019,7 +1020,6 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, const struct qlink_resp_get_mac_info *resp, size_t tlv_buf_size) { - const u8 *tlv_buf = resp->var_info; struct ieee80211_iface_combination *comb = mac->macinfo.if_comb; size_t n_comb = 0; struct ieee80211_iface_limit *limits; @@ -1029,7 +1029,6 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, u16 rec_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; u8 *ext_capa = NULL; u8 *ext_capa_mask = NULL; @@ -1068,16 +1067,9 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, break; } - tlv = (const struct qlink_tlv_hdr *)tlv_buf; - while (tlv_buf_size >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, resp->var_info, tlv_buf_size) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > tlv_buf_size) { - pr_warn("MAC%u: malformed TLV 0x%.2X; LEN: %u\n", - mac->macid, tlv_type, tlv_value_len); - return -EINVAL; - } switch (tlv_type) { case QTN_TLV_ID_IFACE_LIMIT: @@ -1183,14 +1175,10 @@ qtnf_parse_variable_mac_info(struct qtnf_wmac *mac, mac->macid, tlv_type); break; } - - tlv_buf_size -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (tlv_buf_size) { - pr_warn("MAC%u: malformed TLV buf; bytes left: %zu\n", - mac->macid, tlv_buf_size); + if (!qlink_tlv_parsing_ok(tlv, resp->var_info, tlv_buf_size)) { + pr_err("Malformed TLV buffer\n"); return -EINVAL; } @@ -1383,7 +1371,6 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, size_t payload_len) { u16 tlv_type; - size_t tlv_len; size_t tlv_dlen; const struct qlink_tlv_hdr *tlv; const struct qlink_channel *qchan; @@ -1418,24 +1405,15 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, return -ENOMEM; } - tlv = (struct qlink_tlv_hdr *)resp->info; - - while (payload_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, resp->info, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_dlen = le16_to_cpu(tlv->len); - tlv_len = tlv_dlen + sizeof(*tlv); - - if (tlv_len > payload_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %zu\n", - tlv_type, tlv_len); - goto error_ret; - } switch (tlv_type) { case QTN_TLV_ID_CHANNEL: if (unlikely(tlv_dlen != sizeof(*qchan))) { pr_err("invalid channel TLV len %zu\n", - tlv_len); + tlv_dlen); goto error_ret; } @@ -1538,13 +1516,10 @@ qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, pr_warn("unknown TLV type: %#x\n", tlv_type); break; } - - payload_len -= tlv_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen); } - if (payload_len) { - pr_err("malformed TLV buf; bytes left: %zu\n", payload_len); + if (!qlink_tlv_parsing_ok(tlv, resp->info, payload_len)) { + pr_err("Malformed TLV buffer\n"); goto error_ret; } @@ -1689,16 +1664,16 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH, wiphy->rts_threshold); if (changed & WIPHY_PARAM_COVERAGE_CLASS) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, - wiphy->coverage_class); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, + wiphy->coverage_class); if (changed & WIPHY_PARAM_RETRY_LONG) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, - wiphy->retry_long); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, + wiphy->retry_long); if (changed & WIPHY_PARAM_RETRY_SHORT) - qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, - wiphy->retry_short); + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, + wiphy->retry_short); ret = qtnf_cmd_send(mac->bus, cmd_skb); if (ret) @@ -2054,13 +2029,13 @@ static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac, scan_req->duration_mandatory ? "mandatory" : "max", dwell_active, dwell_passive, duration); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SCAN_DWELL_ACTIVE, dwell_active); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SCAN_DWELL_PASSIVE, dwell_passive); - qtnf_cmd_skb_put_tlv_u16(cmd_skb, + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_SCAN_SAMPLE_DURATION, duration); } @@ -2416,25 +2391,15 @@ qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey, { const struct qlink_chan_stats *stats = NULL; const struct qlink_tlv_hdr *tlv; - size_t tlv_full_len; u16 tlv_value_len; u16 tlv_type; const u8 *map = NULL; unsigned int map_len = 0; unsigned int stats_len = 0; - tlv = (struct qlink_tlv_hdr *)payload; - - while (payload_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, payload, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(*tlv); - - if (tlv_full_len > payload_len) { - pr_warn("malformed TLV 0x%.2X; LEN: %u\n", - tlv_type, tlv_value_len); - return -ENOSPC; - } switch (tlv_type) { case QTN_TLV_ID_BITMAP: @@ -2449,13 +2414,10 @@ qtnf_cmd_resp_proc_chan_stat_info(struct survey_info *survey, pr_info("Unknown TLV type: %#x\n", tlv_type); break; } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) { - pr_warn("malformed TLV buf; bytes left: %zu\n", payload_len); + if (!qlink_tlv_parsing_ok(tlv, payload, payload_len)) { + pr_err("Malformed TLV buffer\n"); return -EINVAL; } @@ -2657,7 +2619,7 @@ int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif, if (!cmd_skb) return -ENOMEM; - tlv = skb_put(cmd_skb, sizeof(*tlv) + acl_size); + tlv = skb_put(cmd_skb, sizeof(*tlv) + round_up(acl_size, QLINK_ALIGN)); tlv->type = cpu_to_le16(QTN_TLV_ID_ACL_DATA); tlv->len = cpu_to_le16(acl_size); qlink_acl_data_cfg2q(params, (struct qlink_acl_data *)tlv->val); diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 51af93bdf06e..9d3849488fc7 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -25,7 +25,6 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; int ret = 0; @@ -58,23 +57,17 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, sinfo->generation = vif->generation; payload_len = len - sizeof(*sta_assoc); - tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies; - while (payload_len >= sizeof(*tlv)) { + qlink_for_each_tlv(tlv, sta_assoc->ies, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) { - ret = -EINVAL; - goto out; - } if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) { + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) { ret = -EINVAL; goto out; } @@ -88,12 +81,10 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, sinfo->assoc_req_ies_len = ie_len; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) { + if (!qlink_tlv_parsing_ok(tlv, sta_assoc->ies, payload_len)) { + pr_err("Malformed TLV buffer\n"); ret = -EINVAL; goto out; } @@ -153,7 +144,6 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; const u8 *rsp_ies = NULL; size_t rsp_ies_len = 0; @@ -235,24 +225,17 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, } payload_len = len - sizeof(*join_info); - tlv = (struct qlink_tlv_hdr *)join_info->ies; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, join_info->ies, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (payload_len < tlv_full_len) { - pr_warn("invalid %u TLV\n", tlv_type); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto done; - } if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) { + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) { pr_warn("invalid IE_SET TLV\n"); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; @@ -275,15 +258,10 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, break; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) - pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n", - vif->mac->macid, vif->vifid, payload_len); - + if (!qlink_tlv_parsing_ok(tlv, join_info->ies, payload_len)) + pr_warn("Malformed TLV buffer\n"); done: cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies, rsp_ies_len, status, GFP_KERNEL); @@ -368,7 +346,6 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, size_t payload_len; u16 tlv_type; u16 tlv_value_len; - size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; const u8 *ies = NULL; size_t ies_len = 0; @@ -387,21 +364,17 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, } payload_len = len - sizeof(*sr); - tlv = (struct qlink_tlv_hdr *)sr->payload; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + qlink_for_each_tlv(tlv, sr->payload, payload_len) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); - tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - - if (tlv_full_len > payload_len) - return -EINVAL; if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; - if (payload_len < sizeof(*ie_set)) + if (tlv_value_len < + (sizeof(*ie_set) - sizeof(ie_set->hdr))) return -EINVAL; ie_set = (const struct qlink_tlv_ie_set *)tlv; @@ -424,12 +397,9 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, ies_len = ie_len; } } - - payload_len -= tlv_full_len; - tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) + if (!qlink_tlv_parsing_ok(tlv, sr->payload, payload_len)) return -EINVAL; bss = cfg80211_inform_bss(wiphy, channel, frame_type, diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 16acb10386ad..3577482c5076 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -19,6 +19,8 @@ #define QLINK_PROTO_VER \ QLINK_VER(QLINK_PROTO_VER_MAJOR, QLINK_PROTO_VER_MINOR) +#define QLINK_ALIGN 4 + #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -184,7 +186,7 @@ struct qlink_chandef { __le16 center_freq1; __le16 center_freq2; u8 width; - u8 rsvd; + u8 rsvd[3]; } __packed; #define QLINK_MAX_NR_CIPHER_SUITES 5 @@ -340,9 +342,9 @@ struct qlink_cmd { struct qlink_msg_header mhdr; __le16 cmd_id; __le16 seq_num; - u8 rsvd[2]; u8 macid; u8 vifid; + u8 rsvd[2]; } __packed; /** @@ -404,6 +406,7 @@ struct qlink_cmd_mgmt_frame_register { struct qlink_cmd chdr; __le16 frame_type; u8 do_register; + u8 rsvd[1]; } __packed; /** @@ -441,6 +444,7 @@ struct qlink_cmd_frame_tx { struct qlink_cmd_get_sta_info { struct qlink_cmd chdr; u8 sta_addr[ETH_ALEN]; + u8 rsvd[2]; } __packed; /** @@ -460,6 +464,7 @@ struct qlink_cmd_add_key { u8 addr[ETH_ALEN]; __le32 cipher; __le16 vlanid; + u8 rsvd[2]; u8 key_data[0]; } __packed; @@ -489,6 +494,7 @@ struct qlink_cmd_set_def_key { u8 key_index; u8 unicast; u8 multicast; + u8 rsvd[1]; } __packed; /** @@ -499,6 +505,7 @@ struct qlink_cmd_set_def_key { struct qlink_cmd_set_def_mgmt_key { struct qlink_cmd chdr; u8 key_index; + u8 rsvd[3]; } __packed; /** @@ -515,6 +522,7 @@ struct qlink_cmd_change_sta { __le16 if_type; __le16 vlanid; u8 sta_addr[ETH_ALEN]; + u8 rsvd[2]; } __packed; /** @@ -525,8 +533,9 @@ struct qlink_cmd_change_sta { struct qlink_cmd_del_sta { struct qlink_cmd chdr; __le16 reason_code; - u8 subtype; u8 sta_addr[ETH_ALEN]; + u8 subtype; + u8 rsvd[3]; } __packed; enum qlink_sta_connect_flags { @@ -593,6 +602,7 @@ struct qlink_cmd_external_auth { struct qlink_cmd_disconnect { struct qlink_cmd chdr; __le16 reason; + u8 rsvd[2]; } __packed; /** @@ -604,6 +614,7 @@ struct qlink_cmd_disconnect { struct qlink_cmd_updown { struct qlink_cmd chdr; u8 if_up; + u8 rsvd[3]; } __packed; /** @@ -627,6 +638,7 @@ enum qlink_band { struct qlink_cmd_band_info_get { struct qlink_cmd chdr; u8 band; + u8 rsvd[3]; } __packed; /** @@ -702,6 +714,7 @@ struct qlink_cmd_chan_switch { u8 radar_required; u8 block_tx; u8 beacon_count; + u8 rsvd[3]; } __packed; /** @@ -805,6 +818,7 @@ struct qlink_cmd_pm_set { struct qlink_cmd chdr; __le32 pm_standby_timer; u8 pm_mode; + u8 rsvd[3]; } __packed; /** @@ -1225,6 +1239,7 @@ struct qlink_event_bss_join { struct qlink_event_bss_leave { struct qlink_event ehdr; __le16 reason; + u8 rsvd[2]; } __packed; /** @@ -1341,10 +1356,10 @@ struct qlink_event_radar { */ struct qlink_event_external_auth { struct qlink_event ehdr; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - u8 bssid[ETH_ALEN]; __le32 akm_suite; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 bssid[ETH_ALEN]; + u8 ssid_len; u8 action; } __packed; @@ -1560,6 +1575,7 @@ struct qlink_tlv_ie_set { struct qlink_tlv_hdr hdr; u8 type; u8 flags; + u8 rsvd[2]; u8 ie_data[0]; } __packed; @@ -1572,6 +1588,7 @@ struct qlink_tlv_ie_set { struct qlink_tlv_ext_ie { struct qlink_tlv_hdr hdr; u8 eid_ext; + u8 rsvd[3]; u8 ie_data[0]; } __packed; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index f873beed2ae7..9164b750396c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -20,8 +20,9 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb, u16 tlv_id, const u8 arr[], size_t arr_len) { - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + arr_len); + struct qlink_tlv_hdr *hdr; + hdr = skb_put(skb, sizeof(*hdr) + round_up(arr_len, QLINK_ALIGN)); hdr->type = cpu_to_le16(tlv_id); hdr->len = cpu_to_le16(arr_len); memcpy(hdr->val, arr, arr_len); @@ -35,27 +36,6 @@ static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id) hdr->len = cpu_to_le16(0); } -static inline void qtnf_cmd_skb_put_tlv_u8(struct sk_buff *skb, u16 tlv_id, - u8 value) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value)); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(sizeof(value)); - *hdr->val = value; -} - -static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb, - u16 tlv_id, u16 value) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value)); - __le16 tmp = cpu_to_le16(value); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(sizeof(value)); - memcpy(hdr->val, &tmp, sizeof(tmp)); -} - static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb, u16 tlv_id, u32 value) { @@ -85,4 +65,17 @@ u32 qlink_utils_chflags_cfg2q(u32 cfgflags); void qlink_utils_regrule_q2nl(struct ieee80211_reg_rule *rule, const struct qlink_tlv_reg_rule *tlv_rule); +#define qlink_for_each_tlv(_tlv, _start, _datalen) \ + for (_tlv = (const struct qlink_tlv_hdr *)(_start); \ + (const u8 *)(_start) + (_datalen) - (const u8 *)_tlv >= \ + (int)sizeof(*_tlv) && \ + (const u8 *)(_start) + (_datalen) - (const u8 *)_tlv >= \ + (int)sizeof(*_tlv) + le16_to_cpu(_tlv->len); \ + _tlv = (const struct qlink_tlv_hdr *)(_tlv->val + \ + round_up(le16_to_cpu(_tlv->len), QLINK_ALIGN))) + +#define qlink_tlv_parsing_ok(_tlv_last, _start, _datalen) \ + ((const u8 *)(_tlv_last) == \ + (const u8 *)(_start) + round_up(_datalen, QLINK_ALIGN)) + #endif /* _QTN_FMAC_QLINK_UTIL_H_ */ From 5edadc5a3f1179b3e4db895d6a941e3d257eaa0c Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:55 +0000 Subject: [PATCH 011/168] qtnfmac: update channel switch command to support 6GHz band With an addition of 6GHz band support, channel number can no longer be used to uniquely identify a specific channel. Modify channel switch command to use chandef data. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 17 +++++++------ .../net/wireless/quantenna/qtnfmac/qlink.h | 25 ++++++++++++++----- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 1271d38e4c7a..31286699a5b7 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -2519,6 +2519,7 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, struct qlink_cmd_chan_switch *cmd; struct sk_buff *cmd_skb; int ret; + u64 flags = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, vif->vifid, QLINK_CMD_CHAN_SWITCH, @@ -2526,19 +2527,19 @@ int qtnf_cmd_send_chan_switch(struct qtnf_vif *vif, if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); + if (params->radar_required) + flags |= QLINK_CHAN_SW_RADAR_REQUIRED; + + if (params->block_tx) + flags |= QLINK_CHAN_SW_BLOCK_TX; cmd = (struct qlink_cmd_chan_switch *)cmd_skb->data; - cmd->channel = cpu_to_le16(params->chandef.chan->hw_value); - cmd->radar_required = params->radar_required; - cmd->block_tx = params->block_tx; + qlink_chandef_cfg2q(¶ms->chandef, &cmd->channel); + cmd->flags = cpu_to_le64(flags); cmd->beacon_count = params->count; + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send(mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(mac->bus); return ret; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 3577482c5076..ab2bfae7ff3e 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -700,19 +700,32 @@ struct qlink_cmd_reg_notify { u8 info[0]; } __packed; +/** + * enum qlink_chan_sw_flags - channel switch control flags + * + * @QLINK_CHAN_SW_RADAR_REQUIRED: whether radar detection is required on a new + * channel. + * @QLINK_CHAN_SW_BLOCK_TX: whether transmissions should be blocked while + * changing a channel. + */ +enum qlink_chan_sw_flags { + QLINK_CHAN_SW_RADAR_REQUIRED = BIT(0), + QLINK_CHAN_SW_BLOCK_TX = BIT(1), +}; + /** * struct qlink_cmd_chan_switch - data for QLINK_CMD_CHAN_SWITCH command * - * @channel: channel number according to 802.11 17.3.8.3.2 and Annex J - * @radar_required: whether radar detection is required on the new channel - * @block_tx: whether transmissions should be blocked while changing + * @channel: channel to switch to. + * @flags: flags to control channel switch, bitmap of &enum qlink_chan_sw_flags. * @beacon_count: number of beacons until switch */ struct qlink_cmd_chan_switch { struct qlink_cmd chdr; - __le16 channel; - u8 radar_required; - u8 block_tx; + struct qlink_chandef channel; + __le64 flags; + __le32 n_counter_offsets_beacon; + __le32 n_counter_offsets_presp; u8 beacon_count; u8 rsvd[3]; } __packed; From 501c3be1ec3ccc3297543057e7337a39b4959495 Mon Sep 17 00:00:00 2001 From: Igor Mitsyanko Date: Mon, 27 Jan 2020 10:46:56 +0000 Subject: [PATCH 012/168] qtnfmac: drop unnecessary TLVs from scan command Most part of scan command data is always present, so no need to keep it in TLV. Simplify scan command processing moving most part of its parameters into a fixed part of qlink_cmd_scan message. Use fixed dwell time values for normal scan when device is not connected, and allow wireless card decide on dwell times by itself if it's operating as a STA and is connected. When connected, card can select dwell times dynamically based on traffic conditions to get best results. Signed-off-by: Igor Mitsyanko Signed-off-by: Kalle Valo --- .../net/wireless/quantenna/qtnfmac/commands.c | 132 ++++++++---------- .../net/wireless/quantenna/qtnfmac/qlink.h | 51 +++++-- .../wireless/quantenna/qtnfmac/qlink_util.h | 8 -- 3 files changed, 97 insertions(+), 94 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 31286699a5b7..ccc1e06dfcf6 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -11,11 +11,11 @@ #include "bus.h" #include "commands.h" +/* Let device itself to select best values for current conditions */ #define QTNF_SCAN_TIME_AUTO 0 -/* Let device itself to select best values for current conditions */ -#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT QTNF_SCAN_TIME_AUTO -#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT QTNF_SCAN_TIME_AUTO +#define QTNF_SCAN_DWELL_ACTIVE_DEFAULT 90 +#define QTNF_SCAN_DWELL_PASSIVE_DEFAULT 100 #define QTNF_SCAN_SAMPLE_DURATION_DEFAULT QTNF_SCAN_TIME_AUTO static int qtnf_cmd_check_reply_header(const struct qlink_resp *resp, @@ -2011,108 +2011,90 @@ static void qtnf_cmd_randmac_tlv_add(struct sk_buff *cmd_skb, memcpy(randmac->mac_addr_mask, mac_addr_mask, ETH_ALEN); } -static void qtnf_cmd_scan_set_dwell(struct qtnf_wmac *mac, - struct sk_buff *cmd_skb) -{ - struct cfg80211_scan_request *scan_req = mac->scan_req; - u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; - u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; - u16 duration = QTNF_SCAN_SAMPLE_DURATION_DEFAULT; - - if (scan_req->duration) { - dwell_active = scan_req->duration; - dwell_passive = scan_req->duration; - } - - pr_debug("MAC%u: %s scan dwell active=%u, passive=%u, duration=%u\n", - mac->macid, - scan_req->duration_mandatory ? "mandatory" : "max", - dwell_active, dwell_passive, duration); - - qtnf_cmd_skb_put_tlv_u32(cmd_skb, - QTN_TLV_ID_SCAN_DWELL_ACTIVE, - dwell_active); - qtnf_cmd_skb_put_tlv_u32(cmd_skb, - QTN_TLV_ID_SCAN_DWELL_PASSIVE, - dwell_passive); - qtnf_cmd_skb_put_tlv_u32(cmd_skb, - QTN_TLV_ID_SCAN_SAMPLE_DURATION, - duration); -} - int qtnf_cmd_send_scan(struct qtnf_wmac *mac) { - struct sk_buff *cmd_skb; - struct ieee80211_channel *sc; struct cfg80211_scan_request *scan_req = mac->scan_req; - int n_channels; - int count = 0; + u16 dwell_passive = QTNF_SCAN_DWELL_PASSIVE_DEFAULT; + u16 dwell_active = QTNF_SCAN_DWELL_ACTIVE_DEFAULT; + struct wireless_dev *wdev = scan_req->wdev; + struct ieee80211_channel *sc; + struct qlink_cmd_scan *cmd; + struct sk_buff *cmd_skb; + int n_channels = 0; + u64 flags = 0; + int count; int ret; cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, QLINK_VIFID_RSVD, QLINK_CMD_SCAN, - sizeof(struct qlink_cmd)); + sizeof(*cmd)); if (!cmd_skb) return -ENOMEM; - qtnf_bus_lock(mac->bus); + cmd = (struct qlink_cmd_scan *)cmd_skb->data; - if (scan_req->n_ssids != 0) { - while (count < scan_req->n_ssids) { - qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, - scan_req->ssids[count].ssid, - scan_req->ssids[count].ssid_len); - count++; - } + if (scan_req->duration) { + dwell_active = scan_req->duration; + dwell_passive = scan_req->duration; + } else if (wdev->iftype == NL80211_IFTYPE_STATION && + wdev->current_bss) { + /* let device select dwell based on traffic conditions */ + dwell_active = QTNF_SCAN_TIME_AUTO; + dwell_passive = QTNF_SCAN_TIME_AUTO; + } + + cmd->n_ssids = cpu_to_le16(scan_req->n_ssids); + for (count = 0; count < scan_req->n_ssids; ++count) { + qtnf_cmd_skb_put_tlv_arr(cmd_skb, WLAN_EID_SSID, + scan_req->ssids[count].ssid, + scan_req->ssids[count].ssid_len); } if (scan_req->ie_len != 0) qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, scan_req->ie, scan_req->ie_len); - if (scan_req->n_channels) { - n_channels = scan_req->n_channels; - count = 0; + for (count = 0; count < scan_req->n_channels; ++count) { + sc = scan_req->channels[count]; + if (sc->flags & IEEE80211_CHAN_DISABLED) + continue; - while (n_channels != 0) { - sc = scan_req->channels[count]; - if (sc->flags & IEEE80211_CHAN_DISABLED) { - n_channels--; - continue; - } + pr_debug("[MAC%u] scan chan=%d, freq=%d, flags=%#x\n", + mac->macid, sc->hw_value, sc->center_freq, + sc->flags); - pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n", - mac->macid, sc->hw_value, sc->center_freq, - sc->flags); - - qtnf_cmd_channel_tlv_add(cmd_skb, sc); - n_channels--; - count++; - } + qtnf_cmd_channel_tlv_add(cmd_skb, sc); + ++n_channels; } - qtnf_cmd_scan_set_dwell(mac, cmd_skb); + if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) + flags |= QLINK_SCAN_FLAG_FLUSH; + + if (scan_req->duration_mandatory) + flags |= QLINK_SCAN_FLAG_DURATION_MANDATORY; + + cmd->n_channels = cpu_to_le16(n_channels); + cmd->active_dwell = cpu_to_le16(dwell_active); + cmd->passive_dwell = cpu_to_le16(dwell_passive); + cmd->sample_duration = cpu_to_le16(QTNF_SCAN_SAMPLE_DURATION_DEFAULT); + cmd->flags = cpu_to_le64(flags); + + pr_debug("[MAC%u] %s scan dwell active=%u passive=%u duration=%u\n", + mac->macid, + scan_req->duration_mandatory ? "mandatory" : "max", + dwell_active, dwell_passive, + QTNF_SCAN_SAMPLE_DURATION_DEFAULT); if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { - pr_debug("MAC%u: scan with random addr=%pM, mask=%pM\n", + pr_debug("[MAC%u] scan with random addr=%pM, mask=%pM\n", mac->macid, scan_req->mac_addr, scan_req->mac_addr_mask); - qtnf_cmd_randmac_tlv_add(cmd_skb, scan_req->mac_addr, scan_req->mac_addr_mask); } - if (scan_req->flags & NL80211_SCAN_FLAG_FLUSH) { - pr_debug("MAC%u: flush cache before scan\n", mac->macid); - - qtnf_cmd_skb_put_tlv_tag(cmd_skb, QTN_TLV_ID_SCAN_FLUSH); - } - + qtnf_bus_lock(mac->bus); ret = qtnf_cmd_send(mac->bus, cmd_skb); - if (ret) - goto out; - -out: qtnf_bus_unlock(mac->bus); return ret; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index ab2bfae7ff3e..7ee1070f985f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -920,6 +920,46 @@ struct qlink_cmd_ndev_changeupper { u8 rsvd[1]; } __packed; +/** + * enum qlink_scan_flags - scan request control flags + * + * Scan flags are used to control QLINK_CMD_SCAN behavior. + * + * @QLINK_SCAN_FLAG_FLUSH: flush cache before scanning. + */ +enum qlink_scan_flags { + QLINK_SCAN_FLAG_FLUSH = BIT(0), + QLINK_SCAN_FLAG_DURATION_MANDATORY = BIT(1), +}; + +/** + * struct qlink_cmd_scan - data for QLINK_CMD_SCAN command + * + * @flags: scan flags, a bitmap of &enum qlink_scan_flags. + * @n_ssids: number of WLAN_EID_SSID TLVs expected in variable portion of the + * command. + * @n_channels: number of QTN_TLV_ID_CHANNEL TLVs expected in variable payload. + * @active_dwell: time spent on a single channel for an active scan. + * @passive_dwell: time spent on a single channel for a passive scan. + * @sample_duration: total duration of sampling a single channel during a scan + * including off-channel dwell time and operating channel time. + * @bssid: specific BSSID to scan for or a broadcast BSSID. + * @scan_width: channel width to use, one of &enum qlink_channel_width. + */ +struct qlink_cmd_scan { + struct qlink_cmd chdr; + __le64 flags; + __le16 n_ssids; + __le16 n_channels; + __le16 active_dwell; + __le16 passive_dwell; + __le16 sample_duration; + u8 bssid[ETH_ALEN]; + u8 scan_width; + u8 rsvd[3]; + u8 var_info[0]; +} __packed; + /* QLINK Command Responses messages related definitions */ @@ -1407,13 +1447,6 @@ struct qlink_event_mic_failure { * @QTN_TLV_ID_STA_STATS: per-STA statistics as defined by * &struct qlink_sta_stats. Valid values are marked as such in a bitmap * carried by QTN_TLV_ID_BITMAP. - * @QTN_TLV_ID_SCAN_DWELL_ACTIVE: time spent on a single channel for an active - * scan. - * @QTN_TLV_ID_SCAN_DWELL_PASSIVE: time spent on a single channel for a passive - * scan. - * @QTN_TLV_ID_SCAN_SAMPLE_DURATION: total duration of sampling a single channel - * during a scan including off-channel dwell time and operating channel - * time. * @QTN_TLV_ID_IFTYPE_DATA: supported band data. */ enum qlink_tlv_id { @@ -1444,10 +1477,6 @@ enum qlink_tlv_id { QTN_TLV_ID_RANDOM_MAC_ADDR = 0x0408, QTN_TLV_ID_WOWLAN_CAPAB = 0x0410, QTN_TLV_ID_WOWLAN_PATTERN = 0x0411, - QTN_TLV_ID_SCAN_FLUSH = 0x0412, - QTN_TLV_ID_SCAN_DWELL_ACTIVE = 0x0413, - QTN_TLV_ID_SCAN_DWELL_PASSIVE = 0x0416, - QTN_TLV_ID_SCAN_SAMPLE_DURATION = 0x0417, QTN_TLV_ID_IFTYPE_DATA = 0x0418, }; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index 9164b750396c..230a10a41c7a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -28,14 +28,6 @@ static inline void qtnf_cmd_skb_put_tlv_arr(struct sk_buff *skb, memcpy(hdr->val, arr, arr_len); } -static inline void qtnf_cmd_skb_put_tlv_tag(struct sk_buff *skb, u16 tlv_id) -{ - struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr)); - - hdr->type = cpu_to_le16(tlv_id); - hdr->len = cpu_to_le16(0); -} - static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb, u16 tlv_id, u32 value) { From 946d077a4256c1afffcb1fd4213529da2d793d8e Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 27 Jan 2020 10:46:58 +0000 Subject: [PATCH 013/168] qtnfmac: fix potential Spectre vulnerabilities Fix potential Spectre vulnerabilities and other warnings reported by smatch: drivers/net/wireless/quantenna/qtnfmac/core.c:49 qtnf_core_get_mac() warn: potential spectre issue 'bus->mac' [r] (local cap) drivers/net/wireless/quantenna/qtnfmac/core.c:51 qtnf_core_get_mac() warn: possible spectre second half. 'mac' drivers/net/wireless/quantenna/qtnfmac/event.c:671 qtnf_event_parse() warn: potential spectre issue 'mac->iflist' [r] (local cap) drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c:912 qtnf_pcie_skb_send() warn: variable dereferenced before check 'skb' (see line 881) Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/core.c | 4 +++- drivers/net/wireless/quantenna/qtnfmac/event.c | 9 ++++++--- drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 74c9aa297ec9..9e666fac8b5f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "core.h" #include "bus.h" @@ -41,11 +42,12 @@ struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid) { struct qtnf_wmac *mac = NULL; - if (unlikely(macid >= QTNF_MAX_MAC)) { + if (macid >= QTNF_MAX_MAC) { pr_err("invalid MAC index %u\n", macid); return NULL; } + macid = array_index_nospec(macid, QTNF_MAX_MAC); mac = bus->mac[macid]; if (unlikely(!mac)) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 9d3849488fc7..7e408b5c5549 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "cfg80211.h" #include "core.h" @@ -632,18 +633,20 @@ static int qtnf_event_parse(struct qtnf_wmac *mac, int ret = -1; u16 event_id; u16 event_len; + u8 vifid; event = (const struct qlink_event *)event_skb->data; event_id = le16_to_cpu(event->event_id); event_len = le16_to_cpu(event->mhdr.len); - if (likely(event->vifid < QTNF_MAX_INTF)) { - vif = &mac->iflist[event->vifid]; - } else { + if (event->vifid >= QTNF_MAX_INTF) { pr_err("invalid vif(%u)\n", event->vifid); return -EINVAL; } + vifid = array_index_nospec(event->vifid, QTNF_MAX_INTF); + vif = &mac->iflist[vifid]; + switch (event_id) { case QLINK_EVENT_STA_ASSOCIATED: ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event, diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c index 8e0d8018208a..dbb241106d8a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/pearl_pcie.c @@ -593,7 +593,7 @@ static int qtnf_pcie_skb_send(struct qtnf_bus *bus, struct sk_buff *skb) priv->tx_bd_w_index = i; tx_done: - if (ret && skb) { + if (ret) { pr_err_ratelimited("drop skb\n"); if (skb->dev) skb->dev->stats.tx_dropped++; From 863844ee3bd38219c88e82966d1df36a77716f3e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 28 Jan 2020 14:14:57 -0800 Subject: [PATCH 014/168] brcmfmac: abort and release host after error With commit 216b44000ada ("brcmfmac: Fix use after free in brcmf_sdio_readframes()") applied, we see locking timeouts in brcmf_sdio_watchdog_thread(). brcmfmac: brcmf_escan_timeout: timer expired INFO: task brcmf_wdog/mmc1:621 blocked for more than 120 seconds. Not tainted 4.19.94-07984-g24ff99a0f713 #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. brcmf_wdog/mmc1 D 0 621 2 0x00000000 last_sleep: 2440793077. last_runnable: 2440766827 [] (__schedule) from [] (schedule+0x98/0xc4) [] (schedule) from [] (__mmc_claim_host+0x154/0x274) [] (__mmc_claim_host) from [] (brcmf_sdio_watchdog_thread+0x1b0/0x1f8 [brcmfmac]) [] (brcmf_sdio_watchdog_thread [brcmfmac]) from [] (kthread+0x178/0x180) In addition to restarting or exiting the loop, it is also necessary to abort the command and to release the host. Fixes: 216b44000ada ("brcmfmac: Fix use after free in brcmf_sdio_readframes()") Cc: Dan Carpenter Cc: Matthias Kaehlcke Cc: Brian Norris Cc: Douglas Anderson Signed-off-by: Guenter Roeck Reviewed-by: Douglas Anderson Acked-by: franky.lin@broadcom.com Acked-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index f9047db6a11d..3a08252f1a53 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1938,6 +1938,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new, BRCMF_SDIO_FT_NORMAL)) { rd->len = 0; + brcmf_sdio_rxfail(bus, true, true); + sdio_release_host(bus->sdiodev->func1); brcmu_pkt_buf_free_skb(pkt); continue; } From 597fc0e6ad59c669062d159fd7394058c2adbbfc Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 5 Feb 2020 15:08:52 +0800 Subject: [PATCH 015/168] rtw88: remove unused parameter vif in rtw_lps_pg_info_get() vif is not used, remove it Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 243441453ead..b765b26b6926 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -819,8 +819,7 @@ static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw) return skb; } -static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw) { struct rtw_dev *rtwdev = hw->priv; struct rtw_chip_info *chip = rtwdev->chip; @@ -876,7 +875,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw, skb_new = rtw_lps_pg_dpk_get(hw); break; case RSVD_LPS_PG_INFO: - skb_new = rtw_lps_pg_info_get(hw, vif); + skb_new = rtw_lps_pg_info_get(hw); break; case RSVD_PROBE_REQ: ssid = (struct cfg80211_ssid *)rsvd_pkt->ssid; From 9e01c07069dbd0e025352d958c873a6504f8ce1b Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 5 Feb 2020 15:08:53 +0800 Subject: [PATCH 016/168] rtw88: add rtw_read8_mask and rtw_read16_mask Both are missing but could be used sometimes. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/hci.h | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h index 85a81a578fd5..cad56389182c 100644 --- a/drivers/net/wireless/realtek/rtw88/hci.h +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -193,6 +193,32 @@ rtw_read32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) return ret; } +static inline u16 +rtw_read16_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 ret; + + orig = rtw_read16(rtwdev, addr); + ret = (orig & mask) >> shift; + + return ret; +} + +static inline u8 +rtw_read8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask) +{ + u32 shift = __ffs(mask); + u32 orig; + u32 ret; + + orig = rtw_read8(rtwdev, addr); + ret = (orig & mask) >> shift; + + return ret; +} + static inline void rtw_write32_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 data) { From 2a4225551afbf8a0f8486c88a934f649766a186d Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 5 Feb 2020 15:08:54 +0800 Subject: [PATCH 017/168] rtw88: pci: 8822c should set clock delay to zero Since RTL8822CE has enabled reference clock auto calibration, there is no need to add any clock delay for covering the timing gap of the reference clock. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/pci.c | 7 +++++++ drivers/net/wireless/realtek/rtw88/pci.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 1fbc14c149ec..9ac77aef708d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1197,11 +1197,18 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter) static void rtw_pci_link_cfg(struct rtw_dev *rtwdev) { + struct rtw_chip_info *chip = rtwdev->chip; struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; struct pci_dev *pdev = rtwpci->pdev; u16 link_ctrl; int ret; + /* RTL8822CE has enabled REFCLK auto calibration, it does not need + * to add clock delay to cover the REFCLK timing gap. + */ + if (chip->id == RTW_CHIP_TYPE_8822C) + rtw_dbi_write8(rtwdev, RTK_PCIE_CLKDLY_CTRL, 0); + /* Though there is standard PCIE configuration space to set the * link control register, but by Realtek's design, driver should * check if host supports CLKREQ/ASPM to enable the HW module. diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h index 1580cfc57361..cd4fcd064cdb 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.h +++ b/drivers/net/wireless/realtek/rtw88/pci.h @@ -39,6 +39,7 @@ #define RTK_PCIE_LINK_CFG 0x0719 #define BIT_CLKREQ_SW_EN BIT(4) #define BIT_L1_SW_EN BIT(3) +#define RTK_PCIE_CLKDLY_CTRL 0x0725 #define BIT_PCI_BCNQ_FLAG BIT(4) #define RTK_PCI_TXBD_DESA_BCNQ 0x308 From 398b9bdab2c351c4386a4c060e5922c47ebde691 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Wed, 5 Feb 2020 15:08:55 +0800 Subject: [PATCH 018/168] rtw88: move rtw_enter_ips() to the last when config When driver is coming up, mac80211 will set changed as ~0 (0xffffffff), and driver could enter IDLE state (power off) before switching channel or other config event. So move rtw_enter_ips() to the last, to make sure the driver completed the config events before going to IDLE state. So, moves leave/enter IPS config to be first/last one according to flag IEEE80211_CONF_IDLE. If there're more configureations we want to add in the future, they must locate between leave/enter IPS. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac80211.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 6fc33e11d08c..8742b3f2b5c1 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -75,15 +75,12 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) rtw_leave_lps_deep(rtwdev); - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (hw->conf.flags & IEEE80211_CONF_IDLE) { - rtw_enter_ips(rtwdev); - } else { - ret = rtw_leave_ips(rtwdev); - if (ret) { - rtw_err(rtwdev, "failed to leave idle state\n"); - goto out; - } + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + !(hw->conf.flags & IEEE80211_CONF_IDLE)) { + ret = rtw_leave_ips(rtwdev); + if (ret) { + rtw_err(rtwdev, "failed to leave idle state\n"); + goto out; } } @@ -99,6 +96,10 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) rtw_set_channel(rtwdev); + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (hw->conf.flags & IEEE80211_CONF_IDLE)) + rtw_enter_ips(rtwdev); + out: mutex_unlock(&rtwdev->mutex); return ret; From 6eab0ba99bc2c8659ee310bbc614374ebf769ff1 Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Wed, 5 Feb 2020 15:08:56 +0800 Subject: [PATCH 019/168] rtw88: avoid holding mutex for cancel_delayed_work_sync() Driver could possibly be dead-locked while canceling works with *_sync() with mutex lock held. Those cancel_delayed_work_sync() functions will wait until the work is done, but if we hold the lock, they will never acquire the lock. To prevent this, simply release the lock and acquire again after the works have been canceled. And to avoid the works being queued again, check if the device is at RTW_FLAG_RUNNING state, otherwise just return and do nothing. Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/coex.c | 3 +++ drivers/net/wireless/realtek/rtw88/fw.c | 4 ++++ drivers/net/wireless/realtek/rtw88/main.c | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c index 4dfb2ec395ee..f91dc21a8bf1 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.c +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -1904,6 +1904,9 @@ static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) lockdep_assert_held(&rtwdev->mutex); + if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) + return; + coex_dm->reason = reason; /* update wifi_link_info_ext variable */ diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index b765b26b6926..b36928470fc0 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -136,6 +136,9 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) mutex_lock(&rtwdev->mutex); + if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) + goto unlock; + switch (c2h->id) { case C2H_BT_INFO: rtw_coex_bt_info_notify(rtwdev, c2h->payload, len); @@ -153,6 +156,7 @@ void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb) break; } +unlock: mutex_unlock(&rtwdev->mutex); } diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 2845d2838f7b..edecc7d7ea56 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -909,11 +909,16 @@ void rtw_core_stop(struct rtw_dev *rtwdev) clear_bit(RTW_FLAG_RUNNING, rtwdev->flags); clear_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags); + mutex_unlock(&rtwdev->mutex); + + cancel_work_sync(&rtwdev->c2h_work); cancel_delayed_work_sync(&rtwdev->watch_dog_work); cancel_delayed_work_sync(&coex->bt_relink_work); cancel_delayed_work_sync(&coex->bt_reenable_work); cancel_delayed_work_sync(&coex->defreeze_work); + mutex_lock(&rtwdev->mutex); + rtw_power_off(rtwdev); } From 55cc84421c30eb511a7a09d1addbfaded943c959 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Wed, 5 Feb 2020 15:08:57 +0800 Subject: [PATCH 020/168] rtw88: add ciphers to suppress error message Though hardware isn't implement CCMP-256, GCMP and GCMP-256, it's possible to fallback to use software de-/en-cryption implemented by mac80211. Without adding these chipers, kernel log will show something if we connect to a WPA3 enterprise AP, likes wlan0: failed to set key (1, ff:ff:ff:ff:ff:ff) to hardware (-524) Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac80211.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 8742b3f2b5c1..0190ec6fa090 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -515,6 +515,9 @@ static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_BIP_CMAC_256: case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: /* suppress error messages */ return -EOPNOTSUPP; default: From 8299adec99b29f341f0ee4269f1ce70ca8508e78 Mon Sep 17 00:00:00 2001 From: Tzu-En Huang Date: Wed, 5 Feb 2020 15:08:58 +0800 Subject: [PATCH 021/168] rtw88: 8822c: update power sequence to v16 Fix switching xtal mode leads to BT USB error issue. Signed-off-by: Tzu-En Huang Signed-off-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 3865097696d4..d49c8b697e4f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3544,6 +3544,11 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x1064, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_ALL_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), BIT(1)}, {0xFFFF, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, From 16bbc3eb83728c03138191a5d23d84d38175fa26 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 29 Jan 2020 14:02:59 +0100 Subject: [PATCH 022/168] rsi: fix null pointer dereference during rsi_shutdown() Appearently the hw pointer can be NULL while the module is loaded and in that case rsi_shutdown() crashes due to the unconditional dereference. Signed-off-by: Martin Kepplinger Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 1bebba4e8527..5d6143a55187 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1468,12 +1468,15 @@ static void rsi_shutdown(struct device *dev) struct rsi_91x_sdiodev *sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; struct ieee80211_hw *hw = adapter->hw; - struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); - if (rsi_config_wowlan(adapter, wowlan)) - rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + if (hw) { + struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; + + if (rsi_config_wowlan(adapter, wowlan)) + rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + } if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && adapter->priv->bt_adapter) { From bafbc6f0b51b0bb8566c5d8ec255838c8cfe3545 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 29 Jan 2020 20:39:24 +0300 Subject: [PATCH 023/168] rtw88: Use kfree_skb() instead of kfree() sk_buff structs need to be freed with kfree_skb(), not kfree(). Fixes: b6c12908a33e ("rtw88: Add wowlan net-detect support") Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index b36928470fc0..6867bf29d4c8 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -749,7 +749,7 @@ static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw) loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid); if (!loc) { rtw_err(rtwdev, "failed to get probe req rsvd loc\n"); - kfree(skb); + kfree_skb(skb); return NULL; } nlo_hdr->location[i] = loc; From 40fb04b22f31e17aeb7740bba36cf3297f689f46 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Thu, 30 Jan 2020 13:31:11 +0800 Subject: [PATCH 024/168] rtw88: Use secondary channel offset enumeration The hardware value of secondary channel offset isn't very intuitive. This commit adds enumeration, so we can easier to check the logic with the suffix of enumeration name, likes _UPPER or _LOWER. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac.c | 6 +++--- drivers/net/wireless/realtek/rtw88/main.c | 14 +++++++------- drivers/net/wireless/realtek/rtw88/main.h | 10 ++++++++++ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 2 +- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index cadf0abbe16b..ec2c1adcb900 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -17,10 +17,10 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, txsc20 = primary_ch_idx; if (bw == RTW_CHANNEL_WIDTH_80) { - if (txsc20 == 1 || txsc20 == 3) - txsc40 = 9; + if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST) + txsc40 = RTW_SC_40_UPPER; else - txsc40 = 10; + txsc40 = RTW_SC_40_LOWER; } rtw_write8(rtwdev, REG_DATA_SC, BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40)); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index edecc7d7ea56..2f73820cd9ba 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -317,15 +317,15 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, case NL80211_CHAN_WIDTH_20_NOHT: case NL80211_CHAN_WIDTH_20: bandwidth = RTW_CHANNEL_WIDTH_20; - primary_chan_idx = 0; + primary_chan_idx = RTW_SC_DONT_CARE; break; case NL80211_CHAN_WIDTH_40: bandwidth = RTW_CHANNEL_WIDTH_40; if (primary_freq > center_freq) { - primary_chan_idx = 1; + primary_chan_idx = RTW_SC_20_UPPER; center_chan -= 2; } else { - primary_chan_idx = 2; + primary_chan_idx = RTW_SC_20_LOWER; center_chan += 2; } break; @@ -333,10 +333,10 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, bandwidth = RTW_CHANNEL_WIDTH_80; if (primary_freq > center_freq) { if (primary_freq - center_freq == 10) { - primary_chan_idx = 1; + primary_chan_idx = RTW_SC_20_UPPER; center_chan -= 2; } else { - primary_chan_idx = 3; + primary_chan_idx = RTW_SC_20_UPMOST; center_chan -= 6; } /* assign the center channel used @@ -345,10 +345,10 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef, cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4; } else { if (center_freq - primary_freq == 10) { - primary_chan_idx = 2; + primary_chan_idx = RTW_SC_20_LOWER; center_chan += 2; } else { - primary_chan_idx = 4; + primary_chan_idx = RTW_SC_20_LOWEST; center_chan += 6; } /* assign the center channel used diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index f334d201bfb5..d11f3a26b7bf 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -99,6 +99,16 @@ enum rtw_bandwidth { RTW_CHANNEL_WIDTH_10 = 6, }; +enum rtw_sc_offset { + RTW_SC_DONT_CARE = 0, + RTW_SC_20_UPPER = 1, + RTW_SC_20_LOWER = 2, + RTW_SC_20_UPMOST = 3, + RTW_SC_20_LOWEST = 4, + RTW_SC_40_UPPER = 9, + RTW_SC_40_LOWER = 10, +}; + enum rtw_net_type { RTW_NET_NO_LINK = 0, RTW_NET_AD_HOC = 1, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 4bc14b1a6340..2eed777ee692 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -645,7 +645,7 @@ static void rtw8822b_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1); break; case RTW_CHANNEL_WIDTH_40: - if (primary_ch_idx == 1) + if (primary_ch_idx == RTW_SC_20_UPPER) rtw_write32_set(rtwdev, REG_RXSB, BIT(4)); else rtw_write32_clr(rtwdev, REG_RXSB, BIT(4)); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index d49c8b697e4f..56de9d0c5c10 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1482,7 +1482,7 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, break; case RTW_CHANNEL_WIDTH_40: rtw_write32_mask(rtwdev, REG_CCKSB, BIT(4), - (primary_ch_idx == 1 ? 1 : 0)); + (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0)); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x5); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0); rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00, From 9c714b7caa1750d2832591286d3c071f1160b5d7 Mon Sep 17 00:00:00 2001 From: Chien-Hsun Liao Date: Thu, 30 Jan 2020 13:31:12 +0800 Subject: [PATCH 025/168] rtw88: 8822c: modify rf protection setting According to some experiments, the original RF register protection setting of 8822c cannot perfectly make sure that there is no hardware PI write (direct) during direct write. Modify the setting so that the hardware block of PI would be turned off via rtw8822c_rstb_3wire() during the direct write, to avoid RF register racing. Note that 8822b uses SIPI write (indirect), so 8822b does not have such problem. Signed-off-by: Chien-Hsun Liao Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/phy.c | 10 ---------- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 15 +++++++++++++++ drivers/net/wireless/realtek/rtw88/rtw8822c.h | 5 +++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index eea9d888fbf1..8793dd22188f 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -749,20 +749,10 @@ bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, direct_addr = base_addr[rf_path] + (addr << 2); mask &= RFREG_MASK; - if (addr == RF_CFGCH) { - rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, DISABLE_PI); - rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, DISABLE_PI); - } - rtw_write32_mask(rtwdev, direct_addr, mask, data); udelay(1); - if (addr == RF_CFGCH) { - rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, ENABLE_PI); - rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, ENABLE_PI); - } - return true; } diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 56de9d0c5c10..a32d2271215e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1289,6 +1289,17 @@ static int rtw8822c_mac_init(struct rtw_dev *rtwdev) return 0; } +static void rtw8822c_rstb_3wire(struct rtw_dev *rtwdev, bool enable) +{ + if (enable) { + rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x1); + rtw_write32_mask(rtwdev, REG_ANAPAR_A, BIT_ANAPAR_UPDATE, 0x1); + rtw_write32_mask(rtwdev, REG_ANAPAR_B, BIT_ANAPAR_UPDATE, 0x1); + } else { + rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x0); + } +} + static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) { #define RF18_BAND_MASK (BIT(16) | BIT(9) | BIT(8)) @@ -1337,6 +1348,8 @@ static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) break; } + rtw8822c_rstb_3wire(rtwdev, false); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, 0x04, 0x01); rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, 0x1f, 0x12); rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, 0xfffff, rf_rxbb); @@ -1349,6 +1362,8 @@ static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw) rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_reg18); rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_reg18); + + rtw8822c_rstb_3wire(rtwdev, true); } static void rtw8822c_toggle_igi(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h index abd9f300bedd..dfd8662a0c0e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h @@ -190,6 +190,8 @@ const struct rtw_table name ## _tbl = { \ #define BIT_3WIRE_TX_EN BIT(0) #define BIT_3WIRE_RX_EN BIT(1) #define BIT_3WIRE_PI_ON BIT(28) +#define REG_ANAPAR_A 0x1830 +#define BIT_ANAPAR_UPDATE BIT(29) #define REG_RXAGCCTL0 0x18ac #define BITS_RXAGC_CCK GENMASK(15, 12) #define BITS_RXAGC_OFDM GENMASK(8, 4) @@ -223,6 +225,8 @@ const struct rtw_table name ## _tbl = { \ #define BIT_CCK_BLK_EN BIT(1) #define BIT_CCK_OFDM_BLK_EN (BIT(0) | BIT(1)) #define REG_CCAMSK 0x1c80 +#define REG_RSTB 0x1c90 +#define BIT_RSTB_3WIRE BIT(8) #define REG_RX_BREAK 0x1d2c #define BIT_COM_RX_GCK_EN BIT(31) #define REG_RXFNCTL 0x1d30 @@ -243,6 +247,7 @@ const struct rtw_table name ## _tbl = { \ #define REG_OFDM_TXCNT 0x2de0 #define REG_ORITXCODE2 0x4100 #define REG_3WIRE2 0x410c +#define REG_ANAPAR_B 0x4130 #define REG_RXAGCCTL 0x41ac #define REG_DCKB_I_0 0x41bc #define REG_DCKB_I_1 0x41c0 From 74c3d72cc13401f9eb3e3c712855e9f8f2d2682b Mon Sep 17 00:00:00 2001 From: Yan-Hsuan Chuang Date: Tue, 4 Feb 2020 20:06:14 +0800 Subject: [PATCH 026/168] rtw88: disable TX-AMSDU on 2.4G band Some tests shows that using AMSDU to aggregate TCP ACKs to specific APs will degrade the throughput on 2.4G band in 20MHz bandwidth (< 10 Mbps, should be ~100 Mbps for 2x2). Also found that there's barely no negative impact if we disable TX AMSDU on 2.4G to connect to other APs. So it seems like we can just tell mac80211 to not to aggregate MSDUs when transmitting on 2.4G band. Note that we still can TX AMSDU on 5G band and benefit from it by having 50 ~ 70 Mbps throughput improvement. Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac80211.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 0190ec6fa090..b3125e311fa2 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -596,6 +596,20 @@ static int rtw_ops_ampdu_action(struct ieee80211_hw *hw, return 0; } +static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw, + struct sk_buff *head, + struct sk_buff *skb) +{ + struct rtw_dev *rtwdev = hw->priv; + struct rtw_hal *hal = &rtwdev->hal; + + /* we don't want to enable TX AMSDU on 2.4G */ + if (hal->current_band_type == RTW_BAND_2G) + return false; + + return true; +} + static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac_addr) @@ -791,6 +805,7 @@ const struct ieee80211_ops rtw_ops = { .sta_remove = rtw_ops_sta_remove, .set_key = rtw_ops_set_key, .ampdu_action = rtw_ops_ampdu_action, + .can_aggregate_in_amsdu = rtw_ops_can_aggregate_in_amsdu, .sw_scan_start = rtw_ops_sw_scan_start, .sw_scan_complete = rtw_ops_sw_scan_complete, .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, From d49f2c5063fdd00f896e408a1c1fa63e6d94a767 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 6 Feb 2020 02:54:38 -0800 Subject: [PATCH 027/168] rtw88: 8822[bc]: Make tables const, reduce data object size Reduce the data size 2kb or 3kb by making tables const. Add const to pointer declarations to make compilation work too. (x86-64 defconfig) $ size drivers/net/wireless/realtek/rtw88/rtw8822?.o* text data bss dec hex filename 25054 672 8 25734 6486 drivers/net/wireless/realtek/rtw88/rtw8822b.o.new 23870 1872 8 25750 6496 drivers/net/wireless/realtek/rtw88/rtw8822b.o.old 53646 828 0 54474 d4ca drivers/net/wireless/realtek/rtw88/rtw8822c.o.new 52846 1652 0 54498 d4e2 drivers/net/wireless/realtek/rtw88/rtw8822c.o.old (x86-64 allyesconfig) $ size drivers/net/wireless/realtek/rtw88/rtw8822?.o* text data bss dec hex filename 45811 6280 128 52219 cbfb drivers/net/wireless/realtek/rtw88/rtw8822b.o.new 44211 7880 128 52219 cbfb drivers/net/wireless/realtek/rtw88/rtw8822b.o.old 100195 8128 0 108323 1a723 drivers/net/wireless/realtek/rtw88/rtw8822c.o.new 98947 9376 0 108323 1a723 drivers/net/wireless/realtek/rtw88/rtw8822c.o.old Signed-off-by: Joe Perches Acked-by: Yan-Hsuan Chuang Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/mac.c | 19 +++++++------ drivers/net/wireless/realtek/rtw88/main.h | 22 +++++++-------- drivers/net/wireless/realtek/rtw88/pci.c | 2 +- drivers/net/wireless/realtek/rtw88/rtw8822b.c | 28 +++++++++---------- drivers/net/wireless/realtek/rtw88/rtw8822c.c | 28 +++++++++---------- 5 files changed, 50 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index ec2c1adcb900..7b245779ff90 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -101,7 +101,7 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) } static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, - struct rtw_pwr_seq_cmd *cmd) + const struct rtw_pwr_seq_cmd *cmd) { u8 value; u8 flag = 0; @@ -139,9 +139,10 @@ static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev, } static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, - u8 cut_mask, struct rtw_pwr_seq_cmd *cmd) + u8 cut_mask, + const struct rtw_pwr_seq_cmd *cmd) { - struct rtw_pwr_seq_cmd *cur_cmd; + const struct rtw_pwr_seq_cmd *cur_cmd; u32 offset; u8 value; @@ -183,13 +184,13 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, } static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, - struct rtw_pwr_seq_cmd **cmd_seq) + const struct rtw_pwr_seq_cmd **cmd_seq) { u8 cut_mask; u8 intf_mask; u8 cut; u32 idx = 0; - struct rtw_pwr_seq_cmd *cmd; + const struct rtw_pwr_seq_cmd *cmd; int ret; cut = rtwdev->hal.cut_version; @@ -223,7 +224,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_pwr_seq_cmd **pwr_seq; + const struct rtw_pwr_seq_cmd **pwr_seq; u8 rpwm; bool cur_pwr; @@ -705,7 +706,7 @@ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) { - struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; + const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; u32 prio_queues = 0; if (queues & BIT(IEEE80211_AC_VO)) @@ -793,7 +794,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) static int txdma_queue_mapping(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_rqpn *rqpn = NULL; + const struct rtw_rqpn *rqpn = NULL; u16 txdma_pq_map = 0; switch (rtw_hci_type(rtwdev)) { @@ -882,7 +883,7 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) { struct rtw_fifo_conf *fifo = &rtwdev->fifo; struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_page_table *pg_tbl = NULL; + const struct rtw_page_table *pg_tbl = NULL; u16 pubq_num; int ret; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index d11f3a26b7bf..c074cef22120 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -958,10 +958,10 @@ struct rtw_wow_param { }; struct rtw_intf_phy_para_table { - struct rtw_intf_phy_para *usb2_para; - struct rtw_intf_phy_para *usb3_para; - struct rtw_intf_phy_para *gen1_para; - struct rtw_intf_phy_para *gen2_para; + const struct rtw_intf_phy_para *usb2_para; + const struct rtw_intf_phy_para *usb3_para; + const struct rtw_intf_phy_para *gen1_para; + const struct rtw_intf_phy_para *gen2_para; u8 n_usb2_para; u8 n_usb3_para; u8 n_gen1_para; @@ -1058,13 +1058,13 @@ struct rtw_chip_info { /* init values */ u8 sys_func_en; - struct rtw_pwr_seq_cmd **pwr_on_seq; - struct rtw_pwr_seq_cmd **pwr_off_seq; - struct rtw_rqpn *rqpn_table; - struct rtw_page_table *page_table; - struct rtw_intf_phy_para_table *intf_table; + const struct rtw_pwr_seq_cmd **pwr_on_seq; + const struct rtw_pwr_seq_cmd **pwr_off_seq; + const struct rtw_rqpn *rqpn_table; + const struct rtw_page_table *page_table; + const struct rtw_intf_phy_para_table *intf_table; - struct rtw_hw_reg *dig; + const struct rtw_hw_reg *dig; u32 rf_base_addr[2]; u32 rf_sipi_addr[2]; @@ -1510,7 +1510,7 @@ struct rtw_fifo_conf { u16 rsvd_cpu_instr_addr; u16 rsvd_fw_txbuf_addr; u16 rsvd_csibuf_addr; - struct rtw_rqpn *rqpn; + const struct rtw_rqpn *rqpn; }; struct rtw_fw_state { diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 9ac77aef708d..7c525bb0337d 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1255,7 +1255,7 @@ static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev) static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev) { struct rtw_chip_info *chip = rtwdev->chip; - struct rtw_intf_phy_para *para; + const struct rtw_intf_phy_para *para; u16 cut; u16 value; u16 offset; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 2eed777ee692..96aa332fb28d 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -1543,7 +1543,7 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif, rtw_warn(rtwdev, "wrong bfee role\n"); } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1581,7 +1581,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { {0x0012, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1714,7 +1714,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { {0x0003, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1787,7 +1787,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1905,26 +1905,26 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { trans_carddis_to_cardemu_8822b, trans_cardemu_to_act_8822b, NULL }; -static struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { trans_act_to_cardemu_8822b, trans_cardemu_to_carddis_8822b, NULL }; -static struct rtw_intf_phy_para usb2_param_8822b[] = { +static const struct rtw_intf_phy_para usb2_param_8822b[] = { {0xFFFF, 0x00, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para usb3_param_8822b[] = { +static const struct rtw_intf_phy_para usb3_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_D, @@ -1935,7 +1935,7 @@ static struct rtw_intf_phy_para usb3_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { +static const struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_C, @@ -1982,7 +1982,7 @@ static struct rtw_intf_phy_para pcie_gen1_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { +static const struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { {0x0001, 0xA841, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_C, @@ -2029,7 +2029,7 @@ static struct rtw_intf_phy_para pcie_gen2_param_8822b[] = { RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para_table phy_para_table_8822b = { +static const struct rtw_intf_phy_para_table phy_para_table_8822b = { .usb2_para = usb2_param_8822b, .usb3_para = usb3_param_8822b, .gen1_para = pcie_gen1_param_8822b, @@ -2046,12 +2046,12 @@ static const struct rtw_rfe_def rtw8822b_rfe_defs[] = { [5] = RTW_DEF_RFE(8822b, 5, 5), }; -static struct rtw_hw_reg rtw8822b_dig[] = { +static const struct rtw_hw_reg rtw8822b_dig[] = { [0] = { .addr = 0xc50, .mask = 0x7f }, [1] = { .addr = 0xe50, .mask = 0x7f }, }; -static struct rtw_page_table page_table_8822b[] = { +static const struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, {64, 64, 0, 0, 1}, @@ -2059,7 +2059,7 @@ static struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, }; -static struct rtw_rqpn rqpn_table_8822b[] = { +static const struct rtw_rqpn rqpn_table_8822b[] = { {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index a32d2271215e..146f693c7592 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3414,7 +3414,7 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) dm_info->pwr_trk_triggered = false; } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -3457,7 +3457,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { {0x0000, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -3571,7 +3571,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { {0x0093, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -3634,7 +3634,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -3697,47 +3697,47 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { trans_carddis_to_cardemu_8822c, trans_cardemu_to_act_8822c, NULL }; -static struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { trans_act_to_cardemu_8822c, trans_cardemu_to_carddis_8822c, NULL }; -static struct rtw_intf_phy_para usb2_param_8822c[] = { +static const struct rtw_intf_phy_para usb2_param_8822c[] = { {0xFFFF, 0x00, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para usb3_param_8822c[] = { +static const struct rtw_intf_phy_para usb3_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen1_param_8822c[] = { +static const struct rtw_intf_phy_para pcie_gen1_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para pcie_gen2_param_8822c[] = { +static const struct rtw_intf_phy_para pcie_gen2_param_8822c[] = { {0xFFFF, 0x0000, RTW_IP_SEL_PHY, RTW_INTF_PHY_CUT_ALL, RTW_INTF_PHY_PLATFORM_ALL}, }; -static struct rtw_intf_phy_para_table phy_para_table_8822c = { +static const struct rtw_intf_phy_para_table phy_para_table_8822c = { .usb2_para = usb2_param_8822c, .usb3_para = usb3_param_8822c, .gen1_para = pcie_gen1_param_8822c, @@ -3754,12 +3754,12 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { [2] = RTW_DEF_RFE(8822c, 0, 0), }; -static struct rtw_hw_reg rtw8822c_dig[] = { +static const struct rtw_hw_reg rtw8822c_dig[] = { [0] = { .addr = 0x1d70, .mask = 0x7f }, [1] = { .addr = 0x1d70, .mask = 0x7f00 }, }; -static struct rtw_page_table page_table_8822c[] = { +static const struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, {64, 64, 0, 0, 1}, @@ -3767,7 +3767,7 @@ static struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, }; -static struct rtw_rqpn rqpn_table_8822c[] = { +static const struct rtw_rqpn rqpn_table_8822c[] = { {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, From aa7619a39acef91c5a6904f3ada7d0f20e2ad25e Mon Sep 17 00:00:00 2001 From: Tzu-En Huang Date: Fri, 7 Feb 2020 16:47:29 +0800 Subject: [PATCH 028/168] rtw88: Fix incorrect beamformee role setting In associating and configuring beamformee, bfee->role is not correctly set before rtw_chip_ops::config_bfee(). Fix it by setting it correctly. Signed-off-by: Tzu-En Huang Signed-off-by: Yan-Hsuan Chuang Reviewed-by: Chris Chiu Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtw88/bf.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/bf.c b/drivers/net/wireless/realtek/rtw88/bf.c index fda771d23f71..b6d1d71f4d30 100644 --- a/drivers/net/wireless/realtek/rtw88/bf.c +++ b/drivers/net/wireless/realtek/rtw88/bf.c @@ -41,7 +41,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta_vht_cap *ic_vht_cap; const u8 *bssid = bss_conf->bssid; u32 sound_dim; - u8 bfee_role = RTW_BFEE_NONE; u8 i; if (!(chip->band & RTW_BAND_5G)) @@ -67,7 +66,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, } ether_addr_copy(bfee->mac_addr, bssid); - bfee_role = RTW_BFEE_MU; + bfee->role = RTW_BFEE_MU; bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); bfee->aid = bss_conf->aid; bfinfo->bfer_mu_cnt++; @@ -85,7 +84,7 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ether_addr_copy(bfee->mac_addr, bssid); - bfee_role = RTW_BFEE_SU; + bfee->role = RTW_BFEE_SU; bfee->sound_dim = (u8)sound_dim; bfee->g_id = 0; bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7); @@ -102,7 +101,6 @@ void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, } out_unlock: - bfee->role = bfee_role; rcu_read_unlock(); } From e54432563b68592867adefa5c3ab4d7e46546e83 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 30 Sep 2019 21:23:03 +0200 Subject: [PATCH 029/168] mt76: move initialization of some struct members to mt76_alloc_device Reduces duplication and prepares for further rework Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 1 - drivers/net/wireless/mediatek/mt76/mac80211.c | 8 ++++++-- drivers/net/wireless/mediatek/mt76/usb.c | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 6173c80189ba..eed387b10d48 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -555,7 +555,6 @@ mt76_dma_init(struct mt76_dev *dev) netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); mt76_dma_rx_fill(dev, &dev->q_rx[i]); - skb_queue_head_init(&dev->rx_skb[i]); napi_enable(&dev->napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 96018fd65779..73853b449730 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -275,6 +275,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, { struct ieee80211_hw *hw; struct mt76_dev *dev; + int i; hw = ieee80211_alloc_hw(size, ops); if (!hw) @@ -292,6 +293,11 @@ mt76_alloc_device(struct device *pdev, unsigned int size, init_waitqueue_head(&dev->tx_wait); skb_queue_head_init(&dev->status_list); + INIT_LIST_HEAD(&dev->txwi_cache); + + for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) + skb_queue_head_init(&dev->rx_skb[i]); + tasklet_init(&dev->tx_tasklet, mt76_tx_tasklet, (unsigned long)dev); return dev; @@ -307,8 +313,6 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, dev_set_drvdata(dev->dev, dev); - INIT_LIST_HEAD(&dev->txwi_cache); - SET_IEEE80211_DEV(hw, dev->dev); SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index d6d47081e281..3b9849b59571 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -956,7 +956,6 @@ int mt76u_init(struct mt76_dev *dev, tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev); tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); INIT_WORK(&usb->stat_work, mt76u_tx_status_data); - skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); usb->stat_wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0); if (!usb->stat_wq) From ac24dd35028b07a9343227c13f630617681a236e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 30 Sep 2019 22:09:06 +0200 Subject: [PATCH 030/168] mt76: introduce struct mt76_phy This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D On the first wiphy, hw->priv will point to struct mt76_dev, which contains a struct mt76_phy at the start. For the secondary wiphy, hw->priv will point to a mt76_phy encapsulated in a driver specific struct To simplify access to struct mt76_phy members from drivers, the driver specific device struct is changed to add a union of struct mt76_dev and struct mt76_phy as the first element Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 5 +++++ drivers/net/wireless/mediatek/mt76/mt76.h | 9 ++++++++- drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 5 ++++- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 6 +++++- drivers/net/wireless/mediatek/mt76/mt76x02.h | 5 ++++- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 73853b449730..14e5e1a54768 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -274,6 +274,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size, const struct mt76_driver_ops *drv_ops) { struct ieee80211_hw *hw; + struct mt76_phy *phy; struct mt76_dev *dev; int i; @@ -286,6 +287,10 @@ mt76_alloc_device(struct device *pdev, unsigned int size, dev->dev = pdev; dev->drv = drv_ops; + phy = &dev->phy; + phy->dev = dev; + phy->hw = hw; + spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->lock); spin_lock_init(&dev->cc_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index fb077760347a..2a01d2c0445b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -449,7 +449,14 @@ struct mt76_rx_status { s8 chain_signal[IEEE80211_MAX_CHAINS]; }; +struct mt76_phy { + struct ieee80211_hw *hw; + struct mt76_dev *dev; +}; + struct mt76_dev { + struct mt76_phy phy; /* must be first */ + struct ieee80211_hw *hw; struct cfg80211_chan_def chandef; struct ieee80211_channel *main_chan; @@ -581,7 +588,7 @@ enum mt76_phy_type { #define __mt76_rmw_field(_dev, _reg, _field, _val) \ __mt76_rmw(_dev, _reg, _field, FIELD_PREP(_field, _val)) -#define mt76_hw(dev) (dev)->mt76.hw +#define mt76_hw(dev) (dev)->mphy.hw bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, int timeout); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index ab54b0612e98..63ec1fa71aba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -98,7 +98,10 @@ enum mt7603_reset_cause { }; struct mt7603_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; const struct mt76_bus_ops *bus_ops; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 21486831172c..85d865e832ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -80,7 +80,11 @@ struct mt7615_vif { }; struct mt7615_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + u32 vif_mask; u32 omac_mask; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 0ca0bbfe8769..7a44ab52fca6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -70,7 +70,10 @@ struct mt76x02_beacon_ops { (dev)->beacon_ops->pre_tbtt_enable(dev, enable) struct mt76x02_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; struct mac_address macaddr_list[8]; From bfc394dd65ef474142027123b96fd1f01ec46f85 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Oct 2019 22:30:47 +0200 Subject: [PATCH 031/168] mt76: add support for an extra wiphy in the rx path This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 20 +++++++++++++------ drivers/net/wireless/mediatek/mt76/mt76.h | 11 ++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 14e5e1a54768..360e38527623 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -564,8 +564,12 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid, } EXPORT_SYMBOL(mt76_wcid_key_setup); -static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) +static void +mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb, + struct ieee80211_hw **hw, + struct ieee80211_sta **sta) { + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct mt76_rx_status mstat; @@ -590,7 +594,8 @@ static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb) memcpy(status->chain_signal, mstat.chain_signal, sizeof(mstat.chain_signal)); - return wcid_to_sta(mstat.wcid); + *sta = wcid_to_sta(mstat.wcid); + *hw = mt76_phy_hw(dev, mstat.ext_phy); } static int @@ -716,12 +721,14 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct mt76_wcid *wcid = status->wcid; bool ps; int i; + hw = mt76_phy_hw(dev, status->ext_phy); if (ieee80211_is_pspoll(hdr->frame_control) && !wcid) { - sta = ieee80211_find_sta_by_ifaddr(dev->hw, hdr->addr2, NULL); + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); if (sta) wcid = status->wcid = (struct mt76_wcid *)sta->drv_priv; } @@ -779,7 +786,7 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv; if (!skb_queue_empty(&mtxq->retry_q)) - ieee80211_schedule_txq(dev->hw, sta->txq[i]); + ieee80211_schedule_txq(hw, sta->txq[i]); } } @@ -787,6 +794,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, struct napi_struct *napi) { struct ieee80211_sta *sta; + struct ieee80211_hw *hw; struct sk_buff *skb; spin_lock(&dev->rx_lock); @@ -796,8 +804,8 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, continue; } - sta = mt76_rx_convert(skb); - ieee80211_rx_napi(dev->hw, sta, skb, napi); + mt76_rx_convert(dev, skb, &hw, &sta); + ieee80211_rx_napi(hw, sta, skb, napi); } spin_unlock(&dev->rx_lock); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2a01d2c0445b..705d25f9778a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -433,6 +433,7 @@ struct mt76_rx_status { u8 iv[6]; + u8 ext_phy:1; u8 aggr:1; u8 tid; u16 seqno; @@ -457,6 +458,8 @@ struct mt76_phy { struct mt76_dev { struct mt76_phy phy; /* must be first */ + struct mt76_phy *phy2; + struct ieee80211_hw *hw; struct cfg80211_chan_def chandef; struct ieee80211_channel *main_chan; @@ -640,6 +643,14 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, int mt76_eeprom_init(struct mt76_dev *dev, int len); void mt76_eeprom_override(struct mt76_dev *dev); +static inline struct ieee80211_hw * +mt76_phy_hw(struct mt76_dev *dev, bool phy_ext) +{ + if (phy_ext && dev->phy2) + return dev->phy2->hw; + return dev->phy.hw; +} + static inline u8 * mt76_get_txwi_ptr(struct mt76_dev *dev, struct mt76_txwi_cache *t) { From 9fba6d077f6411b116f435a9a9dc82c6cdc55324 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Oct 2019 23:27:20 +0200 Subject: [PATCH 032/168] mt76: add support for an extra wiphy in the main tx path This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +-- .../net/wireless/mediatek/mt76/mt7603/mac.c | 4 +- .../net/wireless/mediatek/mt76/mt7603/main.c | 4 +- .../net/wireless/mediatek/mt76/mt7615/main.c | 4 +- .../net/wireless/mediatek/mt76/mt76x0/main.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 4 +- .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- drivers/net/wireless/mediatek/mt76/tx.c | 50 +++++++++++-------- drivers/net/wireless/mediatek/mt76/usb.c | 2 +- 11 files changed, 45 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 705d25f9778a..4fd36b3e9440 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -720,15 +720,15 @@ static inline bool mt76_is_skb_pktid(u8 pktid) } void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); -void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, +void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); void mt76_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq); void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq); void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, bool send_bar); -void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid); -void mt76_txq_schedule_all(struct mt76_dev *dev); +void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid); +void mt76_txq_schedule_all(struct mt76_phy *phy); void mt76_tx_tasklet(unsigned long data); void mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 812d081ad943..31611195251b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1392,7 +1392,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) set_bit(MT76_RESET, &dev->mt76.state); /* lock/unlock all queues to ensure that no tx is pending */ - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); tasklet_disable(&dev->mt76.tx_tasklet); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); @@ -1456,7 +1456,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) napi_schedule(&dev->mt76.napi[1]); ieee80211_wake_queues(dev->mt76.hw); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 962e2822d19f..b10bf9da3798 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -178,7 +178,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) clear_bit(MT76_RESET, &dev->mt76.state); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, msecs_to_jiffies(MT7603_WATCHDOG_TIME)); @@ -667,7 +667,7 @@ static void mt7603_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(&dev->mphy, control->sta, wcid, skb); } const struct ieee80211_ops mt7603_ops = { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 070b03403894..c55609c06fc4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -171,7 +171,7 @@ static int mt7615_set_channel(struct mt7615_dev *dev) clear_bit(MT76_RESET, &dev->mt76.state); mutex_unlock(&dev->mt76.mutex); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); return ret; @@ -458,7 +458,7 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(&dev->mphy, control->sta, wcid, skb); } static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index b2ccf50512dc..bae99aa4d863 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -28,7 +28,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) } mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } int mt76x0_config(struct ieee80211_hw *hw, u32 changed) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 4e2371c926d8..6006c831c0a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -151,7 +151,7 @@ static void mt76x02_tx_tasklet(unsigned long data) mt76x02_mac_poll_tx_status(dev, false); mt76x02_process_tx_status_fifo(dev); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } static int mt76x02_poll_tx(struct napi_struct *napi, int budget) @@ -514,7 +514,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) ieee80211_restart_hw(dev->mt76.hw); } else { ieee80211_wake_queues(dev->mt76.hw); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 13825f642087..05dd531a9e1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -28,7 +28,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, wcid = &mvif->group_wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(&dev->mphy, control->sta, wcid, skb); } EXPORT_SYMBOL_GPL(mt76x02_tx); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index cfe8905ce73f..7845e56cb23b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -63,7 +63,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) tasklet_enable(&dev->dfs_pd.dfs_tasklet); tasklet_enable(&dev->mt76.pre_tbtt_tasklet); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 9e97204841f5..8a04a7bf25c0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -56,7 +56,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mutex_unlock(&dev->mt76.mutex); mt76x02_pre_tbtt_enable(dev, true); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(&dev->mphy); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 7ee91d946882..d9fccbeff206 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -245,9 +245,10 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb) EXPORT_SYMBOL_GPL(mt76_tx_complete_skb); void -mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, +mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb) { + struct mt76_dev *dev = phy->dev; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct mt76_queue *q; @@ -282,7 +283,7 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, dev->queue_ops->kick(dev, q); if (q->queued > q->ndesc - 8 && !q->stopped) { - ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); + ieee80211_stop_queue(phy->hw, skb_get_queue_mapping(skb)); q->stopped = true; } @@ -291,7 +292,7 @@ mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta, EXPORT_SYMBOL_GPL(mt76_tx); static struct sk_buff * -mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) +mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq, bool ps) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); struct sk_buff *skb; @@ -306,7 +307,7 @@ mt76_txq_dequeue(struct mt76_dev *dev, struct mt76_txq *mtxq, bool ps) return skb; } - skb = ieee80211_tx_dequeue(dev->hw, txq); + skb = ieee80211_tx_dequeue(phy->hw, txq); if (!skb) return NULL; @@ -335,7 +336,8 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_frame_release_type reason, bool more_data) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; struct sk_buff *last_skb = NULL; struct mt76_queue *hwq = dev->q_tx[MT_TXQ_PSD].q; int i; @@ -350,7 +352,7 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, continue; do { - skb = mt76_txq_dequeue(dev, mtxq, true); + skb = mt76_txq_dequeue(phy, mtxq, true); if (!skb) break; @@ -377,9 +379,10 @@ mt76_release_buffered_frames(struct ieee80211_hw *hw, struct ieee80211_sta *sta, EXPORT_SYMBOL_GPL(mt76_release_buffered_frames); static int -mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, +mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_sw_queue *sq, struct mt76_txq *mtxq) { + struct mt76_dev *dev = phy->dev; struct ieee80211_txq *txq = mtxq_to_txq(mtxq); enum mt76_txq_id qid = mt76_txq_get_qid(txq); struct mt76_wcid *wcid = mtxq->wcid; @@ -395,7 +398,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) return 0; - skb = mt76_txq_dequeue(dev, mtxq, false); + skb = mt76_txq_dequeue(phy, mtxq, false); if (!skb) return 0; @@ -426,7 +429,7 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, if (test_bit(MT76_RESET, &dev->state)) return -EBUSY; - skb = mt76_txq_dequeue(dev, mtxq, false); + skb = mt76_txq_dequeue(phy, mtxq, false); if (!skb) break; @@ -464,8 +467,9 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq, } static int -mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) +mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) { + struct mt76_dev *dev = phy->dev; struct mt76_sw_queue *sq = &dev->q_tx[qid]; struct mt76_queue *hwq = sq->q; struct ieee80211_txq *txq; @@ -483,7 +487,7 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) break; } - txq = ieee80211_next_txq(dev->hw, qid); + txq = ieee80211_next_txq(phy->hw, qid); if (!txq) break; @@ -505,8 +509,8 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) spin_lock_bh(&hwq->lock); } - ret += mt76_txq_send_burst(dev, sq, mtxq); - ieee80211_return_txq(dev->hw, txq, + ret += mt76_txq_send_burst(phy, sq, mtxq); + ieee80211_return_txq(phy->hw, txq, !skb_queue_empty(&mtxq->retry_q)); } spin_unlock_bh(&hwq->lock); @@ -514,8 +518,9 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum mt76_txq_id qid) return ret; } -void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid) +void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid) { + struct mt76_dev *dev = phy->dev; struct mt76_sw_queue *sq = &dev->q_tx[qid]; int len; @@ -528,21 +533,21 @@ void mt76_txq_schedule(struct mt76_dev *dev, enum mt76_txq_id qid) rcu_read_lock(); do { - ieee80211_txq_schedule_start(dev->hw, qid); - len = mt76_txq_schedule_list(dev, qid); - ieee80211_txq_schedule_end(dev->hw, qid); + ieee80211_txq_schedule_start(phy->hw, qid); + len = mt76_txq_schedule_list(phy, qid); + ieee80211_txq_schedule_end(phy->hw, qid); } while (len > 0); rcu_read_unlock(); } EXPORT_SYMBOL_GPL(mt76_txq_schedule); -void mt76_txq_schedule_all(struct mt76_dev *dev) +void mt76_txq_schedule_all(struct mt76_phy *phy) { int i; for (i = 0; i <= MT_TXQ_BK; i++) - mt76_txq_schedule(dev, i); + mt76_txq_schedule(phy, i); } EXPORT_SYMBOL_GPL(mt76_txq_schedule_all); @@ -550,7 +555,9 @@ void mt76_tx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; - mt76_txq_schedule_all(dev); + mt76_txq_schedule_all(&dev->phy); + if (dev->phy2) + mt76_txq_schedule_all(dev->phy2); } void mt76_stop_tx_queues(struct mt76_dev *dev, struct ieee80211_sta *sta, @@ -578,7 +585,8 @@ EXPORT_SYMBOL_GPL(mt76_stop_tx_queues); void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; if (!test_bit(MT76_STATE_RUNNING, &dev->state)) return; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 3b9849b59571..ea5eeaf2dd04 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -694,7 +694,7 @@ static void mt76u_tx_tasklet(unsigned long data) spin_unlock_bh(&q->lock); - mt76_txq_schedule(dev, i); + mt76_txq_schedule(&dev->phy, i); if (!test_and_set_bit(MT76_READING_STATS, &dev->state)) queue_work(dev->usb.stat_wq, &dev->usb.stat_work); From e394b5757badea65c578d0ece59e800c7bb19aa5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Oct 2019 22:57:08 +0200 Subject: [PATCH 033/168] mt76: add support for an extra wiphy in the tx status path This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt76.h | 17 +++++++++++++ drivers/net/wireless/mediatek/mt76/tx.c | 29 +++++++++++++++++++---- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index eed387b10d48..67d10099cb71 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -286,6 +286,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_tx_info tx_info = { .skb = skb, }; + struct ieee80211_hw *hw; int len, n = 0, ret = -ENOMEM; struct mt76_queue_entry e; struct mt76_txwi_cache *t; @@ -295,7 +296,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, t = mt76_get_txwi(dev); if (!t) { - ieee80211_free_txskb(dev->hw, skb); + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); return -ENOMEM; } txwi = mt76_get_txwi_ptr(dev, t); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4fd36b3e9440..604d70fd06e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -177,6 +177,9 @@ enum mt76_wcid_flags { #define MT76_N_WCIDS 128 +/* stored in ieee80211_tx_info::hw_queue */ +#define MT_TX_HW_QUEUE_EXT_PHY BIT(3) + DECLARE_EWMA(signal, 10, 8); #define MT_WCID_TX_INFO_RATE GENMASK(15, 0) @@ -793,6 +796,20 @@ u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info, int len); /* internal */ +static inline struct ieee80211_hw * +mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hw *hw = dev->phy.hw; + + if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2) + hw = dev->phy2->hw; + + info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY; + + return hw; +} + void mt76_tx_free(struct mt76_dev *dev); struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev); void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t); diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index d9fccbeff206..c993ad7ef2e3 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -109,13 +109,17 @@ void mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list) __releases(&dev->status_list.unlock) { + struct ieee80211_hw *hw; struct sk_buff *skb; spin_unlock_bh(&dev->status_list.lock); __release(&dev->status_list.unlock); - while ((skb = __skb_dequeue(list)) != NULL) - ieee80211_tx_status(dev->hw, skb); + while ((skb = __skb_dequeue(list)) != NULL) { + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_tx_status(hw, skb); + } + } EXPORT_SYMBOL_GPL(mt76_tx_status_unlock); @@ -231,10 +235,12 @@ EXPORT_SYMBOL_GPL(mt76_tx_status_check); void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb) { + struct ieee80211_hw *hw; struct sk_buff_head list; if (!skb->prev) { - ieee80211_free_txskb(dev->hw, skb); + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); return; } @@ -253,6 +259,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct mt76_queue *q; int qid = skb_get_queue_mapping(skb); + bool ext_phy = phy != &dev->phy; if (WARN_ON(qid >= MT_TXQ_PSD)) { qid = MT_TXQ_BE; @@ -276,6 +283,9 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, mt76_check_agg_ssn(mtxq, skb); } + if (ext_phy) + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + q = dev->q_tx[qid].q; spin_lock_bh(&q->lock); @@ -295,6 +305,8 @@ static struct sk_buff * mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq, bool ps) { struct ieee80211_txq *txq = mtxq_to_txq(mtxq); + struct ieee80211_tx_info *info; + bool ext_phy = phy != &phy->dev->phy; struct sk_buff *skb; skb = skb_dequeue(&mtxq->retry_q); @@ -311,6 +323,10 @@ mt76_txq_dequeue(struct mt76_phy *phy, struct mt76_txq *mtxq, bool ps) if (!skb) return NULL; + info = IEEE80211_SKB_CB(skb); + if (ext_phy) + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + return skb; } @@ -597,6 +613,7 @@ EXPORT_SYMBOL_GPL(mt76_wake_tx_queue); void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq) { + struct ieee80211_hw *hw; struct mt76_txq *mtxq; struct sk_buff *skb; @@ -605,8 +622,10 @@ void mt76_txq_remove(struct mt76_dev *dev, struct ieee80211_txq *txq) mtxq = (struct mt76_txq *)txq->drv_priv; - while ((skb = skb_dequeue(&mtxq->retry_q)) != NULL) - ieee80211_free_txskb(dev->hw, skb); + while ((skb = skb_dequeue(&mtxq->retry_q)) != NULL) { + hw = mt76_tx_status_get_hw(dev, skb); + ieee80211_free_txskb(hw, skb); + } } EXPORT_SYMBOL_GPL(mt76_txq_remove); From 426e8e413ce856825b43c7340bfd9f8d250e799b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 12 Oct 2019 17:42:00 +0200 Subject: [PATCH 034/168] mt76: add support for an extra wiphy in mt76_sta_state() This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 13 +++++++++---- drivers/net/wireless/mediatek/mt76/mt76.h | 11 +++++++++++ drivers/net/wireless/mediatek/mt76/util.h | 14 +++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 360e38527623..4a02d74da88f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -829,7 +829,7 @@ EXPORT_SYMBOL_GPL(mt76_rx_poll_complete); static int mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, bool ext_phy) { struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int ret; @@ -854,6 +854,8 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, } ewma_signal_init(&wcid->rssi); + if (ext_phy) + mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: @@ -880,7 +882,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, mt76_tx_status_check(dev, wcid, true); for (i = 0; i < ARRAY_SIZE(sta->txq); i++) mt76_txq_remove(dev, sta->txq[i]); - mt76_wcid_free(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_mask, idx); + mt76_wcid_mask_clear(dev->wcid_phy_mask, idx); } EXPORT_SYMBOL_GPL(__mt76_sta_remove); @@ -898,11 +901,13 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return mt76_sta_add(dev, vif, sta); + return mt76_sta_add(dev, vif, sta, ext_phy); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 604d70fd06e7..446a06c29014 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -504,6 +504,7 @@ struct mt76_dev { struct sk_buff_head status_list; unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; + unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG]; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; @@ -596,6 +597,16 @@ enum mt76_phy_type { #define mt76_hw(dev) (dev)->mphy.hw +static inline struct ieee80211_hw * +mt76_wcid_hw(struct mt76_dev *dev, u8 wcid) +{ + if (wcid <= MT76_N_WCIDS && + mt76_wcid_mask_test(dev->wcid_phy_mask, wcid)) + return dev->phy2->hw; + + return dev->phy.hw; +} + bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, int timeout); diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index fe3479c8e561..48a71e7479e5 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -16,8 +16,20 @@ int mt76_wcid_alloc(unsigned long *mask, int size); +static inline bool +mt76_wcid_mask_test(unsigned long *mask, int idx) +{ + return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG); +} + static inline void -mt76_wcid_free(unsigned long *mask, int idx) +mt76_wcid_mask_set(unsigned long *mask, int idx) +{ + mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG); +} + +static inline void +mt76_wcid_mask_clear(unsigned long *mask, int idx) { mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); } From 96747a51fe62eb13481a39438453262d22148fa7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 12 Oct 2019 19:46:40 +0200 Subject: [PATCH 035/168] mt76: move channel state to struct mt76_phy Add support for an extra wiphy in mt76_set_channel and mt76_get_survey This is preparation for supporting multiple wiphys per device to support the concurrent dual-band feature of MT7615D Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 71 +++++++++++-------- drivers/net/wireless/mediatek/mt76/mt76.h | 19 ++--- .../net/wireless/mediatek/mt76/mt7603/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 16 ++--- .../net/wireless/mediatek/mt76/mt7603/main.c | 8 +-- .../net/wireless/mediatek/mt76/mt7603/mcu.c | 6 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 12 ++-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 24 +++---- .../net/wireless/mediatek/mt76/mt7615/main.c | 6 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 6 +- .../wireless/mediatek/mt76/mt7615/mt7615.h | 4 +- .../wireless/mediatek/mt76/mt76x0/eeprom.c | 4 +- .../net/wireless/mediatek/mt76/mt76x0/init.c | 6 +- .../net/wireless/mediatek/mt76/mt76x0/main.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/phy.c | 16 ++--- .../net/wireless/mediatek/mt76/mt76x02_dfs.c | 12 ++-- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 18 ++--- .../net/wireless/mediatek/mt76/mt76x02_phy.h | 4 +- .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_util.c | 4 +- .../wireless/mediatek/mt76/mt76x2/eeprom.c | 4 +- .../wireless/mediatek/mt76/mt76x2/eeprom.h | 2 +- .../wireless/mediatek/mt76/mt76x2/mt76x2.h | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_init.c | 4 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_phy.c | 4 +- .../net/wireless/mediatek/mt76/mt76x2/phy.c | 20 +++--- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 4 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_phy.c | 4 +- 30 files changed, 153 insertions(+), 137 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 4a02d74da88f..4d67d8ff6f3f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -156,9 +156,9 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, void mt76_set_stream_caps(struct mt76_dev *dev, bool vht) { if (dev->cap.has_2ghz) - mt76_init_stream_cap(dev, &dev->sband_2g.sband, false); + mt76_init_stream_cap(dev, &dev->phy.sband_2g.sband, false); if (dev->cap.has_5ghz) - mt76_init_stream_cap(dev, &dev->sband_5g.sband, vht); + mt76_init_stream_cap(dev, &dev->phy.sband_5g.sband, vht); } EXPORT_SYMBOL_GPL(mt76_set_stream_caps); @@ -187,8 +187,8 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, sband->n_channels = n_chan; sband->bitrates = rates; sband->n_bitrates = n_rates; - dev->chandef.chan = &sband->channels[0]; - dev->chan_state = &msband->chan[0]; + dev->phy.chandef.chan = &sband->channels[0]; + dev->phy.chan_state = &msband->chan[0]; ht_cap = &sband->ht_cap; ht_cap->ht_supported = true; @@ -223,9 +223,9 @@ static int mt76_init_sband_2g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates) { - dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->sband_2g.sband; + dev->hw->wiphy->bands[NL80211_BAND_2GHZ] = &dev->phy.sband_2g.sband; - return mt76_init_sband(dev, &dev->sband_2g, + return mt76_init_sband(dev, &dev->phy.sband_2g, mt76_channels_2ghz, ARRAY_SIZE(mt76_channels_2ghz), rates, n_rates, false); @@ -235,9 +235,9 @@ static int mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, int n_rates, bool vht) { - dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->sband_5g.sband; + dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = &dev->phy.sband_5g.sband; - return mt76_init_sband(dev, &dev->sband_5g, + return mt76_init_sband(dev, &dev->phy.sband_5g, mt76_channels_5ghz, ARRAY_SIZE(mt76_channels_5ghz), rates, n_rates, vht); @@ -428,23 +428,32 @@ bool mt76_has_tx_pending(struct mt76_dev *dev) EXPORT_SYMBOL_GPL(mt76_has_tx_pending); static struct mt76_channel_state * -mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) +mt76_channel_state(struct mt76_phy *phy, struct ieee80211_channel *c) { struct mt76_sband *msband; int idx; if (c->band == NL80211_BAND_2GHZ) - msband = &dev->sband_2g; + msband = &phy->sband_2g; else - msband = &dev->sband_5g; + msband = &phy->sband_5g; idx = c - &msband->sband.channels[0]; return &msband->chan[idx]; } +static void +mt76_update_survey_active_time(struct mt76_phy *phy, ktime_t time) +{ + struct mt76_channel_state *state = phy->chan_state; + + state->cc_active += ktime_to_us(ktime_sub(time, + phy->survey_time)); + phy->survey_time = time; +} + void mt76_update_survey(struct mt76_dev *dev) { - struct mt76_channel_state *state = dev->chan_state; ktime_t cur_time; if (!test_bit(MT76_STATE_RUNNING, &dev->state)) @@ -454,11 +463,13 @@ void mt76_update_survey(struct mt76_dev *dev) dev->drv->update_survey(dev); cur_time = ktime_get_boottime(); - state->cc_active += ktime_to_us(ktime_sub(cur_time, - dev->survey_time)); - dev->survey_time = cur_time; + mt76_update_survey_active_time(&dev->phy, cur_time); + if (dev->phy2) + mt76_update_survey_active_time(dev->phy2, cur_time); if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) { + struct mt76_channel_state *state = dev->phy.chan_state; + spin_lock_bh(&dev->cc_lock); state->cc_bss_rx += dev->cur_cc_bss_rx; dev->cur_cc_bss_rx = 0; @@ -467,9 +478,10 @@ void mt76_update_survey(struct mt76_dev *dev) } EXPORT_SYMBOL_GPL(mt76_update_survey); -void mt76_set_channel(struct mt76_dev *dev) +void mt76_set_channel(struct mt76_phy *phy) { - struct ieee80211_hw *hw = dev->hw; + struct mt76_dev *dev = phy->dev; + struct ieee80211_hw *hw = phy->hw; struct cfg80211_chan_def *chandef = &hw->conf.chandef; bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; int timeout = HZ / 5; @@ -477,21 +489,22 @@ void mt76_set_channel(struct mt76_dev *dev) wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), timeout); mt76_update_survey(dev); - dev->chandef = *chandef; - dev->chan_state = mt76_channel_state(dev, chandef->chan); + phy->chandef = *chandef; + phy->chan_state = mt76_channel_state(phy, chandef->chan); if (!offchannel) - dev->main_chan = chandef->chan; + phy->main_chan = chandef->chan; - if (chandef->chan != dev->main_chan) - memset(dev->chan_state, 0, sizeof(*dev->chan_state)); + if (chandef->chan != phy->main_chan) + memset(phy->chan_state, 0, sizeof(*phy->chan_state)); } EXPORT_SYMBOL_GPL(mt76_set_channel); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; struct mt76_sband *sband; struct ieee80211_channel *chan; struct mt76_channel_state *state; @@ -501,10 +514,10 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, if (idx == 0 && dev->drv->update_survey) mt76_update_survey(dev); - sband = &dev->sband_2g; + sband = &phy->sband_2g; if (idx >= sband->sband.n_channels) { idx -= sband->sband.n_channels; - sband = &dev->sband_5g; + sband = &phy->sband_5g; } if (idx >= sband->sband.n_channels) { @@ -513,13 +526,13 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, } chan = &sband->sband.channels[idx]; - state = mt76_channel_state(dev, chan); + state = mt76_channel_state(phy, chan); memset(survey, 0, sizeof(*survey)); survey->channel = chan; survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; survey->filled |= dev->drv->survey_flags; - if (chan == dev->main_chan) { + if (chan == phy->main_chan) { survey->filled |= SURVEY_INFO_IN_USE; if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) @@ -1027,11 +1040,11 @@ int mt76_get_rate(struct mt76_dev *dev, int i, offset = 0, len = sband->n_bitrates; if (cck) { - if (sband == &dev->sband_5g.sband) + if (sband == &dev->phy.sband_5g.sband) return 0; idx &= ~BIT(2); /* short preamble */ - } else if (sband == &dev->sband_2g.sband) { + } else if (sband == &dev->phy.sband_2g.sband) { offset = 4; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 446a06c29014..9fde43f0f2ab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -22,6 +22,7 @@ #define MT_SKB_HEAD_LEN 128 struct mt76_dev; +struct mt76_phy; struct mt76_wcid; struct mt76_reg_pair { @@ -456,6 +457,15 @@ struct mt76_rx_status { struct mt76_phy { struct ieee80211_hw *hw; struct mt76_dev *dev; + + struct cfg80211_chan_def chandef; + struct ieee80211_channel *main_chan; + + struct mt76_channel_state *chan_state; + ktime_t survey_time; + + struct mt76_sband sband_2g; + struct mt76_sband sband_5g; }; struct mt76_dev { @@ -464,10 +474,7 @@ struct mt76_dev { struct mt76_phy *phy2; struct ieee80211_hw *hw; - struct cfg80211_chan_def chandef; - struct ieee80211_channel *main_chan; - struct mt76_channel_state *chan_state; spinlock_t lock; spinlock_t cc_lock; @@ -522,8 +529,6 @@ struct mt76_dev { int beacon_int; u8 beacon_mask; - struct mt76_sband sband_2g; - struct mt76_sband sband_5g; struct debugfs_blob_wrapper eeprom; struct debugfs_blob_wrapper otp; struct mt76_hw_cap cap; @@ -543,8 +548,6 @@ struct mt76_dev { u8 csa_complete; - ktime_t survey_time; - u32 rxfilter; union { @@ -750,7 +753,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw, enum ieee80211_frame_release_type reason, bool more_data); bool mt76_has_tx_pending(struct mt76_dev *dev); -void mt76_set_channel(struct mt76_dev *dev); +void mt76_set_channel(struct mt76_phy *phy); void mt76_update_survey(struct mt76_dev *dev); int mt76_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 0696dbf28c5b..4fb0cf8e4f75 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -573,7 +573,7 @@ int mt7603_register_device(struct mt7603_dev *dev) return ret; mt7603_init_debugfs(dev); - mt7603_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt7603_init_txpower(dev, &dev->mphy.sband_2g.sband); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 31611195251b..8aefadd6278e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -53,7 +53,7 @@ void mt7603_mac_set_timing(struct mt7603_dev *dev) int sifs; u32 val; - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) sifs = 16; else sifs = 10; @@ -456,7 +456,7 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) return; spin_lock_bh(&dev->mt76.cc_lock); - dev->mt76.chan_state->cc_tx += total_airtime; + dev->mphy.chan_state->cc_tx += total_airtime; spin_unlock_bh(&dev->mt76.cc_lock); } @@ -502,7 +502,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) memset(status, 0, sizeof(*status)); i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); - sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; + sband = (i & 1) ? &dev->mphy.sband_5g.sband : &dev->mphy.sband_2g.sband; i >>= 1; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); @@ -668,7 +668,7 @@ mt7603_mac_tx_rate_val(struct mt7603_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = dev->mphy.chandef.chan->band; u16 val; nss = 1; @@ -1156,10 +1156,10 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) + sband = &dev->mphy.sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &dev->mphy.sband_2g.sband; final_rate &= GENMASK(5, 0); final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1574,7 +1574,7 @@ void mt7603_update_channel(struct mt76_dev *mdev) struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); struct mt76_channel_state *state; - state = mdev->chan_state; + state = mdev->phy.chan_state; state->cc_busy += mt76_rr(dev, MT_MIB_STAT_CCA); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index b10bf9da3798..2df06487f7fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -15,7 +15,7 @@ mt7603_start(struct ieee80211_hw *hw) mt7603_mac_reset_counters(dev); mt7603_mac_start(dev); - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); mt7603_mac_work(&dev->mt76.mac_work.work); @@ -146,13 +146,13 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) set_bit(MT76_RESET, &dev->mt76.state); mt7603_beacon_set_timer(dev, -1, 0); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt7603_mac_stop(dev); if (def->width == NL80211_CHAN_WIDTH_40) bw = MT_BW_40; - dev->mt76.chandef = *def; + dev->mphy.chandef = *def; mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); ret = mt7603_mcu_set_channel(dev); if (ret) { @@ -190,7 +190,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt76_rr(dev, MT_MIB_STAT_PSCCA); mt7603_cca_stats_reset(dev); - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); mt7603_init_edcca(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 02b2bd60d04d..96197205fb82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -397,7 +397,7 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) u8 temp_comp_power[17]; u8 reserved; } req = { - .center_channel = dev->mt76.chandef.chan->hw_value, + .center_channel = dev->mphy.chandef.chan->hw_value, #define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n] .tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1), .temp_comp = EEP_VAL(MT_EE_NIC_CONF_1), @@ -430,7 +430,7 @@ static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) int mt7603_mcu_set_channel(struct mt7603_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; struct ieee80211_hw *hw = mt76_hw(dev); int n_chains = hweight8(dev->mt76.antenna_mask); struct { @@ -452,7 +452,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) s8 tx_power; int i, ret; - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) { + if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_40) { req.bw = MT_BW_40; if (chandef->center_freq1 > chandef->chan->center_freq) req.center_chan += 2; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 553bd4d988f7..5b12cb4d2765 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -247,7 +247,7 @@ mt7615_regd_notifier(struct wiphy *wiphy, { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7615_dev *dev = hw->priv; - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; if (request->dfs_region == dev->mt76.region) return; @@ -296,9 +296,9 @@ int mt7615_register_device(struct mt7615_dev *dev) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); - dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.vht_cap.cap |= + dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | @@ -310,8 +310,8 @@ int mt7615_register_device(struct mt7615_dev *dev) if (ret) return ret; - mt7615_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt7615_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index c77adc5d2552..83a219d21d3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -92,12 +92,12 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) } /* TODO: properly support DBDC */ - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; + status->freq = dev->mphy.chandef.chan->center_freq; + status->band = dev->mphy.chandef.chan->band; if (status->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + sband = &dev->mphy.sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &dev->mphy.sband_2g.sband; if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -319,7 +319,7 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = dev->mphy.chandef.chan->band; u16 val; nss = 1; @@ -1059,10 +1059,10 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) + sband = &dev->mphy.sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &dev->mphy.sband_2g.sband; final_rate &= MT_TX_RATE_IDX; final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1383,7 +1383,7 @@ void mt7615_update_channel(struct mt76_dev *mdev) obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_TIME5, MT_MIB_OBSSTIME_MASK); - state = mdev->chan_state; + state = mdev->phy.chan_state; state->cc_busy += busy_time; state->cc_tx += tx_time; state->cc_rx += rx_time + obss_time; @@ -1423,7 +1423,7 @@ void mt7615_mac_work(struct work_struct *work) int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int err; err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD0, @@ -1452,7 +1452,7 @@ static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int err; /* start CAC */ @@ -1479,7 +1479,7 @@ int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int err; if (dev->mt76.region == NL80211_DFS_UNSET) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index c55609c06fc4..0f9fd859b597 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -18,7 +18,7 @@ static int mt7615_start(struct ieee80211_hw *hw) mt7615_mac_reset_counters(dev); - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); @@ -155,7 +155,7 @@ static int mt7615_set_channel(struct mt7615_dev *dev) mt7615_dfs_check_channel(dev); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); ret = mt7615_mcu_set_channel(dev); if (ret) @@ -163,7 +163,7 @@ static int mt7615_set_channel(struct mt7615_dev *dev) ret = mt7615_dfs_init_radar_detector(dev); mt7615_mac_cca_stats_reset(dev); - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); mt7615_mac_reset_counters(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f229c9ce9f65..e6773d3bacfd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1159,7 +1159,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) { int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int freq = chandef->center_freq1, len, target_chains; u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = chandef->chan->band; @@ -1276,7 +1276,7 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) int mt7615_mcu_set_channel(struct mt7615_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; struct { u8 control_chan; @@ -1313,7 +1313,7 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) else req.switch_reason = CH_SWITCH_NORMAL; - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_40: req.bw = CMD_CBW_40MHZ; break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 85d865e832ad..828df9b4a53e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -221,8 +221,8 @@ static inline bool is_mt7622(struct mt76_dev *dev) static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev) { - enum nl80211_chan_width width = dev->mt76.chandef.width; - u32 freq = dev->mt76.chandef.chan->center_freq; + enum nl80211_chan_width width = dev->mphy.chandef.width; + u32 freq = dev->mphy.chandef.chan->center_freq; struct ieee80211_hw *hw = mt76_hw(dev); if (hw->conf.chandef.chan->center_freq != freq || diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index d1405528b504..9087607b621e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -109,7 +109,7 @@ static void mt76x0_set_freq_offset(struct mt76x02_dev *dev) void mt76x0_read_rx_gain(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x02_rx_freq_cal *caldata = &dev->cal.rx; s8 val, lna_5g[3], lna_2g; u16 rssi_offset; @@ -129,7 +129,7 @@ void mt76x0_read_rx_gain(struct mt76x02_dev *dev) static s8 mt76x0_get_delta(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; u8 val; if (chandef->width == NL80211_CHAN_WIDTH_80) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 388b54cded1b..57f8d56737eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -264,12 +264,12 @@ int mt76x0_register_device(struct mt76x02_dev *dev) if (dev->mt76.cap.has_5ghz) { /* overwrite unsupported features */ - mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband); - mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x0_vht_cap_mask(&dev->mphy.sband_5g.sband); + mt76x0_init_txpower(dev, &dev->mphy.sband_5g.sband); } if (dev->mt76.cap.has_2ghz) - mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband); + mt76x0_init_txpower(dev, &dev->mphy.sband_2g.sband); mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index bae99aa4d863..c2383bb48cfd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -16,7 +16,7 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) if (mt76_is_mmio(&dev->mt76)) tasklet_disable(&dev->dfs_pd.dfs_tasklet); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x0_phy_set_channel(dev, chandef); mt76x02_mac_cc_reset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 2ecd45f8af90..2502faa296fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -502,7 +502,7 @@ mt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width) static void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 val; if (chan->band == NL80211_BAND_5GHZ) @@ -543,7 +543,7 @@ static int mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi, u8 *info) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 val; val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050; @@ -696,7 +696,7 @@ mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode, s8 target_power, s8 target_pa_power, s16 ltssi) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int tssi_target = target_power << 12, tssi_slope; int tssi_offset, tssi_db, ret; u32 data; @@ -844,8 +844,8 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) struct mt76_rate_power *t = &dev->mt76.rate_power; s8 info; - mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t); - mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info); + mt76x0_get_tx_power_per_rate(dev, dev->mphy.chandef.chan, t); + mt76x0_get_power_info(dev, dev->mphy.chandef.chan, &info); mt76x02_add_rate_power_offset(t, info); mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); @@ -858,7 +858,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int is_5ghz = (chan->band == NL80211_BAND_5GHZ) ? 1 : 0; u32 val, tx_alc, reg_val; @@ -1037,7 +1037,7 @@ static void mt76x0_phy_temp_sensor(struct mt76x02_dev *dev) if (abs(val - dev->cal.temp_vco) > 20) { mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, - dev->mt76.chandef.chan->hw_value); + dev->mphy.chandef.chan->hw_value); dev->cal.temp_vco = val; } if (abs(val - dev->cal.temp) > 30) { @@ -1057,7 +1057,7 @@ static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, gain); - if ((dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) && + if ((dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) && !is_mt7630(dev)) mt76x02_phy_dfs_adjust_agc(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 5dec33ed8527..f6cb2b6490a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -307,8 +307,8 @@ static bool mt76x02_dfs_check_hw_pulse(struct mt76x02_dev *dev, pulse->period <= 100100); break; case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) { + if (dev->mphy.chandef.chan->center_freq >= 5250 && + dev->mphy.chandef.chan->center_freq <= 5350) { /* JPW53 */ if (pulse->w1 <= 130) ret = (pulse->period >= 28360 && @@ -702,7 +702,7 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) u8 i, shift; u32 data; - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_40: shift = MT_DFS_NUM_ENGINES; break; @@ -722,8 +722,8 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) radar_specs = &etsi_radar_specs[shift]; break; case NL80211_DFS_JP: - if (dev->mt76.chandef.chan->center_freq >= 5250 && - dev->mt76.chandef.chan->center_freq <= 5350) + if (dev->mphy.chandef.chan->center_freq >= 5250 && + dev->mphy.chandef.chan->center_freq <= 5350) radar_specs = &jp_w53_radar_specs[shift]; else radar_specs = &jp_w56_radar_specs[shift]; @@ -822,7 +822,7 @@ EXPORT_SYMBOL_GPL(mt76x02_phy_dfs_adjust_agc); void mt76x02_dfs_init_params(struct mt76x02_dev *dev) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &dev->mphy.chandef; if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && dev->mt76.region != NL80211_DFS_UNSET) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 4460548f346a..965c93b6009b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -200,7 +200,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = dev->mphy.chandef.chan->band; u16 val; r = &dev->mt76.hw->wiphy->bands[band]->bitrates[rate->idx]; @@ -487,17 +487,17 @@ mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev, struct mt76x02_sta *msta, first_rate |= st->pktid & MT_PKTID_RATE; mt76x02_mac_process_tx_rate(&rate[0], first_rate, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); } else if (rate[0].idx < 0) { if (!msta) return; mt76x02_mac_process_tx_rate(&rate[0], msta->wcid.tx_info, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); } mt76x02_mac_process_tx_rate(&last_rate, st->rate, - dev->mt76.chandef.chan->band); + dev->mphy.chandef.chan->band); for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { retry--; @@ -853,8 +853,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, signal = max_t(s8, signal, status->chain_signal[1]); } status->signal = signal; - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; + status->freq = dev->mphy.chandef.chan->center_freq; + status->band = dev->mphy.chandef.chan->band; status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); @@ -1018,7 +1018,7 @@ void mt76x02_update_channel(struct mt76_dev *mdev) struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); struct mt76_channel_state *state; - state = mdev->chan_state; + state = mdev->phy.chan_state; state->cc_busy += mt76_rr(dev, MT_CH_BUSY); spin_lock_bh(&dev->mt76.cc_lock); @@ -1074,7 +1074,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev) dev->ed_silent = 0; if (dev->ed_monitor) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); @@ -1184,7 +1184,7 @@ void mt76x02_mac_work(struct work_struct *work) void mt76x02_mac_cc_reset(struct mt76x02_dev *dev) { - dev->mt76.survey_time = ktime_get_boottime(); + dev->mphy.survey_time = ktime_get_boottime(); mt76_wr(dev, MT_CH_TIME_CFG, MT_CH_TIME_CFG_TIMER_EN | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h index fc2e41006a0d..1def25bf735a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h @@ -11,7 +11,7 @@ static inline int mt76x02_get_rssi_gain_thresh(struct mt76x02_dev *dev) { - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_80: return -62; case NL80211_CHAN_WIDTH_40: @@ -24,7 +24,7 @@ mt76x02_get_rssi_gain_thresh(struct mt76x02_dev *dev) static inline int mt76x02_get_low_rssi_gain_thresh(struct mt76x02_dev *dev) { - switch (dev->mt76.chandef.width) { + switch (dev->mphy.chandef.width) { case NL80211_CHAN_WIDTH_80: return -76; case NL80211_CHAN_WIDTH_40: diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 05dd531a9e1a..10466545405a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -74,7 +74,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, } else if (rate->flags & IEEE80211_TX_RC_MCS) { max_txpwr = dev->mt76.rate_power.ht[rate->idx & 0xf]; } else { - enum nl80211_band band = dev->mt76.chandef.chan->band; + enum nl80211_band band = dev->mphy.chandef.chan->band; if (band == NL80211_BAND_2GHZ) { const struct ieee80211_rate *r; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 0960fc56b672..837ba7f01f31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -188,9 +188,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) dev->slottime = 9; if (is_mt76x2(dev)) { - dev->mt76.sband_2g.sband.ht_cap.cap |= + dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= + dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mt76.chainmask = 0x202; dev->mt76.antenna_mask = 3; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index 9f91556c7f38..4a748a6f0ce2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -248,7 +248,7 @@ mt76x2_get_5g_rx_gain(struct mt76x02_dev *dev, u8 channel) void mt76x2_read_rx_gain(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; int channel = chan->hw_value; s8 lna_5g[3], lna_2g; u8 lna; @@ -455,7 +455,7 @@ EXPORT_SYMBOL_GPL(mt76x2_get_power_info); int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t) { - enum nl80211_band band = dev->mt76.chandef.chan->band; + enum nl80211_band band = dev->mphy.chandef.chan->band; u16 val, slope; u8 bounds; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h index 4dcf6518cb0d..3755632e6494 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.h @@ -53,7 +53,7 @@ mt76x2_has_ext_lna(struct mt76x02_dev *dev) { u32 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); - if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ) return val & MT_EE_NIC_CONF_1_LNA_EXT_2G; else return val & MT_EE_NIC_CONF_1_LNA_EXT_5G; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 41680c420cda..eca95b7f64d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -30,7 +30,7 @@ static inline bool is_mt7612(struct mt76x02_dev *dev) static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; return ((chan->flags & IEEE80211_CHAN_RADAR) && chan->dfs_state != NL80211_DFS_AVAILABLE); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 33fcec9179b2..bae05a088b5e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -289,8 +289,8 @@ int mt76x2_register_device(struct mt76x02_dev *dev) goto fail; mt76x02_init_debugfs(dev); - mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 7845e56cb23b..8c639cbc99ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -47,7 +47,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x2_mac_stop(dev, true); ret = mt76x2_phy_set_channel(dev, chandef); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 23f35bf8d47b..83d00bf74218 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -12,7 +12,7 @@ static bool mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; u32 flag = 0; if (!mt76x2_tssi_enabled(dev)) @@ -35,7 +35,7 @@ mt76x2_phy_tssi_init_cal(struct mt76x02_dev *dev) static void mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; if (dev->cal.channel_cal_done) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index edbab4fa7f6e..6d457c0dd699 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -136,8 +136,8 @@ mt76x2_get_min_rate_power(struct mt76_rate_power *r) void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) { - enum nl80211_chan_width width = dev->mt76.chandef.width; - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + enum nl80211_chan_width width = dev->mphy.chandef.width; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x2_tx_power_info txp; int txp_0, txp_1, delta = 0; struct mt76_rate_power t = {}; @@ -202,7 +202,7 @@ EXPORT_SYMBOL_GPL(mt76x2_configure_tx_delay); void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; struct mt76x2_tx_power_info txp; struct mt76x2_tssi_comp t = {}; @@ -252,12 +252,12 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) val = 0x1836 << 16; if (!mt76x2_has_ext_lna(dev) && - dev->mt76.chandef.width >= NL80211_CHAN_WIDTH_40) + dev->mphy.chandef.width >= NL80211_CHAN_WIDTH_40) val = 0x1e42 << 16; if (mt76x2_has_ext_lna(dev) && - dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ && - dev->mt76.chandef.width < NL80211_CHAN_WIDTH_40) + dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ && + dev->mphy.chandef.width < NL80211_CHAN_WIDTH_40) val = 0x0f36 << 16; val |= 0xf8; @@ -267,7 +267,7 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) mt76_wr(dev, MT_BBP(AGC, 9), val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); - if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) + if (dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) mt76x02_phy_dfs_adjust_agc(dev); } @@ -297,7 +297,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) return; } - if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) { + if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) { mt76_wr(dev, MT_BBP(RXO, 14), 0x00560211); val = mt76_rr(dev, MT_BBP(AGC, 26)) & ~0xf; if (low_gain == 2) @@ -315,11 +315,11 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) low_gain_delta = 14; agc_37 = 0x2121262c; - if (dev->mt76.chandef.chan->band == NL80211_BAND_2GHZ) + if (dev->mphy.chandef.chan->band == NL80211_BAND_2GHZ) agc_35 = 0x11111516; else if (low_gain == 2) agc_35 = agc_37 = 0x08080808; - else if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_80) + else if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_80) agc_35 = 0x10101014; else agc_35 = 0x11111116; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 2910068f4e79..89b04da23db9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -221,8 +221,8 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); mt76x02_init_debugfs(dev); - mt76x2_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt76x2_init_txpower(dev, &dev->mt76.sband_5g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband); + mt76x2_init_txpower(dev, &dev->mphy.sband_5g.sband); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 8a04a7bf25c0..24f2caf7bb66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -43,7 +43,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &dev->mt76.state); - mt76_set_channel(&dev->mt76); + mt76_set_channel(&dev->mphy); mt76x2_mac_stop(dev, false); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index b1381f9df992..d4d9b40ba8d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -10,7 +10,7 @@ static void mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; + struct ieee80211_channel *chan = dev->mphy.chandef.chan; bool is_5ghz = chan->band == NL80211_BAND_5GHZ; if (dev->cal.channel_cal_done) @@ -185,7 +185,7 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, struct ieee80211_channel *chan; u32 flag = 0; - chan = dev->mt76.chandef.chan; + chan = dev->mphy.chandef.chan; if (chan->band == NL80211_BAND_5GHZ) flag |= BIT(0); if (mt76x02_ext_pa_enabled(dev, chan->band)) From 5a95ca41223ed819ef3aa69562c77b6e76743f83 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 14 Oct 2019 10:57:03 +0200 Subject: [PATCH 036/168] mt76: keep a set of software tx queues per phy Allows tracking tx scheduling separately per phy Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/dma.c | 12 ++++++++++-- drivers/net/wireless/mediatek/mt76/mac80211.c | 13 ++++++++----- drivers/net/wireless/mediatek/mt76/mt76.h | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 2 +- 7 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index d2202acb8dc6..2567c5d6945f 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -30,7 +30,7 @@ int mt76_queues_read(struct seq_file *s, void *data) struct mt76_dev *dev = dev_get_drvdata(s->private); int i; - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { + for (i = 0; i < __MT_TXQ_MAX; i++) { struct mt76_sw_queue *q = &dev->q_tx[i]; if (!q->q) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 67d10099cb71..f88d017ff987 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -141,7 +141,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) struct mt76_sw_queue *sq = &dev->q_tx[qid]; struct mt76_queue *q = sq->q; struct mt76_queue_entry entry; - unsigned int n_swq_queued[4] = {}; + unsigned int n_swq_queued[8] = {}; unsigned int n_queued = 0; bool wake = false; int i, last; @@ -178,13 +178,21 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) spin_lock_bh(&q->lock); q->queued -= n_queued; - for (i = 0; i < ARRAY_SIZE(n_swq_queued); i++) { + for (i = 0; i < 4; i++) { if (!n_swq_queued[i]) continue; dev->q_tx[i].swq_queued -= n_swq_queued[i]; } + /* ext PHY */ + for (i = 0; i < 4; i++) { + if (!n_swq_queued[i]) + continue; + + dev->q_tx[__MT_TXQ_MAX + i].swq_queued -= n_swq_queued[4 + i]; + } + if (flush) mt76_dma_sync_idx(dev, q); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 4d67d8ff6f3f..aa61ebcf86a0 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -412,13 +412,16 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) } EXPORT_SYMBOL_GPL(mt76_rx); -bool mt76_has_tx_pending(struct mt76_dev *dev) +bool mt76_has_tx_pending(struct mt76_phy *phy) { + struct mt76_dev *dev = phy->dev; struct mt76_queue *q; - int i; + int i, offset; - for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { - q = dev->q_tx[i].q; + offset = __MT_TXQ_MAX * (phy != &dev->phy); + + for (i = 0; i < __MT_TXQ_MAX; i++) { + q = dev->q_tx[offset + i].q; if (q && q->queued) return true; } @@ -486,7 +489,7 @@ void mt76_set_channel(struct mt76_phy *phy) bool offchannel = hw->conf.flags & IEEE80211_CONF_OFFCHANNEL; int timeout = HZ / 5; - wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), timeout); + wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(phy), timeout); mt76_update_survey(dev); phy->chandef = *chandef; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 9fde43f0f2ab..cf1c2b455205 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -498,7 +498,7 @@ struct mt76_dev { u32 ampdu_ref; struct list_head txwi_cache; - struct mt76_sw_queue q_tx[__MT_TXQ_MAX]; + struct mt76_sw_queue q_tx[2 * __MT_TXQ_MAX]; struct mt76_queue q_rx[__MT_RXQ_MAX]; const struct mt76_queue_ops *queue_ops; int tx_dma_idx[4]; @@ -752,7 +752,7 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw, u16 tids, int nframes, enum ieee80211_frame_release_type reason, bool more_data); -bool mt76_has_tx_pending(struct mt76_dev *dev); +bool mt76_has_tx_pending(struct mt76_phy *phy); void mt76_set_channel(struct mt76_phy *phy); void mt76_update_survey(struct mt76_dev *dev); int mt76_get_survey(struct ieee80211_hw *hw, int idx, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 8aefadd6278e..588b21694ea3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1426,7 +1426,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_pse_client_reset(dev); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 6006c831c0a2..7d463f7bc87f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -476,7 +476,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) if (restart) mt76_mcu_restart(dev); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index ea5eeaf2dd04..3478cff9ab9a 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -872,7 +872,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) struct mt76_queue *q; int i, j, ret; - ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(dev), + ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy), HZ / 5); if (!ret) { dev_err(dev->dev, "timed out waiting for pending tx\n"); From 011849e0fc55d607016314e752fc837c00b7c794 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Oct 2019 12:09:22 +0200 Subject: [PATCH 037/168] mt76: move state from struct mt76_dev to mt76_phy Allows keeping per-wiphy state separate Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 16 +++++++------- drivers/net/wireless/mediatek/mt76/mt76.h | 15 +++++++++---- .../net/wireless/mediatek/mt76/mt7603/core.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mac.c | 4 ++-- .../net/wireless/mediatek/mt76/mt7603/main.c | 8 +++---- .../net/wireless/mediatek/mt76/mt7615/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 4 ++-- .../net/wireless/mediatek/mt76/mt7615/main.c | 8 +++---- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++-- .../net/wireless/mediatek/mt76/mt7615/pci.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/main.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/pci.c | 8 +++---- .../wireless/mediatek/mt76/mt76x0/pci_mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt76x0/phy.c | 10 ++++----- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 14 ++++++------ .../wireless/mediatek/mt76/mt76x0/usb_mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_dfs.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++-- .../net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 8 +++---- .../wireless/mediatek/mt76/mt76x02_usb_core.c | 2 +- .../wireless/mediatek/mt76/mt76x02_usb_mcu.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 10 ++++----- .../wireless/mediatek/mt76/mt76x2/pci_phy.c | 2 +- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_mac.c | 2 +- .../wireless/mediatek/mt76/mt76x2/usb_main.c | 10 ++++----- .../wireless/mediatek/mt76/mt76x2/usb_phy.c | 2 +- drivers/net/wireless/mediatek/mt76/tx.c | 6 ++--- drivers/net/wireless/mediatek/mt76/usb.c | 22 +++++++++---------- 34 files changed, 97 insertions(+), 90 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index aa61ebcf86a0..9d4b5acd555c 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -403,7 +403,10 @@ EXPORT_SYMBOL_GPL(mt76_free_device); void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb) { - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) { + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *phy = mt76_dev_phy(dev, status->ext_phy); + + if (!test_bit(MT76_STATE_RUNNING, &phy->state)) { dev_kfree_skb(skb); return; } @@ -459,9 +462,6 @@ void mt76_update_survey(struct mt76_dev *dev) { ktime_t cur_time; - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) - return; - if (dev->drv->update_survey) dev->drv->update_survey(dev); @@ -1063,17 +1063,17 @@ EXPORT_SYMBOL_GPL(mt76_get_rate); void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - set_bit(MT76_SCANNING, &dev->state); + set_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; - clear_bit(MT76_SCANNING, &dev->state); + clear_bit(MT76_SCANNING, &phy->state); } EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index cf1c2b455205..c6f78292b099 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -458,6 +458,8 @@ struct mt76_phy { struct ieee80211_hw *hw; struct mt76_dev *dev; + unsigned long state; + struct cfg80211_chan_def chandef; struct ieee80211_channel *main_chan; @@ -518,7 +520,6 @@ struct mt76_dev { u8 macaddr[ETH_ALEN]; u32 rev; - unsigned long state; u32 aggr_stats[32]; @@ -660,12 +661,18 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str, int mt76_eeprom_init(struct mt76_dev *dev, int len); void mt76_eeprom_override(struct mt76_dev *dev); +static inline struct mt76_phy * +mt76_dev_phy(struct mt76_dev *dev, bool phy_ext) +{ + if (phy_ext && dev->phy2) + return dev->phy2; + return &dev->phy; +} + static inline struct ieee80211_hw * mt76_phy_hw(struct mt76_dev *dev, bool phy_ext) { - if (phy_ext && dev->phy2) - return dev->phy2->hw; - return dev->phy.hw; + return mt76_dev_phy(dev, phy_ext)->hw; } static inline u8 * diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index e5af4f3389cc..693a91be070a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -17,7 +17,7 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; intr &= dev->mt76.mmio.irqmask; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 4fb0cf8e4f75..2ca07dd4db4b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -284,7 +284,7 @@ mt7603_init_hardware(struct mt7603_dev *dev) mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850); mt7603_mac_dma_start(dev); dev->rxfilter = mt76_rr(dev, MT_WF_RFCR); - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); for (i = 0; i < MT7603_WTBL_SIZE; i++) { mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE | diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 588b21694ea3..8a41bf118ed8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1389,7 +1389,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) int i; ieee80211_stop_queues(dev->mt76.hw); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); @@ -1439,7 +1439,7 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) mt7603_irq_enable(dev, mask); skip_dma_reset: - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->mt76.tx_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 2df06487f7fd..6da7caaaade1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -16,7 +16,7 @@ mt7603_start(struct ieee80211_hw *hw) mt7603_mac_reset_counters(dev); mt7603_mac_start(dev); dev->mphy.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt7603_mac_work(&dev->mt76.mac_work.work); return 0; @@ -27,7 +27,7 @@ mt7603_stop(struct ieee80211_hw *hw) { struct mt7603_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); cancel_delayed_work_sync(&dev->mt76.mac_work); mt7603_mac_stop(dev); } @@ -143,7 +143,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); mt7603_beacon_set_timer(dev, -1, 0); mt76_set_channel(&dev->mphy); @@ -176,7 +176,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt7603_mac_set_timing(dev); mt7603_mac_start(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mt76_txq_schedule_all(&dev->mphy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 5b12cb4d2765..e071cafe80e4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -123,7 +123,7 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); ret = mt7615_mcu_init(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 83a219d21d3a..727af49ca666 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -72,7 +72,7 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) bool unicast, remove_pad, insert_ccmp_hdr = false; int i, idx; - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return -EINVAL; memset(status, 0, sizeof(*status)); @@ -1485,7 +1485,7 @@ int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) if (dev->mt76.region == NL80211_DFS_UNSET) return 0; - if (test_bit(MT76_SCANNING, &dev->mt76.state)) + if (test_bit(MT76_SCANNING, &dev->mphy.state)) return 0; if (dev->dfs_state == chandef->chan->dfs_state) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 0f9fd859b597..cc5651a4441e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -19,7 +19,7 @@ static int mt7615_start(struct ieee80211_hw *hw) mt7615_mac_reset_counters(dev); dev->mphy.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); @@ -30,7 +30,7 @@ static void mt7615_stop(struct ieee80211_hw *hw) { struct mt7615_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); cancel_delayed_work_sync(&dev->mt76.mac_work); } @@ -151,7 +151,7 @@ static int mt7615_set_channel(struct mt7615_dev *dev) cancel_delayed_work_sync(&dev->mt76.mac_work); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); mt7615_dfs_check_channel(dev); @@ -168,7 +168,7 @@ static int mt7615_set_channel(struct mt7615_dev *dev) mt7615_mac_reset_counters(dev); out: - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); mt76_txq_schedule_all(&dev->mphy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index e6773d3bacfd..1aba10e6b5cb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -104,7 +104,7 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, if (wait_seq) *wait_seq = seq; - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) qid = MT_TXQ_MCU; else qid = MT_TXQ_FWDL; @@ -561,7 +561,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 1eb1eb659c3f..dd9ee80dbef7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -43,7 +43,7 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; intr &= dev->mt76.mmio.irqmask; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index c2383bb48cfd..50b3bba19ddb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -46,7 +46,7 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) { dev->mt76.txpower_conf = hw->conf.power_level * 2; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x0_phy_set_txpower(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index e2974e0ae1fc..88ff51400f8f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -20,7 +20,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -47,7 +47,7 @@ static void mt76x0e_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76x0e_stop_hw(dev); } @@ -124,7 +124,7 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) if (err < 0) return err; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); return 0; } @@ -195,7 +195,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) static void mt76x0e_cleanup(struct mt76x02_dev *dev) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); mt76x0_chip_onoff(dev, false, false); mt76x0e_stop_hw(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c index 038187b390ce..007c762c6db1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c @@ -126,7 +126,7 @@ int mt76x0e_mcu_init(struct mt76x02_dev *dev) if (err < 0) return err; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 2502faa296fd..9b1ae77b8fd2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -23,7 +23,7 @@ mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value) int ret = 0; u8 bank, reg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -ENODEV; bank = MT_RF_BANK(offset); @@ -62,7 +62,7 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset) u32 val; u8 bank, reg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -ENODEV; bank = MT_RF_BANK(offset); @@ -109,7 +109,7 @@ mt76x0_rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val) }; WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)); + &dev->mphy.state)); return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); } else { return mt76x0_rf_csr_wr(dev, offset, val); @@ -127,7 +127,7 @@ static int mt76x0_rf_rr(struct mt76x02_dev *dev, u32 offset) }; WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, - &dev->mt76.state)); + &dev->mphy.state)); ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); val = pair.value; } else { @@ -933,7 +933,7 @@ void mt76x0_phy_set_channel(struct mt76x02_dev *dev, FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), }; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); int ch_group_index, freq, freq1; u8 channel; u32 val; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 65ba9fc6ea0b..abf0a19ee70e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -71,7 +71,7 @@ static void mt76x0_init_usb_dma(struct mt76x02_dev *dev) static void mt76x0u_cleanup(struct mt76x02_dev *dev) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x0_chip_onoff(dev, false, false); mt76u_queues_deinit(&dev->mt76); } @@ -80,13 +80,13 @@ static void mt76x0u_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mt76.mac_work); mt76u_stop_tx(&dev->mt76); mt76x02u_exit_beacon_config(dev); - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return; if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000)) @@ -112,7 +112,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw) MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -192,7 +192,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) else hw->max_tx_fragments = 1; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); return 0; @@ -283,7 +283,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, static void mt76x0_disconnect(struct usb_interface *usb_intf) { struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); - bool initialized = test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + bool initialized = test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); if (!initialized) return; @@ -304,7 +304,7 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); mt76u_stop_rx(&dev->mt76); - clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); mt76x0_chip_onoff(dev, false, false); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index 888a930a5e08..45502fd4693f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -168,7 +168,7 @@ int mt76x0u_mcu_init(struct mt76x02_dev *dev) if (ret < 0) return ret; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index f6cb2b6490a9..ff6a9e4daac0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -616,7 +616,7 @@ static void mt76x02_dfs_tasklet(unsigned long arg) u32 engine_mask; int i; - if (test_bit(MT76_SCANNING, &dev->mt76.state)) + if (test_bit(MT76_SCANNING, &dev->mphy.state)) goto out; if (time_is_before_jiffies(dfs_pd->last_sw_check + diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 965c93b6009b..8a4396941ef2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -775,7 +775,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, u8 wcid; int len; - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return -EINVAL; if (rxinfo & MT_RXINFO_L2PAD) @@ -868,7 +868,7 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) u8 update = 1; bool ret; - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return; trace_mac_txstat_poll(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 7d946aa77182..37445bc7b546 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -152,7 +152,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev) int i; for (i = 0; i < 500; i++) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return false; switch (dev->bus->rr(dev, MAC_CSR0)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 7d463f7bc87f..e7ba9bf82d98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -261,7 +261,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask); @@ -402,7 +402,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) lockdep_assert_held(&dev->mt76.mutex); - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); rcu_read_lock(); ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); @@ -441,7 +441,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) int i; ieee80211_stop_queues(dev->mt76.hw); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); tasklet_disable(&dev->mt76.pre_tbtt_tasklet); tasklet_disable(&dev->mt76.tx_tasklet); @@ -496,7 +496,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) mutex_unlock(&dev->mt76.mutex); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); tasklet_enable(&dev->mt76.tx_tasklet); napi_enable(&dev->mt76.tx_napi); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index d03d3c8e296c..5cf015c1ef5d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -280,7 +280,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config); void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev) { - if (!test_bit(MT76_REMOVED, &dev->mt76.state)) + if (!test_bit(MT76_REMOVED, &dev->mphy.state)) mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index a993cd7e9948..106ff4b3e6ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -87,7 +87,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, u8 seq = 0; u32 info; - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return 0; if (wait_resp) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 837ba7f01f31..d226112494d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -602,7 +602,7 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_SCANNING, &dev->mt76.state); + clear_bit(MT76_SCANNING, &dev->mphy.state); if (dev->cal.gain_init_done) { /* Restore AGC gain and resume calibration after scanning. */ dev->cal.low_gain = -1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index bae05a088b5e..c69579e5f647 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -239,7 +239,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x02_mac_start(dev); ret = mt76x2_mcu_init(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 8c639cbc99ed..1f2db374ed51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -22,7 +22,7 @@ mt76x2_start(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, MT_WATCHDOG_TIME); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -31,7 +31,7 @@ mt76x2_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76x2_stop_hardware(dev); } @@ -45,7 +45,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) tasklet_disable(&dev->dfs_pd.dfs_tasklet); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); mt76_set_channel(&dev->mphy); @@ -57,7 +57,7 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); tasklet_enable(&dev->dfs_pd.dfs_tasklet); @@ -91,7 +91,7 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) /* convert to per-chain power for 2x2 devices */ dev->mt76.txpower_conf -= 6; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) { + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { mt76x2_phy_set_txpower(dev); mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 83d00bf74218..e996b736a690 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -118,7 +118,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) { struct ieee80211_channel *chan = chandef->chan; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); enum nl80211_band band = chan->band; u8 channel; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index b64ad816cc25..2c07063eadfe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -86,7 +86,7 @@ static void mt76x2u_disconnect(struct usb_interface *intf) struct mt76x02_dev *dev = usb_get_intfdata(intf); struct ieee80211_hw *hw = mt76_hw(dev); - set_bit(MT76_REMOVED, &dev->mt76.state); + set_bit(MT76_REMOVED, &dev->mphy.state); ieee80211_unregister_hw(hw); mt76x2u_cleanup(dev); mt76u_deinit(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 89b04da23db9..62e5e89baf23 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -218,7 +218,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) else hw->max_tx_fragments = 1; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x02_init_debugfs(dev); mt76x2_init_txpower(dev, &dev->mphy.sband_2g.sband); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index 59cbe826188a..eaa622833f85 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -98,7 +98,7 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) bool stopped = false; u32 rts_cfg; - if (test_bit(MT76_REMOVED, &dev->mt76.state)) + if (test_bit(MT76_REMOVED, &dev->mphy.state)) return -EIO; rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 24f2caf7bb66..e51b9d38221b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -17,7 +17,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT_MAC_WORK_INTERVAL); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + set_bit(MT76_STATE_RUNNING, &dev->mphy.state); return 0; } @@ -26,7 +26,7 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) { struct mt76x02_dev *dev = hw->priv; - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); mt76u_stop_tx(&dev->mt76); mt76x2u_stop_hw(dev); } @@ -41,7 +41,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x02_pre_tbtt_enable(dev, false); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &dev->mphy.state); mt76_set_channel(&dev->mphy); @@ -52,7 +52,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76x02_mac_cc_reset(dev); mt76x2_mac_resume(dev); - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &dev->mphy.state); mutex_unlock(&dev->mt76.mutex); mt76x02_pre_tbtt_enable(dev, true); @@ -83,7 +83,7 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) /* convert to per-chain power for 2x2 devices */ dev->mt76.txpower_conf -= 6; - if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x2_phy_set_txpower(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index d4d9b40ba8d9..a04a98f5ce1e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -82,7 +82,7 @@ int mt76x2u_phy_set_channel(struct mt76x02_dev *dev, FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), }; - bool scan = test_bit(MT76_SCANNING, &dev->mt76.state); + bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); struct ieee80211_channel *chan = chandef->chan; u8 channel = chan->hw_value, bw, bw_index; int ch_group_index, freq, freq1, ret; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index c993ad7ef2e3..eff522dbda34 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -442,7 +442,7 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_sw_queue *sq, if (probe) break; - if (test_bit(MT76_RESET, &dev->state)) + if (test_bit(MT76_RESET, &phy->state)) return -EBUSY; skb = mt76_txq_dequeue(phy, mtxq, false); @@ -498,7 +498,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid) if (sq->swq_queued >= 4) break; - if (test_bit(MT76_RESET, &dev->state)) { + if (test_bit(MT76_RESET, &phy->state)) { ret = -EBUSY; break; } @@ -604,7 +604,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) struct mt76_phy *phy = hw->priv; struct mt76_dev *dev = phy->dev; - if (!test_bit(MT76_STATE_RUNNING, &dev->state)) + if (!test_bit(MT76_STATE_RUNNING, &phy->state)) return; tasklet_schedule(&dev->tx_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 3478cff9ab9a..8561d1bd7e6a 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -29,13 +29,13 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, pipe = (req_type & USB_DIR_IN) ? usb_rcvctrlpipe(udev, 0) : usb_sndctrlpipe(udev, 0); for (i = 0; i < MT_VEND_REQ_MAX_RETRY; i++) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) return -EIO; ret = usb_control_msg(udev, pipe, req, req_type, val, offset, buf, len, MT_VEND_REQ_TOUT_MS); if (ret == -ENODEV) - set_bit(MT76_REMOVED, &dev->state); + set_bit(MT76_REMOVED, &dev->phy.state); if (ret >= 0 || ret == -ENODEV) return ret; usleep_range(5000, 10000); @@ -200,7 +200,7 @@ static int mt76u_wr_rp(struct mt76_dev *dev, u32 base, const struct mt76_reg_pair *data, int n) { - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) return dev->mcu_ops->mcu_wr_rp(dev, base, data, n); else return mt76u_req_wr_rp(dev, base, data, n); @@ -227,7 +227,7 @@ static int mt76u_rd_rp(struct mt76_dev *dev, u32 base, struct mt76_reg_pair *data, int n) { - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->state)) + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) return dev->mcu_ops->mcu_rd_rp(dev, base, data, n); else return mt76u_req_rd_rp(dev, base, data, n); @@ -464,7 +464,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) int len, nsgs = 1; struct sk_buff *skb; - if (!test_bit(MT76_STATE_INITIALIZED, &dev->state)) + if (!test_bit(MT76_STATE_INITIALIZED, &dev->phy.state)) return 0; len = mt76u_get_rx_entry_len(data, urb->actual_length); @@ -696,7 +696,7 @@ static void mt76u_tx_tasklet(unsigned long data) mt76_txq_schedule(&dev->phy, i); - if (!test_and_set_bit(MT76_READING_STATS, &dev->state)) + if (!test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) queue_work(dev->usb.stat_wq, &dev->usb.stat_work); if (wake) ieee80211_wake_queue(dev->hw, i); @@ -714,7 +714,7 @@ static void mt76u_tx_status_data(struct work_struct *work) dev = container_of(usb, struct mt76_dev, usb); while (true) { - if (test_bit(MT76_REMOVED, &dev->state)) + if (test_bit(MT76_REMOVED, &dev->phy.state)) break; if (!dev->drv->tx_status_data(dev, &update)) @@ -722,10 +722,10 @@ static void mt76u_tx_status_data(struct work_struct *work) count++; } - if (count && test_bit(MT76_STATE_RUNNING, &dev->state)) + if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state)) queue_work(usb->stat_wq, &usb->stat_work); else - clear_bit(MT76_READING_STATS, &dev->state); + clear_bit(MT76_READING_STATS, &dev->phy.state); } static void mt76u_complete_tx(struct urb *urb) @@ -806,7 +806,7 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { if (err == -ENODEV) - set_bit(MT76_REMOVED, &dev->state); + set_bit(MT76_REMOVED, &dev->phy.state); else dev_err(dev->dev, "tx urb submit failed:%d\n", err); @@ -905,7 +905,7 @@ void mt76u_stop_tx(struct mt76_dev *dev) } cancel_work_sync(&dev->usb.stat_work); - clear_bit(MT76_READING_STATS, &dev->state); + clear_bit(MT76_READING_STATS, &dev->phy.state); mt76_tx_status_check(dev, NULL, true); } From db7aa188623d522636cf1a0719312b0dbbdf1dc9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Oct 2019 12:31:46 +0200 Subject: [PATCH 038/168] mt76: move chainmask back to driver specific structs Nothing in the core uses it Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 - drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x02_phy.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index c6f78292b099..8aab40ebadf9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -524,7 +524,6 @@ struct mt76_dev { u32 aggr_stats[32]; u8 antenna_mask; - u16 chainmask; struct tasklet_struct pre_tbtt_tasklet; int beacon_int; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 17e277bf39e0..c8ced0ee9704 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -125,7 +125,7 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) if (!tx_mask || tx_mask > max_nss) tx_mask = max_nss; - dev->mt76.chainmask = tx_mask << 8 | rx_mask; + dev->chainmask = tx_mask << 8 | rx_mask; dev->mt76.antenna_mask = BIT(tx_mask) - 1; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 1aba10e6b5cb..3c5922d17e44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1299,7 +1299,7 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) } req = { .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), - .tx_streams = (dev->mt76.chainmask >> 8) & 0xf, + .tx_streams = (dev->chainmask >> 8) & 0xf, .rx_streams_mask = dev->mt76.antenna_mask, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 828df9b4a53e..9c27b355a445 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -85,6 +85,7 @@ struct mt7615_dev { struct mt76_phy mphy; }; + u16 chainmask; u32 vif_mask; u32 omac_mask; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 7a44ab52fca6..28572797a7a6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -80,6 +80,7 @@ struct mt76x02_dev { struct mutex phy_mutex; u16 vif_mask; + u16 chainmask; u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 8a4396941ef2..8fe21e7e0996 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -344,7 +344,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, u16 txwi_flags = 0; u8 nss; s8 txpwr_adj, max_txpwr_adj; - u8 ccmp_pn[8], nstreams = dev->mt76.chainmask & 0xf; + u8 ccmp_pn[8], nstreams = dev->chainmask & 0xf; memset(txwi, 0, sizeof(*txwi)); @@ -679,7 +679,7 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, status->rate_idx = idx; break; case MT_PHY_TYPE_VHT: { - u8 n_rxstream = dev->mt76.chainmask & 0xf; + u8 n_rxstream = dev->chainmask & 0xf; status->encoding = RX_ENC_VHT; status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx); @@ -769,7 +769,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, u16 rate = le16_to_cpu(rxwi->rate); u16 tid_sn = le16_to_cpu(rxwi->tid_sn); bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); - int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; + int pad_len = 0, nstreams = dev->chainmask & 0xf; s8 signal; u8 pn_len; u8 wcid; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index d7334267b530..aaadc15ea83c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c @@ -16,7 +16,7 @@ void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev) val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~BIT(4); - switch (dev->mt76.chainmask & 0xf) { + switch (dev->chainmask & 0xf) { case 2: val |= BIT(3); break; @@ -35,7 +35,7 @@ void mt76x02_phy_set_txdac(struct mt76x02_dev *dev) { int txpath; - txpath = (dev->mt76.chainmask >> 8) & 0xf; + txpath = (dev->chainmask >> 8) & 0xf; switch (txpath) { case 2: mt76_set(dev, MT_BBP(TXBE, 5), 0x3); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index d226112494d3..846cd75e3e2d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -192,10 +192,10 @@ void mt76x02_init_device(struct mt76x02_dev *dev) IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.chainmask = 0x202; + dev->chainmask = 0x202; dev->mt76.antenna_mask = 3; } else { - dev->mt76.chainmask = 0x101; + dev->chainmask = 0x101; dev->mt76.antenna_mask = 1; } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c index 76d8cd37d4de..9635c04ce032 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c @@ -29,7 +29,7 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, .idx = channel, .scan = scan, .bw = bw, - .chainmask = cpu_to_le16(dev->mt76.chainmask), + .chainmask = cpu_to_le16(dev->chainmask), }; /* first set the channel without the extension channel info */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 1f2db374ed51..bc0ffae7adda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -124,7 +124,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, mutex_lock(&dev->mt76.mutex); - dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101; + dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101; dev->mt76.antenna_mask = tx_ant; mt76_set_stream_caps(&dev->mt76, true); From 9e5f6dd7a5c61542c65cbb660ec77bf50700b61f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Oct 2019 12:36:16 +0200 Subject: [PATCH 039/168] mt76: move txpower_conf back to driver specific structs Nothing in the core uses it Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 4 ++-- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8aab40ebadf9..7a20f7555082 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -534,7 +534,6 @@ struct mt76_dev { struct mt76_hw_cap cap; struct mt76_rate_power rate_power; - int txpower_conf; int txpower_cur; enum nl80211_dfs_regions region; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index 50b3bba19ddb..700ae9c12f1d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -44,7 +44,7 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x0_phy_set_txpower(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 9b1ae77b8fd2..0a10d1ee7553 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -848,7 +848,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) mt76x0_get_power_info(dev, dev->mphy.chandef.chan, &info); mt76x02_add_rate_power_offset(t, info); - mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); + mt76x02_limit_rate_power(t, dev->txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 28572797a7a6..f00a9a6ee670 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -108,6 +108,7 @@ struct mt76x02_dev { struct mt76x02_calibration cal; + int txpower_conf; s8 target_power; s8 target_power_delta[2]; bool enable_tpc; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 8fe21e7e0996..098792b86b73 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -386,7 +386,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate); } - txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf, + txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->txpower_conf, max_txpwr_adj); txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 10466545405a..039f96877787 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -96,7 +96,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr, s8 max_txpwr_adj) { - txpwr = min_t(s8, txpwr, dev->mt76.txpower_conf); + txpwr = min_t(s8, txpwr, dev->txpower_conf); txpwr -= (dev->target_power + dev->target_power_delta[0]); txpwr = min_t(s8, txpwr, max_txpwr_adj); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index bc0ffae7adda..3f82b9cec89e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -86,14 +86,14 @@ mt76x2_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; /* convert to per-chain power for 2x2 devices */ - dev->mt76.txpower_conf -= 6; + dev->txpower_conf -= 6; if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) { mt76x2_phy_set_txpower(dev); - mt76x02_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf); + mt76x02_tx_set_txpwr_auto(dev, dev->txpower_conf); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 6d457c0dd699..58f28e4e3952 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -152,7 +152,7 @@ void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) mt76x2_get_rate_power(dev, &t, chan); mt76x02_add_rate_power_offset(&t, txp.target_power + delta); - mt76x02_limit_rate_power(&t, dev->mt76.txpower_conf); + mt76x02_limit_rate_power(&t, dev->txpower_conf); dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t); base_power = mt76x2_get_min_rate_power(&t); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index e51b9d38221b..746f1a8304a6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -78,10 +78,10 @@ mt76x2u_config(struct ieee80211_hw *hw, u32 changed) } if (changed & IEEE80211_CONF_CHANGE_POWER) { - dev->mt76.txpower_conf = hw->conf.power_level * 2; + dev->txpower_conf = hw->conf.power_level * 2; /* convert to per-chain power for 2x2 devices */ - dev->mt76.txpower_conf -= 6; + dev->txpower_conf -= 6; if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) mt76x2_phy_set_txpower(dev); From beaaeb6b682795a03b0357540c0c5966fc657069 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Oct 2019 12:41:48 +0200 Subject: [PATCH 040/168] mt76: move txpower and antenna mask to struct mt76_phy Adds multiple wiphy support to mt76_get_txpower Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 19 ++++++++++--------- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +++--- .../net/wireless/mediatek/mt76/mt7603/init.c | 10 +++++----- .../net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7603/mcu.c | 6 +++--- .../wireless/mediatek/mt76/mt7615/eeprom.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 4 ++-- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 6 +++--- .../net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +- .../net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++-- .../wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- .../wireless/mediatek/mt76/mt76x2/pci_phy.c | 2 +- .../net/wireless/mediatek/mt76/mt76x2/phy.c | 2 +- 14 files changed, 35 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 9d4b5acd555c..fa581ca68638 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -121,7 +121,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, bool vht) { struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; - int i, nstream = hweight8(dev->antenna_mask); + int i, nstream = hweight8(dev->phy.antenna_mask); struct ieee80211_sta_vht_cap *vht_cap; u16 mcs_map = 0; @@ -326,8 +326,8 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); - wiphy->available_antennas_tx = dev->antenna_mask; - wiphy->available_antennas_rx = dev->antenna_mask; + wiphy->available_antennas_tx = dev->phy.antenna_mask; + wiphy->available_antennas_rx = dev->phy.antenna_mask; hw->txq_data_size = sizeof(struct mt76_txq); hw->max_tx_fragments = 16; @@ -941,10 +941,10 @@ EXPORT_SYMBOL_GPL(mt76_sta_state); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { - struct mt76_dev *dev = hw->priv; - int n_chains = hweight8(dev->antenna_mask); + struct mt76_phy *phy = hw->priv; + int n_chains = hweight8(phy->antenna_mask); - *dbm = DIV_ROUND_UP(dev->txpower_cur, 2); + *dbm = DIV_ROUND_UP(phy->txpower_cur, 2); /* convert from per-chain power to combined * output power @@ -1079,11 +1079,12 @@ EXPORT_SYMBOL_GPL(mt76_sw_scan_complete); int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) { - struct mt76_dev *dev = hw->priv; + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; mutex_lock(&dev->mutex); - *tx_ant = dev->antenna_mask; - *rx_ant = dev->antenna_mask; + *tx_ant = phy->antenna_mask; + *rx_ant = phy->antenna_mask; mutex_unlock(&dev->mutex); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 7a20f7555082..73a27fe74a9e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -468,6 +468,9 @@ struct mt76_phy { struct mt76_sband sband_2g; struct mt76_sband sband_5g; + + int txpower_cur; + u8 antenna_mask; }; struct mt76_dev { @@ -523,8 +526,6 @@ struct mt76_dev { u32 aggr_stats[32]; - u8 antenna_mask; - struct tasklet_struct pre_tbtt_tasklet; int beacon_int; u8 beacon_mask; @@ -534,7 +535,6 @@ struct mt76_dev { struct mt76_hw_cap cap; struct mt76_rate_power rate_power; - int txpower_cur; enum nl80211_dfs_regions region; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 2ca07dd4db4b..af346d479258 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -113,7 +113,7 @@ mt7603_dma_sched_init(struct mt7603_dev *dev) static void mt7603_phy_init(struct mt7603_dev *dev) { - int rx_chains = dev->mt76.antenna_mask; + int rx_chains = dev->mphy.antenna_mask; int tx_chains = hweight8(rx_chains) - 1; mt76_rmw(dev, MT_WF_RMAC_RMCR, @@ -493,12 +493,12 @@ mt7603_init_txpower(struct mt7603_dev *dev, target_power += max_offset; dev->tx_power_limit = target_power; - dev->mt76.txpower_cur = target_power; + dev->mphy.txpower_cur = target_power; target_power = DIV_ROUND_UP(target_power, 2); /* add 3 dBm for 2SS devices (combined output) */ - if (dev->mt76.antenna_mask & BIT(1)) + if (dev->mphy.antenna_mask & BIT(1)) target_power += 3; for (i = 0; i < sband->n_channels; i++) { @@ -535,9 +535,9 @@ int mt7603_register_device(struct mt7603_dev *dev) (unsigned long)dev); /* Check for 7688, which only has 1SS */ - dev->mt76.antenna_mask = 3; + dev->mphy.antenna_mask = 3; if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4)) - dev->mt76.antenna_mask = 1; + dev->mphy.antenna_mask = 1; dev->slottime = 9; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 8a41bf118ed8..8cf6c430ef67 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -609,7 +609,7 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) status->rate_idx = i; - status->chains = dev->mt76.antenna_mask; + status->chains = dev->mphy.antenna_mask; status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) + dev->rssi_offset[0]; status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index 96197205fb82..bec58f567010 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -432,7 +432,7 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) { struct cfg80211_chan_def *chandef = &dev->mphy.chandef; struct ieee80211_hw *hw = mt76_hw(dev); - int n_chains = hweight8(dev->mt76.antenna_mask); + int n_chains = hweight8(dev->mphy.antenna_mask); struct { u8 control_chan; u8 center_chan; @@ -461,11 +461,11 @@ int mt7603_mcu_set_channel(struct mt7603_dev *dev) } tx_power = hw->conf.power_level * 2; - if (dev->mt76.antenna_mask == 3) + if (dev->mphy.antenna_mask == 3) tx_power -= 6; tx_power = min(tx_power, dev->tx_power_limit); - dev->mt76.txpower_cur = tx_power; + dev->mphy.txpower_cur = tx_power; for (i = 0; i < ARRAY_SIZE(req.txpower); i++) req.txpower[i] = tx_power; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index c8ced0ee9704..0c2686bbe1ba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -126,7 +126,7 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) tx_mask = max_nss; dev->chainmask = tx_mask << 8 | rx_mask; - dev->mt76.antenna_mask = BIT(tx_mask) - 1; + dev->mphy.antenna_mask = BIT(tx_mask) - 1; } int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index e071cafe80e4..f4dc756bad4b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -203,7 +203,7 @@ static void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) { - int i, n_chains = hweight8(dev->mt76.antenna_mask), target_chains; + int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 727af49ca666..581cbf52482c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -218,14 +218,14 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - status->chains = dev->mt76.antenna_mask; + status->chains = dev->mphy.antenna_mask; status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); status->signal = status->chain_signal[0]; - for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) { + for (i = 1; i < hweight8(dev->mphy.antenna_mask); i++) { if (!(status->chains & BIT(i))) continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 3c5922d17e44..04804c87463a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1158,7 +1158,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) { - int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); + int i, ret, n_chains = hweight8(dev->mphy.antenna_mask); struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int freq = chandef->center_freq1, len, target_chains; u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; @@ -1200,7 +1200,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) break; } tx_power = max_t(s8, tx_power, 0); - dev->mt76.txpower_cur = tx_power; + dev->mphy.txpower_cur = tx_power; target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < target_chains; i++) { @@ -1300,7 +1300,7 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), .tx_streams = (dev->chainmask >> 8) & 0xf, - .rx_streams_mask = dev->mt76.antenna_mask, + .rx_streams_mask = dev->mphy.antenna_mask, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 0a10d1ee7553..cc28ad03155d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -849,7 +849,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) mt76x02_add_rate_power_offset(t, info); mt76x02_limit_rate_power(t, dev->txpower_conf); - dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); + dev->mphy.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info); dev->target_power = info; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 846cd75e3e2d..e5685d9534e4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -193,10 +193,10 @@ void mt76x02_init_device(struct mt76x02_dev *dev) dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->chainmask = 0x202; - dev->mt76.antenna_mask = 3; + dev->mphy.antenna_mask = 3; } else { dev->chainmask = 0x101; - dev->mt76.antenna_mask = 1; + dev->mphy.antenna_mask = 1; } } EXPORT_SYMBOL_GPL(mt76x02_init_device); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 3f82b9cec89e..dd336f54b8ee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -125,7 +125,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, mutex_lock(&dev->mt76.mutex); dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101; - dev->mt76.antenna_mask = tx_ant; + dev->mphy.antenna_mask = tx_ant; mt76_set_stream_caps(&dev->mt76, true); mt76x2_phy_set_antenna(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index e996b736a690..8831337df23e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -74,7 +74,7 @@ void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~(BIT(4) | BIT(1)); - switch (dev->mt76.antenna_mask) { + switch (dev->mphy.antenna_mask) { case 1: /* disable mac DAC control */ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 58f28e4e3952..91ab25c7d5ba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -153,7 +153,7 @@ void mt76x2_phy_set_txpower(struct mt76x02_dev *dev) mt76x2_get_rate_power(dev, &t, chan); mt76x02_add_rate_power_offset(&t, txp.target_power + delta); mt76x02_limit_rate_power(&t, dev->txpower_conf); - dev->mt76.txpower_cur = mt76x02_get_max_rate_power(&t); + dev->mphy.txpower_cur = mt76x02_get_max_rate_power(&t); base_power = mt76x2_get_min_rate_power(&t); delta = base_power - txp.target_power; From 8af63fed3389d1ef129557704e26f55235c4f70d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Oct 2019 16:14:12 +0200 Subject: [PATCH 041/168] mt76: add multiple wiphy support to mt76_get_min_avg_rssi Allow tracking clients of both wiphys separately Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | 2 +- drivers/net/wireless/mediatek/mt76/util.c | 8 ++++++-- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 73a27fe74a9e..49289b50eacf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -793,7 +793,7 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int mt76_get_min_avg_rssi(struct mt76_dev *dev); +int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 8cf6c430ef67..ab9ac6e07159 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -1737,7 +1737,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev) mt7603_cca_stats_reset(dev); - min_signal = mt76_get_min_avg_rssi(&dev->mt76); + min_signal = mt76_get_min_avg_rssi(&dev->mt76, false); if (!min_signal) { dev->sensitivity = 0; dev->last_cca_adj = jiffies; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 581cbf52482c..38abb3dab549 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1266,7 +1266,7 @@ mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, int signal; sensitivity = ofdm ? &dev->ofdm_sensitivity : &dev->cck_sensitivity; - signal = mt76_get_min_avg_rssi(&dev->mt76); + signal = mt76_get_min_avg_rssi(&dev->mt76, false); if (!signal) { mt7615_mac_set_default_sensitivity(dev); return; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index cc28ad03155d..b56397c05218 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1069,7 +1069,7 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) u8 gain_delta; int low_gain; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 91ab25c7d5ba..ed2dcb05d614 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -280,7 +280,7 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) int low_gain; u32 val; - dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); if (!dev->cal.avg_rssi_all) dev->cal.avg_rssi_all = -75; diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 23d1e1da78b2..8c60c450125a 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -64,7 +64,7 @@ int mt76_wcid_alloc(unsigned long *mask, int size) } EXPORT_SYMBOL_GPL(mt76_wcid_alloc); -int mt76_get_min_avg_rssi(struct mt76_dev *dev) +int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) { struct mt76_wcid *wcid; int i, j, min_rssi = 0; @@ -75,14 +75,18 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { unsigned long mask = dev->wcid_mask[i]; + unsigned long phy_mask = dev->wcid_phy_mask[i]; if (!mask) continue; - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { + for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) { if (!(mask & 1)) continue; + if (!!(phy_mask & 1) != ext_phy) + continue; + wcid = rcu_dereference(dev->wcid[j]); if (!wcid) continue; From a3d01038719c656cc8fc956b952b8f94fdc84938 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 20:33:05 +0100 Subject: [PATCH 042/168] mt76: add priv pointer to struct mt76_phy Will be used for per-phy driver private data Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 49289b50eacf..5d385505d804 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -457,6 +457,7 @@ struct mt76_rx_status { struct mt76_phy { struct ieee80211_hw *hw; struct mt76_dev *dev; + void *priv; unsigned long state; From c89d362541553de8977732b8cff9bcbc6db701c1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 21:54:41 +0100 Subject: [PATCH 043/168] mt76: add function for allocating an extra wiphy Unlike the core phy, this will have extra allocated memory for a driver private struct. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 179 +++++++++++++----- drivers/net/wireless/mediatek/mt76/mt76.h | 5 + 2 files changed, 135 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index fa581ca68638..97362a0907a6 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -187,8 +187,6 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband, sband->n_channels = n_chan; sband->bitrates = rates; sband->n_bitrates = n_rates; - dev->phy.chandef.chan = &sband->channels[0]; - dev->phy.chan_state = &msband->chan[0]; ht_cap = &sband->ht_cap; ht_cap->ht_supported = true; @@ -244,9 +242,10 @@ mt76_init_sband_5g(struct mt76_dev *dev, struct ieee80211_rate *rates, } static void -mt76_check_sband(struct mt76_dev *dev, int band) +mt76_check_sband(struct mt76_phy *phy, struct mt76_sband *msband, + enum nl80211_band band) { - struct ieee80211_supported_band *sband = dev->hw->wiphy->bands[band]; + struct ieee80211_supported_band *sband = &msband->sband; bool found = false; int i; @@ -261,13 +260,133 @@ mt76_check_sband(struct mt76_dev *dev, int band) break; } - if (found) + if (found) { + phy->chandef.chan = &sband->channels[0]; + phy->chan_state = &msband->chan[0]; return; + } sband->n_channels = 0; - dev->hw->wiphy->bands[band] = NULL; + phy->hw->wiphy->bands[band] = NULL; } +static void +mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) +{ + struct wiphy *wiphy = hw->wiphy; + + SET_IEEE80211_DEV(hw, dev->dev); + SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); + + wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + + wiphy->available_antennas_tx = dev->phy.antenna_mask; + wiphy->available_antennas_rx = dev->phy.antenna_mask; + + hw->txq_data_size = sizeof(struct mt76_txq); + hw->max_tx_fragments = 16; + + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, PS_NULLFUNC_STACK); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); + ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); + ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + ieee80211_hw_set(hw, TX_AMSDU); + ieee80211_hw_set(hw, TX_FRAG_LIST); + ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, AP_LINK_PS); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); + + wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_ADHOC); +} + +struct mt76_phy * +mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + const struct ieee80211_ops *ops) +{ + struct ieee80211_hw *hw; + struct mt76_phy *phy; + unsigned int phy_size, chan_size; + unsigned int size_2g, size_5g; + void *priv; + + phy_size = ALIGN(sizeof(*phy), 8); + chan_size = sizeof(dev->phy.sband_2g.chan[0]); + size_2g = ALIGN(ARRAY_SIZE(mt76_channels_2ghz) * chan_size, 8); + size_5g = ALIGN(ARRAY_SIZE(mt76_channels_5ghz) * chan_size, 8); + + size += phy_size + size_2g + size_5g; + hw = ieee80211_alloc_hw(size, ops); + if (!hw) + return NULL; + + phy = hw->priv; + phy->dev = dev; + phy->hw = hw; + + mt76_phy_init(dev, hw); + + priv = hw->priv + phy_size; + + phy->sband_2g = dev->phy.sband_2g; + phy->sband_2g.chan = priv; + priv += size_2g; + + phy->sband_5g = dev->phy.sband_5g; + phy->sband_5g.chan = priv; + priv += size_5g; + + phy->priv = priv; + + hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband; + hw->wiphy->bands[NL80211_BAND_5GHZ] = &phy->sband_5g.sband; + + mt76_check_sband(phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(phy, &phy->sband_5g, NL80211_BAND_5GHZ); + + return phy; +} +EXPORT_SYMBOL_GPL(mt76_alloc_phy); + +int +mt76_register_phy(struct mt76_phy *phy) +{ + int ret; + + ret = ieee80211_register_hw(phy->hw); + if (ret) + return ret; + + phy->dev->phy2 = phy; + return 0; +} +EXPORT_SYMBOL_GPL(mt76_register_phy); + +void +mt76_unregister_phy(struct mt76_phy *phy) +{ + struct mt76_dev *dev = phy->dev; + + dev->phy2 = NULL; + mt76_tx_status_check(dev, NULL, true); + ieee80211_unregister_hw(phy->hw); +} +EXPORT_SYMBOL_GPL(mt76_unregister_phy); + struct mt76_dev * mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, @@ -313,49 +432,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates) { struct ieee80211_hw *hw = dev->hw; - struct wiphy *wiphy = hw->wiphy; + struct mt76_phy *phy = &dev->phy; int ret; dev_set_drvdata(dev->dev, dev); - - SET_IEEE80211_DEV(hw, dev->dev); - SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); - - wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; - - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); - - wiphy->available_antennas_tx = dev->phy.antenna_mask; - wiphy->available_antennas_rx = dev->phy.antenna_mask; - - hw->txq_data_size = sizeof(struct mt76_txq); - hw->max_tx_fragments = 16; - - ieee80211_hw_set(hw, SIGNAL_DBM); - ieee80211_hw_set(hw, PS_NULLFUNC_STACK); - ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); - ieee80211_hw_set(hw, AMPDU_AGGREGATION); - ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); - ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); - ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); - ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); - ieee80211_hw_set(hw, TX_AMSDU); - ieee80211_hw_set(hw, TX_FRAG_LIST); - ieee80211_hw_set(hw, MFP_CAPABLE); - ieee80211_hw_set(hw, AP_LINK_PS); - ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); - ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); - - wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC); + mt76_phy_init(dev, hw); if (dev->cap.has_2ghz) { ret = mt76_init_sband_2g(dev, rates, n_rates); @@ -369,9 +450,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, return ret; } - wiphy_read_of_freq_limits(dev->hw->wiphy); - mt76_check_sband(dev, NL80211_BAND_2GHZ); - mt76_check_sband(dev, NL80211_BAND_5GHZ); + wiphy_read_of_freq_limits(hw->wiphy); + mt76_check_sband(&dev->phy, &phy->sband_2g, NL80211_BAND_2GHZ); + mt76_check_sband(&dev->phy, &phy->sband_5g, NL80211_BAND_5GHZ); if (IS_ENABLED(CONFIG_MT76_LEDS)) { ret = mt76_led_init(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5d385505d804..9afae5cc837c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -651,6 +651,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); void mt76_free_device(struct mt76_dev *dev); +void mt76_unregister_phy(struct mt76_phy *phy); + +struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size, + const struct ieee80211_ops *ops); +int mt76_register_phy(struct mt76_phy *phy); struct dentry *mt76_register_debugfs(struct mt76_dev *dev); int mt76_queues_read(struct seq_file *s, void *data); From c7d2d6310969a6cfd1395d610275e391634e8bb0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 4 Nov 2019 15:16:59 +0100 Subject: [PATCH 044/168] mt76: add ext_phy field to struct mt76_wcid Will be used to determine the phy from within the driver Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + drivers/net/wireless/mediatek/mt76/mt76.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 97362a0907a6..76ae2992511a 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -953,6 +953,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, ewma_signal_init(&wcid->rssi); if (ext_phy) mt76_wcid_mask_set(dev->wcid_phy_mask, wcid->idx); + wcid->ext_phy = ext_phy; rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 9afae5cc837c..4e1aaae2164f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -200,6 +200,7 @@ struct mt76_wcid { u8 hw_key_idx; u8 sta:1; + u8 ext_phy:1; u8 rx_check_pn; u8 rx_key_pn[IEEE80211_NUM_TIDS][6]; From 30684481e6cae7df4267a5925ce816bf877fc7cf Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 6 Nov 2019 20:04:56 +0100 Subject: [PATCH 045/168] mt76: move ampdu_ref from mt76_dev to driver struct It is only used by the driver Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 - drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 1 + drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 6 +++--- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4e1aaae2164f..5b648efc43fa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -502,7 +502,6 @@ struct mt76_dev { spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; - u32 ampdu_ref; struct list_head txwi_cache; struct mt76_sw_queue q_tx[2 * __MT_TXQ_MAX]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index ab9ac6e07159..2a384fd0f088 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -531,12 +531,12 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) /* all subframes of an A-MPDU have the same timestamp */ if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; + if (!++dev->ampdu_ref) + dev->ampdu_ref++; } dev->rx_ampdu_ts = rxd[12]; - status->ampdu_ref = dev->mt76.ampdu_ref; + status->ampdu_ref = dev->ampdu_ref; } remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 63ec1fa71aba..12fd2db2df10 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -118,6 +118,7 @@ struct mt7603_dev { u32 false_cca_ofdm, false_cca_cck; unsigned long last_cca_adj; + u32 ampdu_ref; __le32 rx_ampdu_ts; u8 rssi_offset[3]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 38abb3dab549..bf9c8006eb15 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -118,12 +118,12 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) /* all subframes of an A-MPDU have the same timestamp */ if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; + if (!++dev->ampdu_ref) + dev->ampdu_ref++; } dev->rx_ampdu_ts = rxd[12]; - status->ampdu_ref = dev->mt76.ampdu_ref; + status->ampdu_ref = dev->ampdu_ref; } remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 9c27b355a445..17ec75a2bcfb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -90,6 +90,7 @@ struct mt7615_dev { u32 omac_mask; __le32 rx_ampdu_ts; + u32 ampdu_ref; struct list_head sta_poll_list; spinlock_t sta_poll_lock; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index f00a9a6ee670..ba4c14eea22d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -86,6 +86,7 @@ struct mt76x02_dev { DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); spinlock_t txstatus_fifo_lock; u32 tx_airtime; + u32 ampdu_ref; struct sk_buff *rx_head; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 098792b86b73..5b512e4ce6b8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -824,7 +824,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, if (rxinfo & MT_RXINFO_AMPDU) { status->flag |= RX_FLAG_AMPDU_DETAILS; - status->ampdu_ref = dev->mt76.ampdu_ref; + status->ampdu_ref = dev->ampdu_ref; /* * When receiving an A-MPDU subframe and RSSI info is not valid, @@ -832,8 +832,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, * are coming. The last one will have valid RSSI info */ if (rxinfo & MT_RXINFO_RSSI) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; + if (!++dev->ampdu_ref) + dev->ampdu_ref++; } } From c9619dfaf2abe20e596934925ae34637721e26bb Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Sat, 14 Dec 2019 19:22:04 +0800 Subject: [PATCH 046/168] mt76: do not overwrite max_tx_fragments if it has been set Prevent the overwriting of max_tx_fragments if it has already been set in chip-specific init routine. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 76ae2992511a..8cc09aa6fe61 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -287,7 +287,9 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) wiphy->available_antennas_rx = dev->phy.antenna_mask; hw->txq_data_size = sizeof(struct mt76_txq); - hw->max_tx_fragments = 16; + + if (!hw->max_tx_fragments) + hw->max_tx_fragments = 16; ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); From fdd2e570764c28334fcc8728ecec8e401d04294b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 15 Oct 2019 21:08:49 +0200 Subject: [PATCH 047/168] mt76: mt7615: add dual-phy support for mac80211 ops Allows them to be used by a separately registered wiphy later Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 15 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 96 ++++++++---- .../net/wireless/mediatek/mt76/mt7615/main.c | 147 +++++++++++------- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 42 +++-- .../wireless/mediatek/mt76/mt7615/mt7615.h | 47 +++++- .../net/wireless/mediatek/mt76/mt7615/regs.h | 5 +- 6 files changed, 244 insertions(+), 108 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index f4dc756bad4b..3d8bc93fa8d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -50,7 +50,7 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | MT_TMAC_CTCR0_INS_DDLMT_EN); - mt7615_mcu_set_rts_thresh(dev, 0x92b); + mt7615_mcu_set_rts_thresh(&dev->phy, 0x92b); mt7615_mac_set_scs(dev, true); mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, @@ -132,7 +132,7 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) mt7615_mcu_set_eeprom(dev); mt7615_mac_init(dev); mt7615_phy_init(dev); - mt7615_mcu_ctrl_pm_state(dev, 0); + mt7615_mcu_ctrl_pm_state(dev, 0, 0); mt7615_mcu_del_wtbl_all(dev); /* Beacon and mgmt frames should occupy wcid 0 */ @@ -246,11 +246,9 @@ mt7615_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7615_dev *dev = hw->priv; - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; - - if (request->dfs_region == dev->mt76.region) - return; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct cfg80211_chan_def *chandef = &mphy->chandef; dev->mt76.region = request->dfs_region; @@ -271,6 +269,9 @@ int mt7615_register_device(struct mt7615_dev *dev) struct wiphy *wiphy = hw->wiphy; int ret; + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index bf9c8006eb15..967388e88503 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -49,13 +49,20 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) mt76_rr(dev, MT_TX_AGG_CNT(i)); memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats)); - - /* TODO: add DBDC support */ + dev->mt76.phy.survey_time = ktime_get_boottime(); + if (dev->mt76.phy2) + dev->mt76.phy2->survey_time = ktime_get_boottime(); /* reset airtime counters */ mt76_rr(dev, MT_MIB_SDR9(0)); + mt76_rr(dev, MT_MIB_SDR9(1)); + mt76_rr(dev, MT_MIB_SDR36(0)); + mt76_rr(dev, MT_MIB_SDR36(1)); + mt76_rr(dev, MT_MIB_SDR37(0)); + mt76_rr(dev, MT_MIB_SDR37(1)); + mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } @@ -291,6 +298,7 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, static u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, + struct mt76_phy *mphy, const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) { @@ -319,11 +327,11 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mphy.chandef.chan->band; + int band = mphy->chandef.chan->band; u16 val; nss = 1; - r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; + r = &mphy->hw->wiphy->bands[band]->bitrates[rate->idx]; if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) val = r->hw_value_short; else @@ -355,6 +363,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; + struct mt76_phy *mphy = &dev->mphy; int tx_count = 8; u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; __le16 fc = hdr->frame_control; @@ -374,6 +383,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, tx_count = msta->rate_count; } + if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->mt76.phy2) + mphy = dev->mt76.phy2; + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; @@ -431,7 +443,8 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { bool stbc = info->flags & IEEE80211_TX_CTL_STBC; u8 bw; - u16 rateval = mt7615_mac_tx_rate_val(dev, rate, stbc, &bw); + u16 rateval = mt7615_mac_tx_rate_val(dev, mphy, rate, stbc, + &bw); txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); @@ -588,10 +601,12 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) rcu_read_unlock(); } -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates) { + struct mt7615_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; u32 addr = mt7615_mac_wtbl_addr(wcid); @@ -649,11 +664,12 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, } } - val[0] = mt7615_mac_tx_rate_val(dev, &rates[0], stbc, &bw); + val[0] = mt7615_mac_tx_rate_val(dev, mphy, &rates[0], stbc, &bw); bw_prev = bw; if (probe_rate) { - probe_val = mt7615_mac_tx_rate_val(dev, probe_rate, stbc, &bw); + probe_val = mt7615_mac_tx_rate_val(dev, mphy, probe_rate, + stbc, &bw); if (bw) bw_idx = 1; else @@ -662,19 +678,19 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, probe_val = val[0]; } - val[1] = mt7615_mac_tx_rate_val(dev, &rates[1], stbc, &bw); + val[1] = mt7615_mac_tx_rate_val(dev, mphy, &rates[1], stbc, &bw); if (bw_prev) { bw_idx = 3; bw_prev = bw; } - val[2] = mt7615_mac_tx_rate_val(dev, &rates[2], stbc, &bw); + val[2] = mt7615_mac_tx_rate_val(dev, mphy, &rates[2], stbc, &bw); if (bw_prev) { bw_idx = 5; bw_prev = bw; } - val[3] = mt7615_mac_tx_rate_val(dev, &rates[3], stbc, &bw); + val[3] = mt7615_mac_tx_rate_val(dev, mphy, &rates[3], stbc, &bw); if (bw_prev) bw_idx = 7; @@ -906,8 +922,13 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + struct mt7615_phy *phy = &dev->phy; + + if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2) + phy = mdev->phy2->priv; + spin_lock_bh(&dev->mt76.lock); - mt7615_mac_set_rates(dev, msta, &info->control.rates[0], + mt7615_mac_set_rates(phy, msta, &info->control.rates[0], msta->rates); msta->rate_probe = true; spin_unlock_bh(&dev->mt76.lock); @@ -962,6 +983,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, { struct ieee80211_supported_band *sband; struct mt7615_rate_set *rs; + struct mt76_phy *mphy; int first_idx = 0, last_idx; int i, idx, count; bool fixed_rate, ack_timeout; @@ -1019,7 +1041,12 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, spin_lock_bh(&dev->mt76.lock); if (sta->rate_probe) { - mt7615_mac_set_rates(dev, sta, NULL, sta->rates); + struct mt7615_phy *phy = &dev->phy; + + if (sta->wcid.ext_phy && dev->mt76.phy2) + phy = dev->mt76.phy2->priv; + + mt7615_mac_set_rates(phy, sta, NULL, sta->rates); sta->rate_probe = false; } spin_unlock_bh(&dev->mt76.lock); @@ -1059,10 +1086,14 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mphy.sband_5g.sband; + mphy = &dev->mphy; + if (sta->wcid.ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; else - sband = &dev->mphy.sband_2g.sband; + sband = &mphy->sband_2g.sband; final_rate &= MT_TX_RATE_IDX; final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1128,6 +1159,7 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) struct ieee80211_sta *sta = NULL; struct mt7615_sta *msta = NULL; struct mt76_wcid *wcid; + struct mt76_phy *mphy = &dev->mt76.phy; __le32 *txs_data = data; u32 txs; u8 wcidx; @@ -1164,8 +1196,11 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (wcidx >= MT7615_WTBL_STA || !sta) goto out; + if (wcid->ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + if (mt7615_fill_txs(dev, msta, &info, txs_data)) - ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + ieee80211_tx_status_noskb(mphy->hw, sta, &info); out: rcu_read_unlock(); @@ -1367,27 +1402,36 @@ mt7615_mac_scs_check(struct mt7615_dev *dev) mt7615_mac_set_default_sensitivity(dev); } -void mt7615_update_channel(struct mt76_dev *mdev) +static void +mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76); struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; + u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5; - /* TODO: add DBDC support */ - busy_time = mt76_get_field(dev, MT_MIB_SDR9(0), + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), MT_MIB_SDR9_BUSY_MASK); - tx_time = mt76_get_field(dev, MT_MIB_SDR36(0), + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), MT_MIB_SDR36_TXTIME_MASK); - rx_time = mt76_get_field(dev, MT_MIB_SDR37(0), + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), MT_MIB_SDR37_RXTIME_MASK); - obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_TIME5, - MT_MIB_OBSSTIME_MASK); + obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK); - state = mdev->phy.chan_state; + state = mphy->chan_state; state->cc_busy += busy_time; state->cc_tx += tx_time; state->cc_rx += rx_time + obss_time; state->cc_bss_rx += rx_time; +} + +void mt7615_update_channel(struct mt76_dev *mdev) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_phy_update_channel(&mdev->phy, 0); + if (mdev->phy2) + mt7615_phy_update_channel(mdev->phy2, 1); /* reset obss airtime */ mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index cc5651a4441e..839a6780474b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -12,26 +12,55 @@ #include #include "mt7615.h" +static bool mt7615_dev_running(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return true; + + phy = mt7615_ext_phy(dev); + + return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); +} + static int mt7615_start(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool running; + + mutex_lock(&dev->mt76.mutex); + + running = mt7615_dev_running(dev); + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (running) + goto out; mt7615_mac_reset_counters(dev); - dev->mphy.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mphy.state); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); +out: + mutex_unlock(&dev->mt76.mutex); + return 0; } static void mt7615_stop(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); - clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); - cancel_delayed_work_sync(&dev->mt76.mac_work); + mutex_lock(&dev->mt76.mutex); + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); + if (!mt7615_dev_running(dev)) + cancel_delayed_work_sync(&dev->mt76.mac_work); + + mutex_unlock(&dev->mt76.mutex); } static int get_omac_idx(enum nl80211_iftype type, u32 mask) @@ -70,8 +99,10 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt76_txq *mtxq; + bool ext_phy = phy != &dev->phy; int idx, ret = 0; mutex_lock(&dev->mt76.mutex); @@ -89,8 +120,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, } mvif->omac_idx = idx; - /* TODO: DBDC support. Use band 0 for now */ - mvif->band_idx = 0; + mvif->band_idx = ext_phy; mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; ret = mt7615_mcu_set_dev_info(dev, vif, 1); @@ -103,6 +133,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; + mvif->sta.wcid.ext_phy = mvif->band_idx; mvif->sta.wcid.hw_key_idx = -1; mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -123,7 +154,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = &mvif->sta; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); int idx = msta->wcid.idx; /* TODO: disable beacon for the bss */ @@ -144,34 +175,34 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, spin_unlock_bh(&dev->sta_poll_lock); } -static int mt7615_set_channel(struct mt7615_dev *dev) +static int mt7615_set_channel(struct mt7615_phy *phy) { + struct mt7615_dev *dev = phy->dev; int ret; cancel_delayed_work_sync(&dev->mt76.mac_work); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_RESET, &phy->mt76->state); mt7615_dfs_check_channel(dev); - mt76_set_channel(&dev->mphy); + mt76_set_channel(phy->mt76); - ret = mt7615_mcu_set_channel(dev); + ret = mt7615_mcu_set_channel(phy); if (ret) goto out; ret = mt7615_dfs_init_radar_detector(dev); mt7615_mac_cca_stats_reset(dev); - dev->mphy.survey_time = ktime_get_boottime(); mt7615_mac_reset_counters(dev); out: - clear_bit(MT76_RESET, &dev->mphy.state); + clear_bit(MT76_RESET, &phy->mt76->state); mutex_unlock(&dev->mt76.mutex); - mt76_txq_schedule_all(&dev->mphy); + mt76_txq_schedule_all(phy->mt76); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); return ret; @@ -181,7 +212,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; @@ -230,27 +261,29 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool band = phy != &dev->phy; int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { ieee80211_stop_queues(hw); - ret = mt7615_set_channel(dev); + ret = mt7615_set_channel(phy); ieee80211_wake_queues(hw); } mutex_lock(&dev->mt76.mutex); if (changed & IEEE80211_CONF_CHANGE_POWER) - ret = mt7615_mcu_set_tx_power(dev); + ret = mt7615_mcu_set_tx_power(phy); if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) - dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else - dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } mutex_unlock(&dev->mt76.mutex); @@ -263,7 +296,7 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS; @@ -275,7 +308,10 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool band = phy != &dev->phy; + u32 ctl_flags = MT_WF_RFCR1_DROP_ACK | MT_WF_RFCR1_DROP_BF_POLL | MT_WF_RFCR1_DROP_BA | @@ -285,21 +321,21 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - dev->mt76.rxfilter &= ~(_hw); \ - dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + phy->rxfilter &= ~(_hw); \ + phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) - dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); + phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | @@ -313,12 +349,12 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); if (*total_flags & FIF_CONTROL) - mt76_clear(dev, MT_WF_RFCR1, ctl_flags); + mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); else - mt76_set(dev, MT_WF_RFCR1, ctl_flags); + mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); } static void mt7615_bss_info_changed(struct ieee80211_hw *hw, @@ -326,7 +362,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); @@ -341,7 +377,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_bcn(dev, vif, info->enable_beacon); + mt7615_mcu_set_bcn(hw, vif, info->enable_beacon); } mutex_unlock(&dev->mt76.mutex); @@ -352,10 +388,10 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_bcn(dev, vif, true); + mt7615_mcu_set_bcn(hw, vif, true); mutex_unlock(&dev->mt76.mutex); } @@ -375,6 +411,8 @@ int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; + msta->wcid.ext_phy = mvif->band_idx; + mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -415,7 +453,8 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); int i; @@ -430,7 +469,7 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, break; } msta->n_rates = i; - mt7615_mac_set_rates(dev, msta, NULL, msta->rates); + mt7615_mac_set_rates(phy, msta, NULL, msta->rates); msta->rate_probe = false; spin_unlock_bh(&dev->mt76.lock); } @@ -439,7 +478,8 @@ static void mt7615_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; @@ -458,15 +498,16 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mphy, control->sta, wcid, skb); + mt76_tx(mphy, control->sta, wcid, skb); } static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_rts_thresh(dev, val); + mt7615_mcu_set_rts_thresh(phy, val); mutex_unlock(&dev->mt76.mutex); return 0; @@ -477,7 +518,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 04804c87463a..636496b8b339 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -616,8 +616,9 @@ int mt7615_mcu_init_mac(struct mt7615_dev *dev) &req, sizeof(req), true); } -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) +int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val) { + struct mt7615_dev *dev = phy->dev; struct { u8 prot_idx; u8 band; @@ -626,7 +627,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) __le32 pkt_thresh; } __packed req = { .prot_idx = 1, - .band = 0, + .band = phy != &dev->phy, .len_thresh = cpu_to_le32(val), .pkt_thresh = cpu_to_le32(0x2), }; @@ -672,7 +673,7 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, &req, sizeof(req), true); } -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter) { #define ENTER_PM_STATE 1 #define EXIT_PM_STATE 2 @@ -695,7 +696,7 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) } __packed req = { .pm_number = 5, .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = 0, + .band_idx = band, }; return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, @@ -1099,12 +1100,14 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), true); } -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en) { + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct ieee80211_mutable_offsets offs; + struct ieee80211_tx_info *info; struct req { u8 omac_idx; u8 enable; @@ -1128,7 +1131,7 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, }; struct sk_buff *skb; - skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + skb = ieee80211_beacon_get_template(hw, vif, &offs); if (!skb) return -EINVAL; @@ -1138,6 +1141,11 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, return -EINVAL; } + if (mvif->band_idx) { + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + } + mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, 0, NULL); memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); @@ -1156,14 +1164,16 @@ int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), true); } -int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) +int mt7615_mcu_set_tx_power(struct mt7615_phy *phy) { - int i, ret, n_chains = hweight8(dev->mphy.antenna_mask); - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct mt7615_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + int i, ret, n_chains = hweight8(mphy->antenna_mask); + struct cfg80211_chan_def *chandef = &mphy->chandef; int freq = chandef->center_freq1, len, target_chains; u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = chandef->chan->band; - struct ieee80211_hw *hw = mt76_hw(dev); + struct ieee80211_hw *hw = mphy->hw; struct { u8 center_chan; u8 dbdc_idx; @@ -1172,6 +1182,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) } __packed req_hdr = { .center_chan = ieee80211_frequency_to_channel(freq), .band = band, + .dbdc_idx = phy != &dev->phy, }; s8 tx_power; @@ -1200,7 +1211,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) break; } tx_power = max_t(s8, tx_power, 0); - dev->mphy.txpower_cur = tx_power; + mphy->txpower_cur = tx_power; target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < target_chains; i++) { @@ -1274,9 +1285,10 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) &req, sizeof(req), false); } -int mt7615_mcu_set_channel(struct mt7615_dev *dev) +int mt7615_mcu_set_channel(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct mt7615_dev *dev = phy->dev; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; struct { u8 control_chan; @@ -1313,7 +1325,9 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) else req.switch_reason = CH_SWITCH_NORMAL; - switch (dev->mphy.chandef.width) { + req.band_idx = phy != &dev->phy; + + switch (chandef->width) { case NL80211_CHAN_WIDTH_40: req.bw = CMD_CBW_40MHZ; break; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 17ec75a2bcfb..527408d587c7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -79,12 +79,20 @@ struct mt7615_vif { struct mt7615_sta sta; }; +struct mt7615_phy { + struct mt76_phy *mt76; + struct mt7615_dev *dev; + + u32 rxfilter; +}; + struct mt7615_dev { union { /* must be first */ struct mt76_dev mt76; struct mt76_phy mphy; }; + struct mt7615_phy phy; u16 chainmask; u32 vif_mask; u32 omac_mask; @@ -164,6 +172,33 @@ enum mt7615_rdd_cmd { RDD_RESUME_BF, }; +static inline struct mt7615_phy * +mt7615_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + +static inline struct mt7615_dev * +mt7615_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt7615_dev, mt76); +} + +static inline struct mt7615_phy * +mt7615_ext_phy(struct mt7615_dev *dev) +{ + struct mt76_phy *phy = dev->mt76.phy2; + + if (!phy) + return NULL; + + return phy->priv; +} + extern const struct ieee80211_ops mt7615_ops; extern struct pci_driver mt7615_pci_driver; @@ -182,7 +217,7 @@ int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, int en); -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -195,9 +230,9 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en); int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool en); -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, +int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en); -int mt7615_mcu_set_channel(struct mt7615_dev *dev); +int mt7615_mcu_set_channel(struct mt7615_phy *phy); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, @@ -261,10 +296,10 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); int mt7615_mcu_init_mac(struct mt7615_dev *dev); -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); +int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter); int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index); -int mt7615_mcu_set_tx_power(struct mt7615_dev *dev); +int mt7615_mcu_set_tx_power(struct mt7615_phy *phy); void mt7615_mcu_exit(struct mt7615_dev *dev); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 61a4aa9ac6e6..50da79a276f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -170,7 +170,7 @@ #define MT_WF_RMAC_BASE 0x21200 #define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) -#define MT_WF_RFCR MT_WF_RMAC(0x000) +#define MT_WF_RFCR(_band) MT_WF_RMAC((_band) ? 0x100 : 0x000) #define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) #define MT_WF_RFCR_DROP_FCSFAIL BIT(1) #define MT_WF_RFCR_DROP_VERSION BIT(3) @@ -193,7 +193,7 @@ #define MT_WF_RFCR_DROP_NDPA BIT(20) #define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) -#define MT_WF_RFCR1 MT_WF_RMAC(0x004) +#define MT_WF_RFCR1(_band) MT_WF_RMAC((_band) ? 0x104 : 0x004) #define MT_WF_RFCR1_DROP_ACK BIT(4) #define MT_WF_RFCR1_DROP_BF_POLL BIT(5) #define MT_WF_RFCR1_DROP_BA BIT(6) @@ -207,6 +207,7 @@ #define MT_WF_RMAC_MIB_AIRTIME0 MT_WF_RMAC(0x0380) #define MT_WF_RMAC_MIB_TIME5 MT_WF_RMAC(0x03d8) +#define MT_WF_RMAC_MIB_TIME6 MT_WF_RMAC(0x03dc) #define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) #define MT_WF_DMA_BASE 0x21800 From d446a20f5b0ca04cf79df617d5cebc3fb8aba904 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 26 Oct 2019 09:30:42 +0200 Subject: [PATCH 048/168] mt76: mt7615: add multiple wiphy support for smart carrier sense Use per-phy radio stats and tuning registers Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 21 ++- .../net/wireless/mediatek/mt76/mt7615/mac.c | 130 +++++++++++------- .../net/wireless/mediatek/mt76/mt7615/main.c | 2 +- .../wireless/mediatek/mt76/mt7615/mt7615.h | 11 +- .../net/wireless/mediatek/mt76/mt7615/regs.h | 9 +- 5 files changed, 110 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index f6b75f832e6a..05a0172b32ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -74,15 +74,28 @@ static const struct file_operations fops_ampdu_stat = { .release = single_release, }; +static void +mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s) +{ + struct mt7615_dev *dev = dev_get_drvdata(s->private); + bool ext_phy = phy != &dev->phy; + + if (!phy) + return; + + seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy, + phy->ofdm_sensitivity, phy->cck_sensitivity); + seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy, + phy->false_cca_ofdm, phy->false_cca_cck); +} + static int mt7615_radio_read(struct seq_file *s, void *data) { struct mt7615_dev *dev = dev_get_drvdata(s->private); - seq_printf(s, "Sensitivity: ofdm=%d cck=%d\n", - dev->ofdm_sensitivity, dev->cck_sensitivity); - seq_printf(s, "False CCA: ofdm=%d cck=%d\n", - dev->false_cca_ofdm, dev->false_cca_cck); + mt7615_radio_read_phy(&dev->phy, s); + mt7615_radio_read_phy(mt7615_ext_phy(dev), s); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 967388e88503..71b3de5c810c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1234,38 +1234,46 @@ void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) } static void -mt7615_mac_set_default_sensitivity(struct mt7615_dev *dev) +mt7615_mac_set_default_sensitivity(struct mt7615_phy *phy) { - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(0x13c)); - mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_OFDM_MASK, - MT_WF_PHY_B1_PD_OFDM(0x13c)); + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(0x92)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(0x92)); + if (!ext_phy) { + mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, + MT_WF_PHY_B0_PD_OFDM_MASK, + MT_WF_PHY_B0_PD_OFDM(0x13c)); + mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, + MT_WF_PHY_B0_PD_CCK_MASK, + MT_WF_PHY_B0_PD_CCK(0x92)); + } else { + mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, + MT_WF_PHY_B1_PD_OFDM_MASK, + MT_WF_PHY_B1_PD_OFDM(0x13c)); + mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, + MT_WF_PHY_B1_PD_CCK_MASK, + MT_WF_PHY_B1_PD_CCK(0x92)); + } - dev->ofdm_sensitivity = -98; - dev->cck_sensitivity = -110; - dev->last_cca_adj = jiffies; + phy->ofdm_sensitivity = -98; + phy->cck_sensitivity = -110; + phy->last_cca_adj = jiffies; } void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) { + struct mt7615_phy *ext_phy; + mutex_lock(&dev->mt76.mutex); if (dev->scs_en == enable) goto out; if (enable) { - /* DBDC not supported */ mt76_set(dev, MT_WF_PHY_B0_MIN_PRI_PWR, MT_WF_PHY_B0_PD_BLK); + mt76_set(dev, MT_WF_PHY_B1_MIN_PRI_PWR, + MT_WF_PHY_B1_PD_BLK); if (is_mt7622(&dev->mt76)) { mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7 << 8); mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7); @@ -1277,33 +1285,43 @@ void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) MT_WF_PHY_B1_PD_BLK); } - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(&dev->phy); + ext_phy = mt7615_ext_phy(dev); + if (ext_phy) + mt7615_mac_set_default_sensitivity(ext_phy); + dev->scs_en = enable; out: mutex_unlock(&dev->mt76.mutex); } -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev) +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy) { - mt76_clear(dev, MT_WF_PHY_R0_B0_PHYMUX_5, GENMASK(22, 20)); - mt76_set(dev, MT_WF_PHY_R0_B0_PHYMUX_5, BIT(22) | BIT(20)); + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 reg = MT_WF_PHY_R0_PHYMUX_5(ext_phy); + + mt76_clear(dev, reg, GENMASK(22, 20)); + mt76_set(dev, reg, BIT(22) | BIT(20)); } static void -mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, +mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, u32 rts_err_rate, bool ofdm) { - int false_cca = ofdm ? dev->false_cca_ofdm : dev->false_cca_cck; + struct mt7615_dev *dev = phy->dev; + int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck; + bool ext_phy = phy != &dev->phy; u16 def_th = ofdm ? -98 : -110; bool update = false; s8 *sensitivity; int signal; - sensitivity = ofdm ? &dev->ofdm_sensitivity : &dev->cck_sensitivity; - signal = mt76_get_min_avg_rssi(&dev->mt76, false); + sensitivity = ofdm ? &phy->ofdm_sensitivity : &phy->cck_sensitivity; + signal = mt76_get_min_avg_rssi(&dev->mt76, ext_phy); if (!signal) { - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(phy); return; } @@ -1338,29 +1356,37 @@ mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, u16 val; if (ofdm) { - /* DBDC not supported */ val = *sensitivity * 2 + 512; - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(val)); + if (!ext_phy) + mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, + MT_WF_PHY_B0_PD_OFDM_MASK, + MT_WF_PHY_B0_PD_OFDM(val)); + else + mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, + MT_WF_PHY_B1_PD_OFDM_MASK, + MT_WF_PHY_B1_PD_OFDM(val)); } else { val = *sensitivity + 256; - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(val)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(val)); + if (!ext_phy) + mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, + MT_WF_PHY_B0_PD_CCK_MASK, + MT_WF_PHY_B0_PD_CCK(val)); + else + mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, + MT_WF_PHY_B1_PD_CCK_MASK, + MT_WF_PHY_B1_PD_CCK(val)); } - dev->last_cca_adj = jiffies; + phy->last_cca_adj = jiffies; } } static void -mt7615_mac_scs_check(struct mt7615_dev *dev) +mt7615_mac_scs_check(struct mt7615_phy *phy) { + struct mt7615_dev *dev = phy->dev; u32 val, rts_cnt = 0, rts_retries_cnt = 0, rts_err_rate = 0; u32 mdrdy_cck, mdrdy_ofdm, pd_cck, pd_ofdm; + bool ext_phy = phy != &dev->phy; int i; if (!dev->scs_en) @@ -1369,7 +1395,7 @@ mt7615_mac_scs_check(struct mt7615_dev *dev) for (i = 0; i < 4; i++) { u32 data; - val = mt76_rr(dev, MT_MIB_MB_SDR0(i)); + val = mt76_rr(dev, MT_MIB_MB_SDR(ext_phy, i)); data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); if (data > rts_retries_cnt) { rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); @@ -1377,29 +1403,29 @@ mt7615_mac_scs_check(struct mt7615_dev *dev) } } - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS0); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS0(ext_phy)); pd_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_CCK, val); pd_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_OFDM, val); - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS5); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS5(ext_phy)); mdrdy_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_CCK, val); mdrdy_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_OFDM, val); - dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; - dev->false_cca_cck = pd_cck - mdrdy_cck; - mt7615_mac_cca_stats_reset(dev); + phy->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; + phy->false_cca_cck = pd_cck - mdrdy_cck; + mt7615_mac_cca_stats_reset(phy); if (rts_cnt + rts_retries_cnt) rts_err_rate = MT_FRAC(rts_retries_cnt, rts_cnt + rts_retries_cnt); /* cck */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, false); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, false); /* ofdm */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, true); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, true); - if (time_after(jiffies, dev->last_cca_adj + 10 * HZ)) - mt7615_mac_set_default_sensitivity(dev); + if (time_after(jiffies, phy->last_cca_adj + 10 * HZ)) + mt7615_mac_set_default_sensitivity(phy); } static void @@ -1440,6 +1466,7 @@ void mt7615_update_channel(struct mt76_dev *mdev) void mt7615_mac_work(struct work_struct *work) { struct mt7615_dev *dev; + struct mt7615_phy *ext_phy; int i, idx; dev = (struct mt7615_dev *)container_of(work, struct mt76_dev, @@ -1448,7 +1475,12 @@ void mt7615_mac_work(struct work_struct *work) mutex_lock(&dev->mt76.mutex); mt76_update_survey(&dev->mt76); if (++dev->mac_work_count == 5) { - mt7615_mac_scs_check(dev); + ext_phy = mt7615_ext_phy(dev); + + mt7615_mac_scs_check(&dev->phy); + if (ext_phy) + mt7615_mac_scs_check(ext_phy); + dev->mac_work_count = 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 839a6780474b..934eefe821e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -194,7 +194,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) goto out; ret = mt7615_dfs_init_radar_detector(dev); - mt7615_mac_cca_stats_reset(dev); + mt7615_mac_cca_stats_reset(phy); mt7615_mac_reset_counters(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 527408d587c7..88e903324f07 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -84,6 +84,11 @@ struct mt7615_phy { struct mt7615_dev *dev; u32 rxfilter; + + unsigned long last_cca_adj; + int false_cca_ofdm, false_cca_cck; + s8 ofdm_sensitivity; + s8 cck_sensitivity; }; struct mt7615_dev { @@ -112,11 +117,7 @@ struct mt7615_dev { u32 hw_pattern; int dfs_state; - int false_cca_ofdm, false_cca_cck; - unsigned long last_cca_adj; u8 mac_work_count; - s8 ofdm_sensitivity; - s8 cck_sensitivity; bool scs_en; spinlock_t token_lock; @@ -280,7 +281,7 @@ static inline void mt7615_irq_disable(struct mt7615_dev *dev, u32 mask) void mt7615_update_channel(struct mt76_dev *mdev); bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask); void mt7615_mac_reset_counters(struct mt7615_dev *dev); -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev); +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy); void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable); void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 50da79a276f8..afb1eb08462d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -84,13 +84,13 @@ #define MT_WF_PHY_WF2_RFCTRL0 MT_WF_PHY(0x1900) #define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) -#define MT_WF_PHY_R0_B0_PHYMUX_5 MT_WF_PHY(0x0614) +#define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9)) -#define MT_WF_PHY_R0_B0_PHYCTRL_STS0 MT_WF_PHY(0x020c) +#define MT_WF_PHY_R0_PHYCTRL_STS0(_phy) MT_WF_PHY(0x020c + ((_phy) << 9)) #define MT_WF_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16) #define MT_WF_PHYCTRL_STAT_PD_CCK GENMASK(15, 0) -#define MT_WF_PHY_R0_B0_PHYCTRL_STS5 MT_WF_PHY(0x0220) +#define MT_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0220 + ((_phy) << 9)) #define MT_WF_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) #define MT_WF_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) @@ -295,7 +295,8 @@ #define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs)) #define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c) -#define MT_MIB_MB_SDR0(n) MT_WF_MIB(0x100 + ((n) << 4)) +#define MT_MIB_MB_SDR(_band, n) MT_WF_MIB(0x100 + ((_band) << 9) + \ + ((n) << 4)) #define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) #define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) From f89f58c8fb6350eb029720a1b2445cc92261b82f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 11:02:38 +0100 Subject: [PATCH 049/168] mt76: mt7615: add missing register init for dual-wiphy support Initialize low-power beacon mode setting Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7615/regs.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 3d8bc93fa8d2..9dcc3b26ff33 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -13,9 +13,9 @@ static void mt7615_phy_init(struct mt7615_dev *dev) { - /* disable band 0 rf low power beacon mode */ - mt76_rmw(dev, MT_WF_PHY_WF2_RFCTRL0, MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN, - MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); + /* disable rf low power beacon mode */ + mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); + mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); } static void mt7615_mac_init(struct mt7615_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index afb1eb08462d..a805561d10c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -81,7 +81,7 @@ #define MT_WF_PHY_BASE 0x10000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) -#define MT_WF_PHY_WF2_RFCTRL0 MT_WF_PHY(0x1900) +#define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + ((n) * 0x400)) #define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) #define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9)) From d23cb96ccf71c5850b6a4ac92cd7cd973f70ca5b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 11:19:10 +0100 Subject: [PATCH 050/168] mt76: mt7615: remove useless MT_HW_RDD0/1 enum Writing 0/1 is shorter and just as clear Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 3 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 29 ++++++++----------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 5 ---- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 9dcc3b26ff33..8d80aaf9723a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -257,8 +257,7 @@ mt7615_regd_notifier(struct wiphy *wiphy, mt7615_dfs_stop_radar_detector(dev); if (request->dfs_region == NL80211_DFS_UNSET) - mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); + mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, 0, MT_RX_SEL0, 0); else mt7615_dfs_start_radar_detector(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 71b3de5c810c..8223c7fa1c65 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1502,15 +1502,13 @@ int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev) struct cfg80211_chan_def *chandef = &dev->mphy.chandef; int err; - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD0, - MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); if (err < 0) return err; if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD1, - MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); return err; } @@ -1532,20 +1530,19 @@ int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) int err; /* start CAC */ - err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, MT_HW_RDD0, - MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, 0, MT_RX_SEL0, 0); if (err < 0) return err; /* TODO: DBDC support */ - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD0); + err = mt7615_dfs_start_rdd(dev, 0); if (err < 0) return err; if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) { - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD1); + err = mt7615_dfs_start_rdd(dev, 1); if (err < 0) return err; } @@ -1572,15 +1569,13 @@ int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) return mt7615_dfs_start_radar_detector(dev); - else - return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); - } else { - err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, - MT_HW_RDD0, MT_RX_SEL0, 0); - if (err < 0) - return err; - return mt7615_dfs_stop_radar_detector(dev); + return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, 0, MT_RX_SEL0, 0); } + + err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, 0, MT_RX_SEL0, 0); + if (err < 0) + return err; + + return mt7615_dfs_stop_radar_detector(dev); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 88e903324f07..bd9014421b00 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -149,11 +149,6 @@ enum { EXT_BSSID_END }; -enum { - MT_HW_RDD0, - MT_HW_RDD1, -}; - enum { MT_RX_SEL0, MT_RX_SEL1, From 5dabdf71e94e4583a1111b6d833e00e6eef373d1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 13:11:27 +0100 Subject: [PATCH 051/168] mt76: mt7615: add multiple wiphy support to the dfs support code There are two DFS detectors on the chip. When using 160 MHz channel bandwidth (not supported in dual-wiphy mode), both are used. Otherwise, one detector is used per wiphy. Rework the code to start/stop them separately per phy and to indicate the radar event on the right phy based on the detector index Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 9 +-- .../net/wireless/mediatek/mt76/mt7615/mac.c | 67 +++++++++++-------- .../net/wireless/mediatek/mt76/mt7615/main.c | 5 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 18 ++++- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 46 +++++++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 19 ++---- 6 files changed, 109 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 8d80aaf9723a..c4dbc635c2c6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -248,6 +248,7 @@ mt7615_regd_notifier(struct wiphy *wiphy, struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt76_phy *mphy = hw->priv; + struct mt7615_phy *phy = mphy->priv; struct cfg80211_chan_def *chandef = &mphy->chandef; dev->mt76.region = request->dfs_region; @@ -255,11 +256,7 @@ mt7615_regd_notifier(struct wiphy *wiphy, if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) return; - mt7615_dfs_stop_radar_detector(dev); - if (request->dfs_region == NL80211_DFS_UNSET) - mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, 0, MT_RX_SEL0, 0); - else - mt7615_dfs_start_radar_detector(dev); + mt7615_dfs_init_radar_detector(phy); } int mt7615_register_device(struct mt7615_dev *dev) @@ -303,7 +300,7 @@ int mt7615_register_device(struct mt7615_dev *dev) IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; - dev->dfs_state = -1; + dev->phy.dfs_state = -1; ret = mt76_register_device(&dev->mt76, true, mt7615_rates, ARRAY_SIZE(mt7615_rates)); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 8223c7fa1c65..89d6a21820ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1497,19 +1497,14 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev) +static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; - int err; + struct mt7615_dev *dev = phy->dev; - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); - if (err < 0) - return err; - - if (chandef->width == NL80211_CHAN_WIDTH_160 || - chandef->width == NL80211_CHAN_WIDTH_80P80) - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); - return err; + if (phy->rdd_state & BIT(0)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + if (phy->rdd_state & BIT(1)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); } static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) @@ -1524,58 +1519,72 @@ static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) MT_RX_SEL0, 1); } -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) +static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; /* start CAC */ - err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, 0, MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); if (err < 0) return err; - /* TODO: DBDC support */ - - err = mt7615_dfs_start_rdd(dev, 0); + err = mt7615_dfs_start_rdd(dev, ext_phy); if (err < 0) return err; + phy->rdd_state |= BIT(ext_phy); + if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) { err = mt7615_dfs_start_rdd(dev, 1); if (err < 0) return err; + + phy->rdd_state |= BIT(1); } return 0; } -int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mphy.chandef; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; - if (dev->mt76.region == NL80211_DFS_UNSET) + if (dev->mt76.region == NL80211_DFS_UNSET) { + phy->dfs_state = -1; + if (phy->rdd_state) + goto stop; + + return 0; + } + + if (test_bit(MT76_SCANNING, &phy->mt76->state)) return 0; - if (test_bit(MT76_SCANNING, &dev->mphy.state)) + if (phy->dfs_state == chandef->chan->dfs_state) return 0; - if (dev->dfs_state == chandef->chan->dfs_state) - return 0; - - dev->dfs_state = chandef->chan->dfs_state; + phy->dfs_state = chandef->chan->dfs_state; if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) - return mt7615_dfs_start_radar_detector(dev); + return mt7615_dfs_start_radar_detector(phy); - return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, 0, MT_RX_SEL0, 0); + return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, + MT_RX_SEL0, 0); } - err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, 0, MT_RX_SEL0, 0); +stop: + err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, MT_RX_SEL0, 0); if (err < 0) return err; - return mt7615_dfs_stop_radar_detector(dev); + mt7615_dfs_stop_radar_detector(phy); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 934eefe821e3..35e2d258db5e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -185,15 +185,14 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &phy->mt76->state); - mt7615_dfs_check_channel(dev); - + phy->dfs_state = -1; mt76_set_channel(phy->mt76); ret = mt7615_mcu_set_channel(phy); if (ret) goto out; - ret = mt7615_dfs_init_radar_detector(dev); + ret = mt7615_dfs_init_radar_detector(phy); mt7615_mac_cca_stats_reset(phy); mt7615_mac_reset_counters(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 636496b8b339..dc0d598f5498 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -185,6 +185,21 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) ieee80211_csa_finish(vif); } +static void +mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_mcu_rdd_report *r; + + r = (struct mt7615_mcu_rdd_report *)skb->data; + + if (r->idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_radar_detected(mphy->hw); + dev->hw_pattern++; +} + static void mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) { @@ -192,8 +207,7 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) switch (rxd->ext_eid) { case MCU_EXT_EVENT_RDD_REPORT: - ieee80211_radar_detected(dev->mt76.hw); - dev->hw_pattern++; + mt7615_mcu_rx_radar_detected(dev, skb); break; case MCU_EXT_EVENT_CSA_NOTIFY: ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 1fd7dffa6eef..f4781477fc9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -60,6 +60,52 @@ struct mt7615_mcu_rxd { u8 s2d_index; }; +struct mt7615_mcu_rdd_report { + struct mt7615_mcu_rxd rxd; + + u8 idx; + u8 long_detected; + u8 constant_prf_detected; + u8 staggered_prf_detected; + u8 radar_type_idx; + u8 periodic_pulse_num; + u8 long_pulse_num; + u8 hw_pulse_num; + + u8 out_lpn; + u8 out_spn; + u8 out_crpn; + u8 out_crpw; + u8 out_crbn; + u8 out_stgpn; + u8 out_stgpw; + + u8 _rsv[2]; + + __le32 out_pri_const; + __le32 out_pri_stg[3]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } long_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } periodic_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 sc_pass; + u8 sw_reset; + } hw_pulse[32]; +}; + #define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) #define MCU_PKT_ID 0xa0 diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index bd9014421b00..3c8d96992b60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -89,6 +89,9 @@ struct mt7615_phy { int false_cca_ofdm, false_cca_cck; s8 ofdm_sensitivity; s8 cck_sensitivity; + + u8 rdd_state; + int dfs_state; }; struct mt7615_dev { @@ -115,7 +118,6 @@ struct mt7615_dev { s16 power; } radar_pattern; u32 hw_pattern; - int dfs_state; u8 mac_work_count; bool scs_en; @@ -243,8 +245,6 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val); -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev); -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); static inline bool is_mt7622(struct mt76_dev *dev) @@ -252,17 +252,6 @@ static inline bool is_mt7622(struct mt76_dev *dev) return mt76_chip(dev) == 0x7622; } -static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev) -{ - enum nl80211_chan_width width = dev->mphy.chandef.width; - u32 freq = dev->mphy.chandef.chan->center_freq; - struct ieee80211_hw *hw = mt76_hw(dev); - - if (hw->conf.chandef.chan->center_freq != freq || - hw->conf.chandef.width != width) - dev->dfs_state = -1; -} - static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); @@ -319,7 +308,7 @@ void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force); -int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev); +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_init_debugfs(struct mt7615_dev *dev); From 2bed2a3e905a736abc75c83786042b9c758514f6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 14:16:28 +0100 Subject: [PATCH 052/168] mt76: mt7615: rework chainmask handling Move chainmask to struct mt7615_phy and instead of needlessly making the format similar to values for older chips, make it refer to the actual chain bits used for the rx/tx path. This is important for multiple wiphy support, where for a secondary phy, antenna_mask will start at 0, and chainmask will start at the chain offset (bit 2) Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 7 +++++-- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 0c2686bbe1ba..78ce6d3b1654 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -125,8 +125,8 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) if (!tx_mask || tx_mask > max_nss) tx_mask = max_nss; - dev->chainmask = tx_mask << 8 | rx_mask; dev->mphy.antenna_mask = BIT(tx_mask) - 1; + dev->phy.chainmask = dev->mphy.antenna_mask; } int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index dc0d598f5498..a19c406c2231 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1304,6 +1304,7 @@ int mt7615_mcu_set_channel(struct mt7615_phy *phy) struct mt7615_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; + u8 n_chains = hweight8(phy->mt76->antenna_mask); struct { u8 control_chan; u8 center_chan; @@ -1325,8 +1326,8 @@ int mt7615_mcu_set_channel(struct mt7615_phy *phy) } req = { .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), - .tx_streams = (dev->chainmask >> 8) & 0xf, - .rx_streams_mask = dev->mphy.antenna_mask, + .tx_streams = n_chains, + .rx_streams_mask = n_chains, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; int ret; @@ -1373,6 +1374,8 @@ int mt7615_mcu_set_channel(struct mt7615_phy *phy) if (ret) return ret; + req.rx_streams_mask = phy->chainmask; + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, &req, sizeof(req), true); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 3c8d96992b60..37d3b0971292 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -90,6 +90,8 @@ struct mt7615_phy { s8 ofdm_sensitivity; s8 cck_sensitivity; + u16 chainmask; + u8 rdd_state; int dfs_state; }; @@ -101,7 +103,6 @@ struct mt7615_dev { }; struct mt7615_phy phy; - u16 chainmask; u32 vif_mask; u32 omac_mask; From 27ae72193249d7325ef72772e8f38015cfeae947 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 17:50:57 +0100 Subject: [PATCH 053/168] mt76: mt7615: add multiple wiphy support to the rx path Program the RMAC CHFREQ registers to properly indicate the band that the frames are received on. Add some sanity checks to the programmed values, because the firmware programs these registers differently Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 44 +++++++++++++------ .../net/wireless/mediatek/mt76/mt7615/main.c | 7 +++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 11 +++-- .../net/wireless/mediatek/mt76/mt7615/regs.h | 2 + 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 89d6a21820ac..886c54a91252 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -70,6 +70,8 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; __le32 *rxd = (__le32 *)skb->data; @@ -78,12 +80,29 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) u32 rxd2 = le32_to_cpu(rxd[2]); bool unicast, remove_pad, insert_ccmp_hdr = false; int i, idx; - - if (!test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) - return -EINVAL; + u8 chfreq; memset(status, 0, sizeof(*status)); + chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); + if (!(chfreq & MT_CHFREQ_VALID)) + return -EINVAL; + + if (chfreq & MT_CHFREQ_DBDC_IDX) { + mphy = dev->mt76.phy2; + if (!mphy) + return -EINVAL; + + phy = mphy->priv; + status->ext_phy = true; + } + + if ((chfreq & MT_CHFREQ_SEQ) != phy->chfreq_seq) + return -EINVAL; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); @@ -98,13 +117,12 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } - /* TODO: properly support DBDC */ - status->freq = dev->mphy.chandef.chan->center_freq; - status->band = dev->mphy.chandef.chan->band; + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; if (status->band == NL80211_BAND_5GHZ) - sband = &dev->mphy.sband_5g.sband; + sband = &mphy->sband_5g.sband; else - sband = &dev->mphy.sband_2g.sband; + sband = &mphy->sband_2g.sband; if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -124,13 +142,13 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_AMPDU_DETAILS; /* all subframes of an A-MPDU have the same timestamp */ - if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->ampdu_ref) - dev->ampdu_ref++; + if (phy->rx_ampdu_ts != rxd[12]) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; } - dev->rx_ampdu_ts = rxd[12]; + phy->rx_ampdu_ts = rxd[12]; - status->ampdu_ref = dev->ampdu_ref; + status->ampdu_ref = phy->ampdu_ref; } remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 35e2d258db5e..6b60ca80a241 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -178,6 +178,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, static int mt7615_set_channel(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int ret; cancel_delayed_work_sync(&dev->mt76.mac_work); @@ -185,6 +186,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &phy->mt76->state); + phy->chfreq_seq = (phy->chfreq_seq + 1) & MT_CHFREQ_SEQ; phy->dfs_state = -1; mt76_set_channel(phy->mt76); @@ -192,6 +194,11 @@ static int mt7615_set_channel(struct mt7615_phy *phy) if (ret) goto out; + mt76_wr(dev, MT_CHFREQ(ext_phy), + MT_CHFREQ_VALID | + (ext_phy * MT_CHFREQ_DBDC_IDX) | + phy->chfreq_seq); + ret = mt7615_dfs_init_radar_detector(phy); mt7615_mac_cca_stats_reset(phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 37d3b0971292..64c8ad64733b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -36,6 +36,10 @@ #define MT_FRAC_SCALE 12 #define MT_FRAC(val, div) (((val) << MT_FRAC_SCALE) / (div)) +#define MT_CHFREQ_VALID BIT(7) +#define MT_CHFREQ_DBDC_IDX BIT(6) +#define MT_CHFREQ_SEQ GENMASK(5, 0) + struct mt7615_vif; struct mt7615_sta; @@ -92,8 +96,12 @@ struct mt7615_phy { u16 chainmask; + u8 chfreq_seq; u8 rdd_state; int dfs_state; + + __le32 rx_ampdu_ts; + u32 ampdu_ref; }; struct mt7615_dev { @@ -106,9 +114,6 @@ struct mt7615_dev { u32 vif_mask; u32 omac_mask; - __le32 rx_ampdu_ts; - u32 ampdu_ref; - struct list_head sta_poll_list; spinlock_t sta_poll_lock; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index a805561d10c4..d0602a3b0ac1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -200,6 +200,8 @@ #define MT_WF_RFCR1_DROP_CFEND BIT(7) #define MT_WF_RFCR1_DROP_CFACK BIT(8) +#define MT_CHFREQ(_band) MT_WF_RMAC((_band) ? 0x130 : 0x030) + #define MT_WF_RMAC_MIB_TIME0 MT_WF_RMAC(0x03c4) #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) #define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) From ac3ef85cebdeb452c1f3b2069b29efc9869c6dc3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 19:06:19 +0100 Subject: [PATCH 054/168] mt76: mt7615: initialize dbdc settings on interface add Use the first two WMM slots for the primary phy and the second two for the secondary phy. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 12 +++- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 59 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.h | 13 ++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 + .../net/wireless/mediatek/mt76/mt7615/regs.h | 9 +++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 6b60ca80a241..08b8285b58ae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -121,7 +121,11 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, mvif->omac_idx = idx; mvif->band_idx = ext_phy; - mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; + if (mt7615_ext_phy(dev)) + mvif->wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) + + mvif->idx % (MT7615_MAX_WMM_SETS / 2); + else + mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; ret = mt7615_mcu_set_dev_info(dev, vif, 1); if (ret) @@ -129,6 +133,10 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->vif_mask |= BIT(mvif->idx); dev->omac_mask |= BIT(mvif->omac_idx); + phy->omac_mask |= BIT(mvif->omac_idx); + + mt7615_mcu_set_dbdc(dev); + idx = MT7615_WTBL_RESERVED - mvif->idx; INIT_LIST_HEAD(&mvif->sta.poll_list); @@ -155,6 +163,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = &mvif->sta; struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); int idx = msta->wcid.idx; /* TODO: disable beacon for the bss */ @@ -167,6 +176,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mutex_lock(&dev->mt76.mutex); dev->vif_mask &= ~BIT(mvif->idx); dev->omac_mask &= ~BIT(mvif->omac_idx); + phy->omac_mask &= ~BIT(mvif->omac_idx); mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->sta_poll_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index a19c406c2231..9b09f2e742df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -717,6 +717,65 @@ int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter) &req, sizeof(req), true); } +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) +{ + struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); + struct dbdc_entry { + u8 type; + u8 index; + u8 band; + u8 _rsv; + }; + struct { + u8 enable; + u8 num; + u8 _rsv[2]; + struct dbdc_entry entry[64]; + } req = { + .enable = !!ext_phy, + }; + int i; + + if (!ext_phy) + goto out; + +#define ADD_DBDC_ENTRY(_type, _idx, _band) \ + do { \ + req.entry[req.num].type = _type; \ + req.entry[req.num].index = _idx; \ + req.entry[req.num++].band = _band; \ + } while (0) + + for (i = 0; i < 4; i++) { + bool band = !!(ext_phy->omac_mask & BIT(i)); + + ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band); + } + + for (i = 0; i < 14; i++) { + bool band = !!(ext_phy->omac_mask & BIT(0x11 + i)); + + ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band); + } + + ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1); + + for (i = 0; i < 3; i++) + ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1); + + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1); + + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1); + +out: + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, + &req, sizeof(req), true); +} + int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index f4781477fc9b..8d057c72366a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -148,6 +148,7 @@ enum { MCU_EXT_CMD_WTBL_UPDATE = 0x32, MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, MCU_EXT_CMD_PROTECT_CTRL = 0x3e, + MCU_EXT_CMD_DBDC_CTRL = 0x45, MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, @@ -202,6 +203,18 @@ enum { DEV_INFO_MAX_NUM }; +enum { + DBDC_TYPE_WMM, + DBDC_TYPE_MGMT, + DBDC_TYPE_BSS, + DBDC_TYPE_MBSS, + DBDC_TYPE_REPEATER, + DBDC_TYPE_MU, + DBDC_TYPE_BF, + DBDC_TYPE_PTA, + __DBDC_TYPE_MAX, +}; + struct bss_info_omac { __le16 tag; __le16 len; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 64c8ad64733b..3323baa7cc0c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -88,6 +88,7 @@ struct mt7615_phy { struct mt7615_dev *dev; u32 rxfilter; + u32 omac_mask; unsigned long last_cca_adj; int false_cca_ofdm, false_cca_cck; @@ -285,6 +286,7 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd); +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); int mt7615_mcu_init_mac(struct mt7615_dev *dev); int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index d0602a3b0ac1..cece061b1108 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -121,6 +121,15 @@ #define MT_CFG_CCR_MAC_D1_2X_GC_EN BIT(30) #define MT_CFG_CCR_MAC_D0_2X_GC_EN BIT(31) +#define MT_DBDC_CTRL0 MT_WF_CFG(0x050) +#define MT_DBDC_CTRL0_OMAC_00_04 GENMASK(4, 0) +#define MT_DBDC_CTRL0_OMAC_11_1F GENMASK(19, 5) +#define MT_DBDC_CTRL0_MGMT GENMASK(21, 20) +#define MT_DBDC_CTRL0_WMM GENMASK(25, 22) +#define MT_DBDC_CTRL0_DBDC_EN BIT(31) + +#define MT_DBDC_CTRL1 MT_WF_CFG(0x054) + #define MT_WF_AGG_BASE 0x20a00 #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) From b0b5426ee7d57ddff30e35303a1db6fd8a2a9c30 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 31 Oct 2019 14:53:03 +0100 Subject: [PATCH 055/168] mt76: mt7615: move radio/mac initialization to .start/stop callbacks Run initialization per phy Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 3 --- .../net/wireless/mediatek/mt76/mt7615/main.c | 23 ++++++++++++++++++- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 6 ++--- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index c4dbc635c2c6..78bcdf90ca5e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -56,8 +56,6 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, MT_AGG_SCR_NLNAV_MID_PTEC_DIS); - mt7615_mcu_init_mac(dev); - mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); @@ -132,7 +130,6 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) mt7615_mcu_set_eeprom(dev); mt7615_mac_init(dev); mt7615_phy_init(dev); - mt7615_mcu_ctrl_pm_state(dev, 0, 0); mt7615_mcu_del_wtbl_all(dev); /* Beacon and mgmt frames should occupy wcid 0 */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 08b8285b58ae..70d665ce924f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -33,6 +33,17 @@ static int mt7615_start(struct ieee80211_hw *hw) mutex_lock(&dev->mt76.mutex); running = mt7615_dev_running(dev); + + if (!running) { + mt7615_mcu_ctrl_pm_state(dev, 0, 0); + mt7615_mcu_set_mac_enable(dev, 0, true); + } + + if (phy != &dev->phy) { + mt7615_mcu_ctrl_pm_state(dev, 1, 0); + mt7615_mcu_set_mac_enable(dev, 1, true); + } + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); if (running) @@ -57,9 +68,19 @@ static void mt7615_stop(struct ieee80211_hw *hw) mutex_lock(&dev->mt76.mutex); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); - if (!mt7615_dev_running(dev)) + + if (phy != &dev->phy) { + mt7615_mcu_ctrl_pm_state(dev, 1, 1); + mt7615_mcu_set_mac_enable(dev, 1, false); + } + + if (!mt7615_dev_running(dev)) { cancel_delayed_work_sync(&dev->mt76.mac_work); + mt7615_mcu_ctrl_pm_state(dev, 0, 1); + mt7615_mcu_set_mac_enable(dev, 0, false); + } + mutex_unlock(&dev->mt76.mutex); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 9b09f2e742df..c08a301d4a62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -615,15 +615,15 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) return ret; } -int mt7615_mcu_init_mac(struct mt7615_dev *dev) +int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable) { struct { u8 enable; u8 band; u8 rsv[2]; } __packed req = { - .enable = 1, - .band = 0, + .enable = enable, + .band = band, }; return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 3323baa7cc0c..2adf3b8a61b8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -288,7 +288,7 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); -int mt7615_mcu_init_mac(struct mt7615_dev *dev); +int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable); int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter); int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index); From 9ce2f7fa94c1c5ce3859fdfa307c3951b233b2c7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 5 Nov 2019 12:55:18 +0100 Subject: [PATCH 056/168] mt76: mt7615: select the correct tx queue for frames sent to the second phy Beacons and management frames need to explicitly select the alternate tx queues in order to be sent out on the right phy Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 13 ++++++++++--- drivers/net/wireless/mediatek/mt76/mt7615/mac.h | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 886c54a91252..4d528aa725fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -382,6 +382,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; struct mt76_phy *mphy = &dev->mphy; + bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; int tx_count = 8; u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; __le16 fc = hdr->frame_control; @@ -401,7 +402,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, tx_count = msta->rate_count; } - if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->mt76.phy2) + if (ext_phy && dev->mt76.phy2) mphy = dev->mt76.phy2; fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; @@ -412,10 +413,16 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, skb_get_queue_mapping(skb); p_fmt = MT_TX_TYPE_CT; } else if (ieee80211_is_beacon(fc)) { - q_idx = MT_LMAC_BCN0; + if (ext_phy) + q_idx = MT_LMAC_BCN1; + else + q_idx = MT_LMAC_BCN0; p_fmt = MT_TX_TYPE_FW; } else { - q_idx = MT_LMAC_ALTX0; + if (ext_phy) + q_idx = MT_LMAC_ALTX1; + else + q_idx = MT_LMAC_ALTX0; p_fmt = MT_TX_TYPE_CT; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 38695d4f92e2..8579b829778d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -126,6 +126,10 @@ enum tx_pkt_queue_idx { MT_LMAC_BMC0, MT_LMAC_BCN0, MT_LMAC_PSMP0, + MT_LMAC_ALTX1, + MT_LMAC_BMC1, + MT_LMAC_BCN1, + MT_LMAC_PSMP1, }; enum tx_port_idx { From 0f2173f093b3f62cd21eda32019b059cdcd0d11f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Oct 2019 23:27:48 +0100 Subject: [PATCH 057/168] mt76: mt7615: add support for registering a second wiphy via debugfs This is only used for testing for now. In the future it will be possible to enable the second PHY through an proper API via device tree Running: echo 1 > /sys/kernel/debug/ieee80211/phyX/mt76/dbdc will register a second wiphy (and limit the primary one to 2 spatial streams). The second wiphy will only be able to run on 5 GHz, while the primary one can operate in both bands (if supported by the device). Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 27 ++++ .../wireless/mediatek/mt76/mt7615/eeprom.c | 5 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 125 +++++++++++++++--- .../wireless/mediatek/mt76/mt7615/mt7615.h | 4 + 4 files changed, 140 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 05a0172b32ce..f75b3f66cdb4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -36,6 +36,32 @@ mt7615_scs_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get, mt7615_scs_set, "%lld\n"); +static int +mt7615_dbdc_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (val) + mt7615_register_ext_phy(dev); + else + mt7615_unregister_ext_phy(dev); + + return 0; +} + +static int +mt7615_dbdc_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = !!mt7615_ext_phy(dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get, + mt7615_dbdc_set, "%lld\n"); + static int mt7615_ampdu_stat_read(struct seq_file *file, void *data) { @@ -183,6 +209,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) mt7615_queues_acq); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("scs", 0600, dir, dev, &fops_scs); + debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 78ce6d3b1654..c295c00759af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -125,8 +125,9 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) if (!tx_mask || tx_mask > max_nss) tx_mask = max_nss; - dev->mphy.antenna_mask = BIT(tx_mask) - 1; - dev->phy.chainmask = dev->mphy.antenna_mask; + dev->chainmask = BIT(tx_mask) - 1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; } int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 78bcdf90ca5e..a14d4d978aad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -256,22 +256,10 @@ mt7615_regd_notifier(struct wiphy *wiphy, mt7615_dfs_init_radar_detector(phy); } -int mt7615_register_device(struct mt7615_dev *dev) +static void +mt7615_init_wiphy(struct ieee80211_hw *hw) { - struct ieee80211_hw *hw = mt76_hw(dev); struct wiphy *wiphy = hw->wiphy; - int ret; - - dev->phy.dev = dev; - dev->phy.mt76 = &dev->mt76.phy; - dev->mt76.phy.priv = &dev->phy; - INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); - - ret = mt7615_init_hardware(dev); - if (ret) - return ret; hw->queues = 4; hw->max_rates = 3; @@ -290,13 +278,113 @@ int mt7615_register_device(struct mt7615_dev *dev) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; +} + +static void +mt7615_cap_dbdc_enable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap &= + ~(IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + if (dev->chainmask == 0xf) + dev->mphy.antenna_mask = dev->chainmask >> 2; + else + dev->mphy.antenna_mask = dev->chainmask >> 1; + dev->phy.chainmask = dev->mphy.antenna_mask; + mt76_set_stream_caps(&dev->mt76, true); +} + +static void +mt7615_cap_dbdc_disable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.chainmask = dev->chainmask; + mt76_set_stream_caps(&dev->mt76, true); +} + +int mt7615_register_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return -EINVAL; + + if (phy) + return 0; + + mt7615_cap_dbdc_enable(dev); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7615_init_wiphy(mphy->hw); + + /* + * Make the secondary PHY MAC address local without overlapping with + * the usual MAC address allocation scheme on multiple virtual interfaces + */ + mphy->hw->wiphy->perm_addr[0] |= 2; + mphy->hw->wiphy->perm_addr[0] ^= BIT(7); + + /* second phy can only handle 5 GHz */ + mphy->sband_2g.sband.n_channels = 0; + mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + + ret = mt76_register_phy(mphy); + if (ret) + ieee80211_free_hw(mphy->hw); + + return ret; +} + +void mt7615_unregister_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = dev->mt76.phy2; + + if (!phy) + return; + + mt7615_cap_dbdc_disable(dev); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +} + + +int mt7615_register_device(struct mt7615_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + int ret; + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); + + ret = mt7615_init_hardware(dev); + if (ret) + return ret; + + mt7615_init_wiphy(hw); dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; dev->mphy.sband_5g.sband.vht_cap.cap |= - IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; ret = mt76_register_device(&dev->mt76, true, mt7615_rates, @@ -307,8 +395,6 @@ int mt7615_register_device(struct mt7615_dev *dev) mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); - hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; - return mt7615_init_debugfs(dev); } @@ -317,6 +403,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev) struct mt76_txwi_cache *txwi; int id; + mt7615_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); mt7615_mcu_exit(dev); mt7615_dma_cleanup(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 2adf3b8a61b8..32f23f5fdd58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -115,6 +115,8 @@ struct mt7615_dev { u32 vif_mask; u32 omac_mask; + u16 chainmask; + struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -211,6 +213,8 @@ u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); +int mt7615_register_ext_phy(struct mt7615_dev *dev); +void mt7615_unregister_ext_phy(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, struct ieee80211_channel *chan, From f0305d182c020d8c6300af461a5b606316b096e8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 6 Nov 2019 20:18:28 +0100 Subject: [PATCH 058/168] mt76: mt7615: update beacon contents on BSS_CHANGED_BEACON Beacon changes need to be sent to the firmware, otherwise it will keep sending stale data Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 70d665ce924f..79f32b699ffa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -406,17 +406,16 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7615_mcu_set_bss_info(dev, vif, info->assoc); - /* TODO: update beacon content - * BSS_CHANGED_BEACON - */ - if (changed & BSS_CHANGED_BEACON_ENABLED) { mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_bcn(hw, vif, info->enable_beacon); } + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7615_mcu_set_bcn(hw, vif, info->enable_beacon); + mutex_unlock(&dev->mt76.mutex); } From c3c25d09d4ac1fc5eb8795f8904b2f0d42bca1d3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 5 Dec 2019 11:36:51 +0100 Subject: [PATCH 059/168] mt76: mt7615: defer mcu initialization via workqueue Loading the mcu firmware and waiting for it to boot takes a long time, which adds a significant amount to the system boot time. Fix this by running the mcu init from a workqueue and waiting for it to complete before starting the phy or issuing mcu commands via debugfs Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 12 ++++++ .../net/wireless/mediatek/mt76/mt7615/init.c | 37 ++++++++++++++----- .../net/wireless/mediatek/mt76/mt7615/main.c | 3 ++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index f75b3f66cdb4..783f145b7d02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -7,6 +7,9 @@ mt7615_radar_pattern_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + return mt7615_mcu_rdd_send_pattern(dev); } @@ -18,6 +21,9 @@ mt7615_scs_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + mt7615_mac_set_scs(dev, val); return 0; @@ -41,6 +47,9 @@ mt7615_dbdc_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + if (val) mt7615_register_ext_phy(dev); else @@ -131,6 +140,9 @@ static int mt7615_read_temperature(struct seq_file *s, void *data) struct mt7615_dev *dev = dev_get_drvdata(s->private); int temp; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + /* cpu */ temp = mt7615_mcu_get_temperature(dev, 0); seq_printf(s, "Temperature: %d\n", temp); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index a14d4d978aad..77869e28c3c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -104,12 +104,33 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); } +bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) +{ + flush_work(&dev->mcu_work); + + return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); +} + +static void mt7615_init_work(struct work_struct *work) +{ + struct mt7615_dev *dev = container_of(work, struct mt7615_dev, mcu_work); + + if (mt7615_mcu_init(dev)) + return; + + mt7615_mcu_set_eeprom(dev); + mt7615_mac_init(dev); + mt7615_phy_init(dev); + mt7615_mcu_del_wtbl_all(dev); +} + static int mt7615_init_hardware(struct mt7615_dev *dev) { int ret, idx; mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + INIT_WORK(&dev->mcu_work, mt7615_init_work); spin_lock_init(&dev->token_lock); idr_init(&dev->token); @@ -123,15 +144,6 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - ret = mt7615_mcu_init(dev); - if (ret) - return ret; - - mt7615_mcu_set_eeprom(dev); - mt7615_mac_init(dev); - mt7615_phy_init(dev); - mt7615_mcu_del_wtbl_all(dev); - /* Beacon and mgmt frames should occupy wcid 0 */ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1); if (idx) @@ -392,6 +404,7 @@ int mt7615_register_device(struct mt7615_dev *dev) if (ret) return ret; + ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work); mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband); mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband); @@ -401,11 +414,15 @@ int mt7615_register_device(struct mt7615_dev *dev) void mt7615_unregister_device(struct mt7615_dev *dev) { struct mt76_txwi_cache *txwi; + bool mcu_running; int id; + mcu_running = mt7615_wait_for_mcu_init(dev); + mt7615_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); - mt7615_mcu_exit(dev); + if (mcu_running) + mt7615_mcu_exit(dev); mt7615_dma_cleanup(dev); spin_lock_bh(&dev->token_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 79f32b699ffa..8c2b28e19b6a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -30,6 +30,9 @@ static int mt7615_start(struct ieee80211_hw *hw) struct mt7615_phy *phy = mt7615_hw_phy(hw); bool running; + if (!mt7615_wait_for_mcu_init(dev)) + return -EIO; + mutex_lock(&dev->mt76.mutex); running = mt7615_dev_running(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 32f23f5fdd58..b4d6727cf285 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -117,6 +117,8 @@ struct mt7615_dev { u16 chainmask; + struct work_struct mcu_work; + struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -222,6 +224,7 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); +bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, From 3e3848280f7d9c3f434c6a8bf9006b41882eb2d1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 5 Dec 2019 14:26:13 +0100 Subject: [PATCH 060/168] mt7615: replace sta_state callback with sta_add/sta_remove The MT7615 firmware needs to know the association id at creation time, which is unavailable during the transition from notexist to none in .sta_state. This can cause a number of issues, probably also breaking powersave support. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 38 ++++++++++++------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 8 ++-- .../net/wireless/mediatek/mt76/mt7615/pci.c | 5 +-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 8c2b28e19b6a..6a18f7d8454e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -434,8 +434,8 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw, mutex_unlock(&dev->mt76.mutex); } -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -457,21 +457,14 @@ int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7615_mcu_add_wtbl(dev, vif, sta); mt7615_mcu_set_sta_rec(dev, vif, sta, 1); + if (sta->ht_cap.ht_supported) + mt7615_mcu_set_ht_cap(dev, vif, sta); return 0; } -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - if (sta->ht_cap.ht_supported) - mt7615_mcu_set_ht_cap(dev, vif, sta); -} - -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -607,6 +600,22 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return ret; } +static int +mt7615_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE); +} + +static int +mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); +} + const struct ieee80211_ops mt7615_ops = { .tx = mt7615_tx, .start = mt7615_start, @@ -617,7 +626,8 @@ const struct ieee80211_ops mt7615_ops = { .conf_tx = mt7615_conf_tx, .configure_filter = mt7615_configure_filter, .bss_info_changed = mt7615_bss_info_changed, - .sta_state = mt76_sta_state, + .sta_add = mt7615_sta_add, + .sta_remove = mt7615_sta_remove, .set_key = mt7615_set_key, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index b4d6727cf285..4fe6dc60e0cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -313,12 +313,10 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb); void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index dd9ee80dbef7..7e3556c3b6eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -81,9 +81,8 @@ static int mt7615_pci_probe(struct pci_dev *pdev, .rx_skb = mt7615_queue_rx_skb, .rx_poll_complete = mt7615_rx_poll_complete, .sta_ps = mt7615_sta_ps, - .sta_add = mt7615_sta_add, - .sta_assoc = mt7615_sta_assoc, - .sta_remove = mt7615_sta_remove, + .sta_add = mt7615_mac_sta_add, + .sta_remove = mt7615_mac_sta_remove, .update_survey = mt7615_update_channel, }; struct mt7615_dev *dev; From 2703bafcdbf7d41562b8e8c877ed94c3aec70ac4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 5 Dec 2019 17:32:41 +0100 Subject: [PATCH 061/168] mt76: fix rx dma ring descriptor state on reset To avoid having the hardware potentially write to memory behind stale descriptors, set the dma-done flag on all of them before cleaning up allocated rx buffers Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index f88d017ff987..2298a4e91943 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -437,7 +437,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) int i; for (i = 0; i < q->ndesc; i++) - q->desc[i].ctrl &= ~cpu_to_le32(MT_DMA_CTL_DMA_DONE); + q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE); mt76_dma_rx_cleanup(dev, q); mt76_dma_sync_idx(dev, q); From 37a68e001578ed1cd7def6a0666f60d2aade4f26 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 5 Dec 2019 17:46:42 +0100 Subject: [PATCH 062/168] mt76: disable bh in mt76_dma_rx_poll Fixes potential RCU issues and avoids calling ieee80211_rx_napi with softirq enabled. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 2298a4e91943..9e03a7871ff4 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -538,6 +538,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) dev = container_of(napi->dev, struct mt76_dev, napi_dev); qid = napi - dev->napi; + local_bh_disable(); rcu_read_lock(); do { @@ -547,6 +548,7 @@ mt76_dma_rx_poll(struct napi_struct *napi, int budget) } while (cur && done < budget); rcu_read_unlock(); + local_bh_enable(); if (done < budget && napi_complete(napi)) dev->drv->rx_poll_complete(dev, qid); From eba571683b40eb1ad982c6ce9b92d15724bc220e Mon Sep 17 00:00:00 2001 From: Shayne Chen Date: Tue, 26 Nov 2019 21:15:54 +0800 Subject: [PATCH 063/168] mt76: fix possible undetected invalid MAC address Make sure the MAC address is checked before function returns. If CONFIG_OF is set and the device node is null, the function will return directly, and an invalid MAC address will not be checked. Signed-off-by: Shayne Chen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/eeprom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 804224e81103..358fb0a1e523 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -80,13 +80,14 @@ mt76_eeprom_override(struct mt76_dev *dev) const u8 *mac; if (!np) - return; + goto out; mac = of_get_mac_address(np); if (!IS_ERR(mac)) ether_addr_copy(dev->macaddr, mac); #endif +out: if (!is_valid_ether_addr(dev->macaddr)) { eth_random_addr(dev->macaddr); dev_info(dev->dev, From 00c29ab2f67105444b50cea59b68cf716e27cedc Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 21 Nov 2019 10:42:13 +0200 Subject: [PATCH 064/168] mt76: mt7603: reset STA_CCA counter setting the channel Reset MT_MIB_STAT_CCA after channel switch since it is used to track busy time starting from 'commit dcff8d4dc301 ("mt76: mt7603: switch to a different counter for survey busy time")' Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 6da7caaaade1..eed56165b275 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -187,7 +187,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS); mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); - mt76_rr(dev, MT_MIB_STAT_PSCCA); + mt76_rr(dev, MT_MIB_STAT_CCA); mt7603_cca_stats_reset(dev); dev->mphy.survey_time = ktime_get_boottime(); From b3c6d6388b512e947dfa6c244af5d8f54b37cf65 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 27 Nov 2019 16:46:33 +0200 Subject: [PATCH 065/168] mt76: eeprom: add support for big endian eeprom partition mt76x0e users reported some devices (e.g TP-Link Archer VR200v) have been flashed with big endian radio partition. Add the possibility to specify eeprom endianness using big-endian dts property and in case covert eeprom data in little endian Tested-by: Kevin Schmidt Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/eeprom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 358fb0a1e523..8f2693748faf 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -64,6 +64,16 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len) goto out_put_node; } + if (of_property_read_bool(dev->dev->of_node, "big-endian")) { + u8 *data = (u8 *)dev->eeprom.data; + int i; + + /* convert eeprom data in Little Endian */ + for (i = 0; i < round_down(len, 2); i += 2) + put_unaligned_le16(get_unaligned_be16(&data[i]), + &data[i]); + } + out_put_node: of_node_put(np); return ret; From 1a874afbbf8812af4c4e269eb3d2c6b201532ed0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 27 Nov 2019 16:46:34 +0200 Subject: [PATCH 066/168] dt-bindings: net: wireless: mt76: introduce big-endian property Introduce big-endian property to specify mtd radio partition endianness Signed-off-by: Lorenzo Bianconi Acked-by: Rob Herring Signed-off-by: Felix Fietkau --- .../devicetree/bindings/net/wireless/mediatek,mt76.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt index 7e675dafc256..d4d982f7ab37 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt @@ -15,6 +15,8 @@ Optional properties: - ieee80211-freq-limit: See ieee80211.txt - mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data +- big-endian: if the radio eeprom partition is written in big-endian, specify + this property The MAC address can as well be set with corresponding optional properties defined in net/ethernet.txt. @@ -31,6 +33,7 @@ Optional nodes: reg = <0x0000 0 0 0 0>; ieee80211-freq-limit = <5000000 6000000>; mediatek,mtd-eeprom = <&factory 0x8000>; + big-endian; led { led-sources = <2>; From f53300fdaa84dc02f96ab9446b5bac4d20016c43 Mon Sep 17 00:00:00 2001 From: Pablo Greco Date: Sun, 1 Dec 2019 15:17:10 -0300 Subject: [PATCH 067/168] mt76: mt7615: Fix build with older compilers Some compilers (tested with 4.8.5 from CentOS 7) fail properly process FIELD_GET inside an inline function, which ends up in a BUILD_BUG_ON. Convert inline function to a macro. Fixes commit bf92e7685100 ("mt76: mt7615: add support for per-chain signal strength reporting") Reported in https://lkml.org/lkml/2019/9/21/146 Reported-by: kbuild test robot Signed-off-by: Pablo Greco Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 4d528aa725fd..b03b5c6fd571 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -13,10 +13,7 @@ #include "../dma.h" #include "mac.h" -static inline s8 to_rssi(u32 field, u32 rxv) -{ - return (FIELD_GET(field, rxv) - 220) / 2; -} +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) From 175b4d58b91a6f9ddd305c0d4f785283fa4b2d6f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 9 Dec 2019 20:58:59 +0100 Subject: [PATCH 068/168] mt76: mt7615: report firmware version using ethtool Print fw_ver and build_date members of struct mt7615_fw_trailer similarly to what appears in the output of 'dmesg' when the MCU firmware is loaded. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index c08a301d4a62..fc091278d9e5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -514,8 +514,14 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; ret = mt7615_mcu_start_firmware(dev, 0, FW_START_WORKING_PDA_CR4); - if (ret) + if (ret) { dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n"); + goto out; + } + + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); out: release_firmware(fw); From bae76a1eefd4815f73046d66ddfdb2a4987bf952 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 8 Dec 2019 08:25:38 +0100 Subject: [PATCH 069/168] mt76: mt76x02: fix coverage_class type Fix coverage_class type in mt76x02_dev data structure since coverage_class can be negative to enable dynack (just supported by ath9k). Set 0 as minimum value for coverage_class Fixes: 7bc04215a66b ("mt76: add driver code for MT76x2e") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index ba4c14eea22d..57665516d00e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -116,7 +116,7 @@ struct mt76x02_dev { bool no_2ghz; - u8 coverage_class; + s16 coverage_class; u8 slottime; struct mt76x02_dfs_pattern_detector dfs_pd; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index e5685d9534e4..ab717d82d771 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -545,7 +545,7 @@ void mt76x02_set_coverage_class(struct ieee80211_hw *hw, struct mt76x02_dev *dev = hw->priv; mutex_lock(&dev->mt76.mutex); - dev->coverage_class = coverage_class; + dev->coverage_class = max_t(s16, coverage_class, 0); mt76x02_set_tx_ackto(dev); mutex_unlock(&dev->mt76.mutex); } From 6a792b1a0332413e16d36c167c96ab3897cb3e04 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 8 Dec 2019 08:25:39 +0100 Subject: [PATCH 070/168] mt76: mt7603: set 0 as min coverage_class value Set 0 as minimum configurable value for coverage_class since mt76 does not support dynack Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index eed56165b275..e5776d936c0a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -642,7 +642,7 @@ mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt7603_dev *dev = hw->priv; - dev->coverage_class = coverage_class; + dev->coverage_class = max_t(s16, coverage_class, 0); mt7603_mac_set_timing(dev); } From 183d1fcf0b6a8542fcd4be3074b1dee50bd3b760 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 8 Dec 2019 08:25:40 +0100 Subject: [PATCH 071/168] mt76: mt7615: add set_coverage class support Add the capability to configure acktimeout for mt7615 driver. Moreover configure slottime according to the value provided by mac80211 Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 3 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 61 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 21 +++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 7 +++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 21 +++++++ 5 files changed, 113 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 77869e28c3c3..17a4055ad53f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -271,6 +271,7 @@ mt7615_regd_notifier(struct wiphy *wiphy, static void mt7615_init_wiphy(struct ieee80211_hw *hw) { + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct wiphy *wiphy = hw->wiphy; hw->queues = 4; @@ -278,6 +279,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) hw->max_report_rates = 7; hw->max_rate_tries = 11; + phy->slottime = 9; + hw->sta_data_size = sizeof(struct mt7615_sta); hw->vif_data_size = sizeof(struct mt7615_vif); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b03b5c6fd571..903b8395a446 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -64,6 +64,67 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +void mt7615_mac_set_timing(struct mt7615_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 val, reg_offset, reg = ext_phy ? MT_TMAC_ICR1 : MT_TMAC_ICR0; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); + int sifs, offset; + + if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) + sifs = 16; + else + sifs = 10; + + if (ext_phy) { + coverage_class = max_t(s16, dev->phy.coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + } else { + struct mt7615_phy *phy_ext = mt7615_ext_phy(dev); + + if (phy_ext) + coverage_class = max_t(s16, phy_ext->coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + } + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + mt76_wr(dev, MT_TMAC_CDTR, cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR, ofdm + reg_offset); + + mt76_wr(dev, reg, + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20) + val = MT7615_CFEND_RATE_DEFAULT; + else + val = MT7615_CFEND_RATE_11B; + + if (ext_phy) { + mt76_rmw_field(dev, MT_AGG_ACR1, MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + } else { + mt76_rmw_field(dev, MT_AGG_ACR0, MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + } +} + int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 6a18f7d8454e..77b35accd5d2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -233,6 +233,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) (ext_phy * MT_CHFREQ_DBDC_IDX) | phy->chfreq_seq); + mt7615_mac_set_timing(phy); ret = mt7615_dfs_init_radar_detector(phy); mt7615_mac_cca_stats_reset(phy); @@ -409,6 +410,16 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7615_mcu_set_bss_info(dev, vif, info->assoc); + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt7615_mac_set_timing(phy); + } + } + if (changed & BSS_CHANGED_BEACON_ENABLED) { mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); @@ -616,6 +627,15 @@ mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_STA_NOTEXIST); } +static void +mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt7615_mac_set_timing(phy); +} + const struct ieee80211_ops mt7615_ops = { .tx = mt7615_tx, .start = mt7615_start, @@ -640,4 +660,5 @@ const struct ieee80211_ops mt7615_ops = { .channel_switch_beacon = mt7615_channel_switch_beacon, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, + .set_coverage_class = mt7615_set_coverage_class, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 4fe6dc60e0cd..554bd04d6d81 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -40,6 +40,9 @@ #define MT_CHFREQ_DBDC_IDX BIT(6) #define MT_CHFREQ_SEQ GENMASK(5, 0) +#define MT7615_CFEND_RATE_DEFAULT 0x69 /* chip default (24M) */ +#define MT7615_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + struct mt7615_vif; struct mt7615_sta; @@ -97,6 +100,9 @@ struct mt7615_phy { u16 chainmask; + s16 coverage_class; + u8 slottime; + u8 chfreq_seq; u8 rdd_state; int dfs_state; @@ -286,6 +292,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, struct ieee80211_key_conf *key); +void mt7615_mac_set_timing(struct mt7615_phy *phy); int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb); void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data); void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index cece061b1108..26d121646787 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -162,14 +162,35 @@ #define MT_AGG_SCR MT_WF_AGG(0x0fc) #define MT_AGG_SCR_NLNAV_MID_PTEC_DIS BIT(3) +#define MT_WF_ARB_BASE 0x20c00 +#define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) + +#define MT_ARB_SCR MT_WF_ARB(0x080) +#define MT_ARB_SCR_TX0_DISABLE BIT(8) +#define MT_ARB_SCR_RX0_DISABLE BIT(9) +#define MT_ARB_SCR_TX1_DISABLE BIT(10) +#define MT_ARB_SCR_RX1_DISABLE BIT(11) + #define MT_WF_TMAC_BASE 0x21000 #define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) +#define MT_TMAC_CDTR MT_WF_TMAC(0x090) +#define MT_TMAC_ODTR MT_WF_TMAC(0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + #define MT_TMAC_TRCR0 MT_WF_TMAC(0x09c) #define MT_TMAC_TRCR1 MT_WF_TMAC(0x070) #define MT_TMAC_TRCR_CCA_SEL GENMASK(31, 30) #define MT_TMAC_TRCR_SEC_CCA_SEL GENMASK(29, 28) +#define MT_TMAC_ICR0 MT_WF_TMAC(0x0a4) +#define MT_TMAC_ICR1 MT_WF_TMAC(0x074) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + #define MT_TMAC_CTCR0 MT_WF_TMAC(0x0f4) #define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) #define MT_TMAC_CTCR0_INS_DDLMT_DENSITY GENMASK(15, 12) From e7ec563eae04d16b5d2c4f56c3ac8254f7e4cb09 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 14 Dec 2019 10:58:59 +0100 Subject: [PATCH 072/168] mt76: use AC specific reorder timeout Before this patch, mt76 handled rx traffic for all TIDs equally, when released from reorder buffer early. This patch uses an AC specific reorder timeout, in order to release partial aggregated frames for video ACs earlier. Voice ACs are currently not aggregated (thanks to Felix for this hint). For example, ath10k also uses AC specific reorder timeouts (reported by firmware in that case). Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/agg-rx.c | 16 ++++++++++++---- drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index 59c187898132..a4c64ae8fb1a 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -4,7 +4,13 @@ */ #include "mt76.h" -#define REORDER_TIMEOUT (HZ / 10) +static unsigned long mt76_aggr_tid_to_timeo(u8 tidno) +{ + /* Currently voice traffic (AC_VO) always runs without aggregation, + * no special handling is needed. AC_BE/AC_BK use tids 0-3. Just check + * for non AC_BK/AC_BE and set smaller timeout for it. */ + return HZ / (tidno >= 4 ? 25 : 10); +} static void mt76_aggr_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames, int idx) @@ -71,7 +77,8 @@ mt76_rx_aggr_check_release(struct mt76_rx_tid *tid, struct sk_buff_head *frames) nframes--; status = (struct mt76_rx_status *)skb->cb; if (!time_after(jiffies, - status->reorder_time + REORDER_TIMEOUT)) + status->reorder_time + + mt76_aggr_tid_to_timeo(tid->num))) continue; mt76_rx_aggr_release_frames(tid, frames, status->seqno); @@ -101,7 +108,7 @@ mt76_rx_aggr_reorder_work(struct work_struct *work) if (nframes) ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, - REORDER_TIMEOUT); + mt76_aggr_tid_to_timeo(tid->num)); mt76_rx_complete(dev, &frames, NULL); rcu_read_unlock(); @@ -225,7 +232,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames) mt76_rx_aggr_release_head(tid, frames); ieee80211_queue_delayed_work(tid->dev->hw, &tid->reorder_work, - REORDER_TIMEOUT); + mt76_aggr_tid_to_timeo(tid->num)); out: spin_unlock_bh(&tid->lock); @@ -245,6 +252,7 @@ int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno, tid->dev = dev; tid->head = ssn; tid->size = size; + tid->num = tidno; INIT_DELAYED_WORK(&tid->reorder_work, mt76_rx_aggr_reorder_work); spin_lock_init(&tid->lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5b648efc43fa..846c9e16c4c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -242,6 +242,8 @@ struct mt76_rx_tid { u8 size; u8 nframes; + u8 num; + u8 started:1, stopped:1, timer_pending:1; struct sk_buff *reorder_buf[]; From 0794d03a8f2f76ee68e14994bc3c8a589ea0c169 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:49 +0100 Subject: [PATCH 073/168] mt76: mt76x02: omit beacon slot clearing mt76 hw does not send beacons from beacon slots, if the corresponding bitmask is set accordingly. Therefore we can omit clearing the beacon memory. Clearing uses many usb calls, if usb drivers are used. These calls unnecessarily slow down the beacon tasklet. Thanks to Stanislaw Gruzska for pointing this out. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index 4209209ac940..403866496640 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -58,8 +58,6 @@ __mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, dev->beacon_data_mask |= BIT(bcn_idx); } else { dev->beacon_data_mask &= ~BIT(bcn_idx); - for (i = 0; i < beacon_len; i += 4) - mt76_wr(dev, beacon_addr + i, 0); } mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); @@ -241,17 +239,11 @@ EXPORT_SYMBOL_GPL(mt76x02_enqueue_buffered_bc); void mt76x02_init_beacon_config(struct mt76x02_dev *dev) { - int i; - mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX)); mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); - - for (i = 0; i < 8; i++) - mt76x02_mac_set_beacon(dev, i, NULL); - mt76x02_set_beacon_offsets(dev); } EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); From f27469a9339681edc1b64c82506c1b393d99a304 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:50 +0100 Subject: [PATCH 074/168] mt76: mt76x02: split beaconing Sending beacons to the hardware always happens in batches. In order to speed up beacon processing on usb devices, this patch splits out common code an calls it only once. Beacons are sequentially written into the beacon memory area, by tracking its usage with the dev->beacon_data_count. For MBSS support and buffered traffic dev->beacon_data_count is used to create the bypass mask. The code is also adapted for the mmio part of the driver, but should not have any performance implication there. MBSS tests were performed with AVM AC860 USB NIC with temporary support for 5 BSS'. Different combinations of active vifs were created and brought up. Afterwards connection and data transfer was tested for the announced BSS'. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 3 +- .../wireless/mediatek/mt76/mt76x02_beacon.c | 64 ++++--------------- .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 + .../net/wireless/mediatek/mt76/mt76x02_mac.h | 3 +- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 7 ++ .../wireless/mediatek/mt76/mt76x02_usb_core.c | 20 +++--- 6 files changed, 31 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 57665516d00e..23040c193ca5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -98,8 +98,7 @@ struct mt76x02_dev { const struct mt76x02_beacon_ops *beacon_ops; - struct sk_buff *beacons[8]; - u8 beacon_data_mask; + u8 beacon_data_count; u8 tbtt_count; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index 403866496640..c93e2e8749f0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -40,62 +40,21 @@ mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) return 0; } -static int -__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx, - struct sk_buff *skb) -{ - int beacon_len = dev->beacon_ops->slot_size; - int beacon_addr = MT_BEACON_BASE + (beacon_len * bcn_idx); - int ret = 0; - int i; - - /* Prevent corrupt transmissions during update */ - mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx)); - - if (skb) { - ret = mt76x02_write_beacon(dev, beacon_addr, skb); - if (!ret) - dev->beacon_data_mask |= BIT(bcn_idx); - } else { - dev->beacon_data_mask &= ~BIT(bcn_idx); - } - - mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask); - - return ret; -} - -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, +int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, struct sk_buff *skb) { - bool force_update = false; - int bcn_idx = 0; - int i; + int bcn_len = dev->beacon_ops->slot_size; + int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count); + int ret = 0; - for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) { - if (vif_idx == i) { - force_update = !!dev->beacons[i] ^ !!skb; - dev_kfree_skb(dev->beacons[i]); - dev->beacons[i] = skb; - __mt76x02_mac_set_beacon(dev, bcn_idx, skb); - } else if (force_update && dev->beacons[i]) { - __mt76x02_mac_set_beacon(dev, bcn_idx, - dev->beacons[i]); - } - - bcn_idx += !!dev->beacons[i]; + if (skb) { + ret = mt76x02_write_beacon(dev, bcn_addr, skb); + if (!ret) + dev->beacon_data_count++; } - for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) { - if (!(dev->beacon_data_mask & BIT(i))) - break; - - __mt76x02_mac_set_beacon(dev, i, NULL); - } - - mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, - bcn_idx - 1); - return 0; + dev_kfree_skb(skb); + return ret; } EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); @@ -114,7 +73,6 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, dev->mt76.beacon_mask |= BIT(mvif->idx); } else { dev->mt76.beacon_mask &= ~BIT(mvif->idx); - mt76x02_mac_set_beacon(dev, mvif->idx, NULL); } if (!!old_mask == !!dev->mt76.beacon_mask) @@ -180,7 +138,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) if (!skb) return; - mt76x02_mac_set_beacon(dev, mvif->idx, skb); + mt76x02_mac_set_beacon(dev, skb); } EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 5b512e4ce6b8..484cb5770fd9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -741,6 +741,8 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr) get_unaligned_le16(dev->mt76.macaddr + 4) | FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */ MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); + /* enable 7 additional beacon slots and control them with bypass mask */ + mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N, 7); for (i = 0; i < 16; i++) mt76x02_mac_set_bssid(dev, i, null_addr); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 37445bc7b546..89db7b3671d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -201,8 +201,7 @@ void mt76x02_mac_work(struct work_struct *work); void mt76x02_mac_cc_reset(struct mt76x02_dev *dev); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, - struct sk_buff *skb); +int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, struct sk_buff *skb); void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool enable); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index e7ba9bf82d98..094a4228b591 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -24,10 +24,17 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) mt76x02_resync_beacon_timer(dev); + /* Prevent corrupt transmissions during update */ + mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff); + dev->beacon_data_count = 0; + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); + mt76_wr(dev, MT_BCN_BYPASS_MASK, + 0xff00 | ~(0xff00 >> dev->beacon_data_count)); + mt76_csa_check(&dev->mt76); if (dev->mt76.csa_complete) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 5cf015c1ef5d..30f119ba61c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -208,6 +208,10 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) mt76x02_resync_beacon_timer(dev); + /* Prevent corrupt transmissions during update */ + mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff); + dev->beacon_data_count = 0; + ieee80211_iterate_active_interfaces(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); @@ -217,9 +221,12 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) for (i = nbeacons; i < N_BCN_SLOTS; i++) { skb = __skb_dequeue(&data.q); - mt76x02_mac_set_beacon(dev, i, skb); + mt76x02_mac_set_beacon(dev, skb); } + mt76_wr(dev, MT_BCN_BYPASS_MASK, + 0xff00 | ~(0xff00 >> dev->beacon_data_count)); + mt76x02u_restart_pre_tbtt_timer(dev); } @@ -244,20 +251,11 @@ static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en) static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en) { - int i; - if (WARN_ON_ONCE(!dev->mt76.beacon_int)) return; - if (en) { + if (en) mt76x02u_start_pre_tbtt_timer(dev); - } else { - /* Timer is already stopped, only clean up - * PS buffered frames if any. - */ - for (i = 0; i < N_BCN_SLOTS; i++) - mt76x02_mac_set_beacon(dev, i, NULL); - } } void mt76x02u_init_beacon_config(struct mt76x02_dev *dev) From 7d2886404e78c34ecb43b56c84f4e4a83d965962 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:51 +0100 Subject: [PATCH 075/168] mt76: mt76x02: add check for invalid vif idx On adding vifs the idx can become 1 + (7 & 7) = 8 for APs. Check against that, as only AP vif idx 0-7 is possible. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index ab717d82d771..cb798191ac40 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -325,7 +325,9 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (vif->type == NL80211_IFTYPE_STATION) idx += 8; - if (dev->vif_mask & BIT(idx)) + /* vif is already set or idx is 8 for AP/Mesh/... */ + if (dev->vif_mask & BIT(idx) || + (vif->type != NL80211_IFTYPE_STATION && idx > 7)) return -EBUSY; dev->vif_mask |= BIT(idx); From 5c48e60e57b0c3fa30f32cacff454cb855f2af88 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:52 +0100 Subject: [PATCH 076/168] mt76: mt76x02: remove a copy call for usb speedup This patch removes a mt76_wr_copy call from the beacon path to hw. The skb which is used in this place gets therefore build with txwi inside its data. For mt76 usb drivers, this saves one synchronuous copy call over usb, which lets the beacon work complete faster. In mmio case, there is not enough headroom to put the txwi into the skb, it is therefore using an additional mt76_wr_copy, which is fast over mmio. Thanks Stanislaw for pointing this out. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt76x02_beacon.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index c93e2e8749f0..3d0d3f6d28eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -26,15 +26,26 @@ static int mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) { int beacon_len = dev->beacon_ops->slot_size; - struct mt76x02_txwi txwi; if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi))) return -ENOSPC; - mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + /* USB devices already reserve enough skb headroom for txwi's. This + * helps to save slow copies over USB. + */ + if (mt76_is_usb(&dev->mt76)) { + struct mt76x02_txwi *txwi; - mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); - offset += sizeof(txwi); + txwi = (struct mt76x02_txwi *)(skb->data - sizeof(*txwi)); + mt76x02_mac_write_txwi(dev, txwi, skb, NULL, NULL, skb->len); + skb_push(skb, sizeof(*txwi)); + } else { + struct mt76x02_txwi txwi; + + mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len); + mt76_wr_copy(dev, offset, &txwi, sizeof(txwi)); + offset += sizeof(txwi); + } mt76_wr_copy(dev, offset, skb->data, skb->len); return 0; From 9446248669968f3f73f7547156799df5f041bc2f Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:53 +0100 Subject: [PATCH 077/168] mt76: speed up usb bulk copy Use larger batches for usb copy to speed this operation up. Otherwise it would be too slow for copying new beacons or broadcast frames over usb. Assure, that always a multiple of 4 Bytes is copied, as outlined in 850e8f6fbd "mt76: round up length on mt76_wr_copy" from Felix Fietkau. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 24 +++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 846c9e16c4c1..3d508500574c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -389,7 +389,7 @@ enum mt76u_out_ep { struct mt76_usb { struct mutex usb_ctrl_mtx; union { - u8 data[32]; + u8 data[128]; __le32 reg_val; }; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 8561d1bd7e6a..e89b38b0445c 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -149,18 +149,30 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) { struct mt76_usb *usb = &dev->usb; - const u32 *val = data; - int i, ret; + const u8 *val = data; + int ret; + int current_batch_size; + int i = 0; + + /* Assure that always a multiple of 4 bytes are copied, + * otherwise beacons can be corrupted. + * See: "mt76: round up length on mt76_wr_copy" + * Commit 850e8f6fbd5d0003b0 + */ + len = round_up(len, 4); mutex_lock(&usb->usb_ctrl_mtx); - for (i = 0; i < DIV_ROUND_UP(len, 4); i++) { - put_unaligned(val[i], (u32 *)usb->data); + while (i < len) { + current_batch_size = min_t(int, sizeof(usb->data), len - i); + memcpy(usb->data, val + i, current_batch_size); ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE, USB_DIR_OUT | USB_TYPE_VENDOR, - 0, offset + i * 4, usb->data, - sizeof(u32)); + 0, offset + i, usb->data, + current_batch_size); if (ret < 0) break; + + i += current_batch_size; } mutex_unlock(&usb->usb_ctrl_mtx); } From d3cc4e7640cabb0100630093a0d07c266ea08c42 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 17:07:54 +0100 Subject: [PATCH 078/168] mt76: mt76x02: add channel switch support for usb interfaces This patch enables channel switch support on mt76 usb interfaces. Signed-off-by: Markus Theil Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 8 ++++++++ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 30f119ba61c3..324872d9640d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -216,6 +216,13 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); + mt76_csa_check(&dev->mt76); + + if (dev->mt76.csa_complete) { + mt76_csa_finish(&dev->mt76); + goto out; + } + nbeacons = hweight8(dev->mt76.beacon_mask); mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons); @@ -224,6 +231,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) mt76x02_mac_set_beacon(dev, skb); } +out: mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~(0xff00 >> dev->beacon_data_count)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index cb798191ac40..15a24e04a194 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -166,7 +166,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -176,6 +175,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) } } + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); hw->sta_data_size = sizeof(struct mt76x02_sta); From a6bfb6d13f3325fd5cc3646f558b67c40ea823d0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 29 Nov 2019 13:32:26 +0100 Subject: [PATCH 079/168] mt76: usb: use max packet length for m76u_copy For transferring data over USB the optimal size is endpoint maxpacket. For my hardware maxpaket for control endpoint is 64 bytes and changing to this value from 128 bytes further shorten TBTT work time from 3ms to 1ms. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 7 +++--- drivers/net/wireless/mediatek/mt76/usb.c | 29 +++++++++++++++-------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 3d508500574c..7034e901098a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -388,10 +388,9 @@ enum mt76u_out_ep { #define MCU_RESP_URB_SIZE 1024 struct mt76_usb { struct mutex usb_ctrl_mtx; - union { - u8 data[128]; - __le32 reg_val; - }; + __le32 reg_val; + u8 *data; + u16 data_len; struct tasklet_struct rx_tasklet; struct workqueue_struct *stat_wq; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index e89b38b0445c..22dacf040123 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -163,7 +163,7 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset, mutex_lock(&usb->usb_ctrl_mtx); while (i < len) { - current_batch_size = min_t(int, sizeof(usb->data), len - i); + current_batch_size = min_t(int, usb->data_len, len - i); memcpy(usb->data, val + i, current_batch_size); ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE, USB_DIR_OUT | USB_TYPE_VENDOR, @@ -950,6 +950,15 @@ static const struct mt76_queue_ops usb_queue_ops = { .kick = mt76u_tx_kick, }; +void mt76u_deinit(struct mt76_dev *dev) +{ + if (dev->usb.stat_wq) { + destroy_workqueue(dev->usb.stat_wq); + dev->usb.stat_wq = NULL; + } +} +EXPORT_SYMBOL_GPL(mt76u_deinit); + int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf) { @@ -973,6 +982,15 @@ int mt76u_init(struct mt76_dev *dev, if (!usb->stat_wq) return -ENOMEM; + usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); + if (usb->data_len < 32) + usb->data_len = 32; + usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL); + if (!usb->data) { + mt76u_deinit(dev); + return -ENOMEM; + } + mutex_init(&usb->mcu.mutex); mutex_init(&usb->usb_ctrl_mtx); @@ -987,14 +1005,5 @@ int mt76u_init(struct mt76_dev *dev, } EXPORT_SYMBOL_GPL(mt76u_init); -void mt76u_deinit(struct mt76_dev *dev) -{ - if (dev->usb.stat_wq) { - destroy_workqueue(dev->usb.stat_wq); - dev->usb.stat_wq = NULL; - } -} -EXPORT_SYMBOL_GPL(mt76u_deinit); - MODULE_AUTHOR("Lorenzo Bianconi "); MODULE_LICENSE("Dual BSD/GPL"); From c708bfa352d3464def0da485a3f846cc7c7b88cf Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 29 Nov 2019 13:32:27 +0100 Subject: [PATCH 080/168] mt76: mt76x02u: do not set NULL beacons With current implementation we do not cleanup beacon memory, so is not needed to call mt76x02_mac_set_beacon() with NULL skb. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 324872d9640d..bf3198ec193b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -198,7 +198,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) container_of(work, struct mt76x02_dev, pre_tbtt_work); struct beacon_bc_data data = {}; struct sk_buff *skb; - int i, nbeacons; + int nbeacons; if (!dev->mt76.beacon_mask) return; @@ -226,10 +226,8 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work) nbeacons = hweight8(dev->mt76.beacon_mask); mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons); - for (i = nbeacons; i < N_BCN_SLOTS; i++) { - skb = __skb_dequeue(&data.q); + while ((skb = __skb_dequeue(&data.q)) != NULL) mt76x02_mac_set_beacon(dev, skb); - } out: mt76_wr(dev, MT_BCN_BYPASS_MASK, From b74f98b828f54dfa0de193c3ddce725fea966b1a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 29 Nov 2019 13:32:28 +0100 Subject: [PATCH 081/168] mt76: mt76x02: minor mt76x02_mac_set_beacon optimization We do not call mt76x02_mac_set_beacon() with NULL skb any longer and we do not need to return error value. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76x02_beacon.c | 14 ++++---------- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c index 3d0d3f6d28eb..5d034cec191b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c @@ -51,21 +51,15 @@ mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb) return 0; } -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, - struct sk_buff *skb) +void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, + struct sk_buff *skb) { int bcn_len = dev->beacon_ops->slot_size; int bcn_addr = MT_BEACON_BASE + (bcn_len * dev->beacon_data_count); - int ret = 0; - - if (skb) { - ret = mt76x02_write_beacon(dev, bcn_addr, skb); - if (!ret) - dev->beacon_data_count++; - } + if (!mt76x02_write_beacon(dev, bcn_addr, skb)) + dev->beacon_data_count++; dev_kfree_skb(skb); - return ret; } EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 89db7b3671d3..c70d17b2290c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -201,7 +201,7 @@ void mt76x02_mac_work(struct work_struct *work); void mt76x02_mac_cc_reset(struct mt76x02_dev *dev); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); -int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, struct sk_buff *skb); +void mt76x02_mac_set_beacon(struct mt76x02_dev *dev, struct sk_buff *skb); void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool enable); From a25c888f3a5f1885b46455c04a20be7f6950ec95 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 21 Dec 2019 15:17:00 +0800 Subject: [PATCH 082/168] mt76: mt7615: fix MT7615_CFEND_RATE_DEFAULT value Fix default CFEND_RATE and replace hardcode values. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 17a4055ad53f..a2405e10879c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -35,8 +35,8 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_wr(dev, MT_TMAC_TRCR1, val); val = MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | - FIELD_PREP(MT_AGG_ACR_CFEND_RATE, 0x49) | /* 24M */ - FIELD_PREP(MT_AGG_ACR_BAR_RATE, 0x4b); /* 6M */ + FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | + FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT); mt76_wr(dev, MT_AGG_ACR0, val); mt76_wr(dev, MT_AGG_ACR1, val); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 554bd04d6d81..48810eda1cd6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -40,7 +40,8 @@ #define MT_CHFREQ_DBDC_IDX BIT(6) #define MT_CHFREQ_SEQ GENMASK(5, 0) -#define MT7615_CFEND_RATE_DEFAULT 0x69 /* chip default (24M) */ +#define MT7615_BAR_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7615_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7615_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ struct mt7615_vif; From e5051965fd2b2fee3b9c332a9a9412841883decb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 14 Dec 2019 20:08:59 +0100 Subject: [PATCH 083/168] mt76: mt7615: measure channel noise and report it via survey Read measurements every 100 ms and build a simple moving average Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 ++ drivers/net/wireless/mediatek/mt76/mt76.h | 2 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 42 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/main.c | 3 ++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 3 ++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 6 +++ 6 files changed, 60 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 8cc09aa6fe61..d752fb539351 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -618,6 +618,9 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, survey->channel = chan; survey->filled = SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY; survey->filled |= dev->drv->survey_flags; + if (state->noise) + survey->filled |= SURVEY_INFO_NOISE_DBM; + if (chan == phy->main_chan) { survey->filled |= SURVEY_INFO_IN_USE; @@ -628,6 +631,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx, survey->time_busy = div_u64(state->cc_busy, 1000); survey->time_rx = div_u64(state->cc_rx, 1000); survey->time = div_u64(state->cc_active, 1000); + survey->noise = state->noise; spin_lock_bh(&dev->cc_lock); survey->time_bss_rx = div_u64(state->cc_bss_rx, 1000); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 7034e901098a..c050d95dc7ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -328,6 +328,8 @@ struct mt76_channel_state { u64 cc_rx; u64 cc_bss_rx; u64 cc_tx; + + s8 noise; }; struct mt76_sband { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 903b8395a446..1b52d8b79496 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1379,6 +1379,19 @@ void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) mutex_unlock(&dev->mt76.mutex); } +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy) +{ + u32 rxtd; + + if (ext_phy) + rxtd = MT_WF_PHY_RXTD2(10); + else + rxtd = MT_WF_PHY_RXTD(12); + + mt76_set(dev, rxtd, BIT(18) | BIT(29)); + mt76_set(dev, MT_WF_PHY_R0_PHYMUX_5(ext_phy), 0x5 << 12); +} + void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; @@ -1511,13 +1524,35 @@ mt7615_mac_scs_check(struct mt7615_phy *phy) mt7615_mac_set_default_sensitivity(phy); } +static u8 +mt7615_phy_get_nf(struct mt7615_dev *dev, int idx) +{ + static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; + u32 reg = idx ? MT_WF_PHY_RXTD2(17) : MT_WF_PHY_RXTD(20); + u32 val, sum = 0, n = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { + val = mt76_rr(dev, reg); + sum += val * nf_power[i]; + n += val; + } + + if (!n) + return 0; + + return sum / n; +} + static void mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) { struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76); + struct mt7615_phy *phy = mphy->priv; struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5; + int nf; busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), MT_MIB_SDR9_BUSY_MASK); @@ -1527,11 +1562,18 @@ mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) MT_MIB_SDR37_RXTIME_MASK); obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK); + nf = mt7615_phy_get_nf(dev, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); + state = mphy->chan_state; state->cc_busy += busy_time; state->cc_tx += tx_time; state->cc_rx += rx_time + obss_time; state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); } void mt7615_update_channel(struct mt76_dev *mdev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 77b35accd5d2..52c502af4d4d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -40,11 +40,13 @@ static int mt7615_start(struct ieee80211_hw *hw) if (!running) { mt7615_mcu_ctrl_pm_state(dev, 0, 0); mt7615_mcu_set_mac_enable(dev, 0, true); + mt7615_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { mt7615_mcu_ctrl_pm_state(dev, 1, 0); mt7615_mcu_set_mac_enable(dev, 1, true); + mt7615_mac_enable_nf(dev, 1); } set_bit(MT76_STATE_RUNNING, &phy->mt76->state); @@ -238,6 +240,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mt7615_mac_cca_stats_reset(phy); mt7615_mac_reset_counters(dev); + phy->noise = 0; out: clear_bit(MT76_RESET, &phy->mt76->state); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 48810eda1cd6..eaafae9cc279 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -94,6 +94,8 @@ struct mt7615_phy { u32 rxfilter; u32 omac_mask; + u16 noise; + unsigned long last_cca_adj; int false_cca_ofdm, false_cca_cck; s8 ofdm_sensitivity; @@ -288,6 +290,7 @@ bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask); void mt7615_mac_reset_counters(struct mt7615_dev *dev); void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy); void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable); +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy); void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 26d121646787..46db0faae93d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -104,6 +104,9 @@ #define MT_WF_PHY_B1_PD_OFDM(v) ((v) << 16) #define MT_WF_PHY_B1_PD_BLK BIT(25) +#define MT_WF_PHY_RXTD_BASE MT_WF_PHY(0x2200) +#define MT_WF_PHY_RXTD(_n) (MT_WF_PHY_RXTD_BASE + ((_n) << 2)) + #define MT_WF_PHY_B0_RXTD_CCK_PD MT_WF_PHY(0x2310) #define MT_WF_PHY_B0_PD_CCK_MASK GENMASK(8, 1) #define MT_WF_PHY_B0_PD_CCK(v) ((v) << 1) @@ -112,6 +115,9 @@ #define MT_WF_PHY_B1_PD_CCK_MASK GENMASK(31, 24) #define MT_WF_PHY_B1_PD_CCK(v) ((v) << 24) +#define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00) +#define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2)) + #define MT_WF_CFG_BASE 0x20200 #define MT_WF_CFG(ofs) (MT_WF_CFG_BASE + (ofs)) From c99dc3c1524de875226528995abbb0294303bd6c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 19 Dec 2019 13:41:24 +0100 Subject: [PATCH 084/168] mt76: mt7615: increase MCU command timeout MCU_EXT_CMD_EFUSE_BUFFER_MODE needs more time on initialization, and with only 10 seconds it sometimes runs into timeouts. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index fc091278d9e5..c8d6a36f5d0a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -144,7 +144,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - unsigned long expires = jiffies + 10 * HZ; + unsigned long expires = jiffies + 20 * HZ; struct sk_buff *skb; int ret, seq; From d55aa5e17461b8b423adae376978032c4a10a1d8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 21 Dec 2019 16:46:53 +0100 Subject: [PATCH 085/168] mt76: mt7603: fix input validation issues for powersave-filtered frames Before extracting the tid out of the packet, check if it was qos-data. Only accept tid values 0-7 Also, avoid accepting the hardware queue as skb queue mapping, it could lead to an overrun. Instead, derive the hardware queue from the tid number, in order to avoid issues with packets being filtered multiple times. This also fixes a mismatch between hardware and software queue indexes. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7603/dma.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index a6ab73060aad..57428467fe96 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -30,6 +30,16 @@ mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q, static void mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) { + static const u8 tid_to_ac[8] = { + IEEE80211_AC_BE, + IEEE80211_AC_BK, + IEEE80211_AC_BK, + IEEE80211_AC_BE, + IEEE80211_AC_VI, + IEEE80211_AC_VI, + IEEE80211_AC_VO, + IEEE80211_AC_VO + }; __le32 *txd = (__le32 *)skb->data; struct ieee80211_hdr *hdr; struct ieee80211_sta *sta; @@ -38,7 +48,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) void *priv; int idx; u32 val; - u8 tid; + u8 tid = 0; if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) goto free; @@ -56,15 +66,16 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) priv = msta = container_of(wcid, struct mt7603_sta, wcid); val = le32_to_cpu(txd[0]); - skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); - val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); txd[0] = cpu_to_le32(val); sta = container_of(priv, struct ieee80211_sta, drv_priv); hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE]; - tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + if (ieee80211_is_data_qos(hdr->frame_control)) + tid = *ieee80211_get_qos_ctl(hdr) & + IEEE80211_QOS_CTL_TAG1D_MASK; + skb_set_queue_mapping(skb, tid_to_ac[tid]); ieee80211_sta_set_buffered(sta, tid, true); spin_lock_bh(&dev->ps_lock); From 9379df2fd9234e3b67a23101c2370c99f6af6d77 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 14 Dec 2019 00:15:26 +0100 Subject: [PATCH 086/168] mt76: clear skb pointers from rx aggregation reorder buffer during cleanup During the cleanup of the aggregation session, a rx handler (or release timer) on another CPU might still hold a pointer to the reorder buffer and could attempt to release some packets. Clearing pointers during cleanup avoids a theoretical use-after-free bug here. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/agg-rx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c index a4c64ae8fb1a..f77f03530259 100644 --- a/drivers/net/wireless/mediatek/mt76/agg-rx.c +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c @@ -276,6 +276,7 @@ static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid) if (!skb) continue; + tid->reorder_buf[i] = NULL; tid->nframes--; dev_kfree_skb(skb); } From ff913979a2d33175ebae0d17e5633917c833fe67 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 16 Dec 2019 14:05:05 +0100 Subject: [PATCH 087/168] mt76: mt7615: introduce LED support Initialize brightness_set and blink_set callbacks to mt7615_led_set_brightness and mt7615_led_set_blink in order to enable LED support in mt7615 driver Tested-by: Deng Qingfang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 58 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 18 ++++++ 2 files changed, 76 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index a2405e10879c..c16df56b0717 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -208,6 +208,58 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; +static void +mt7615_led_set_config(struct led_classdev *led_cdev, + u8 delay_on, u8 delay_off) +{ + struct mt7615_dev *dev; + struct mt76_dev *mt76; + u32 val, addr; + + mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); + dev = container_of(mt76, struct mt7615_dev, mt76); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); + + addr = mt7615_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); + mt76_wr(dev, addr, val); + addr = mt7615_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); + mt76_wr(dev, addr, val); + + val = MT_LED_CTRL_REPLAY(mt76->led_pin) | + MT_LED_CTRL_KICK(mt76->led_pin); + if (mt76->led_al) + val |= MT_LED_CTRL_POLARITY(mt76->led_pin); + addr = mt7615_reg_map(dev, MT_LED_CTRL); + mt76_wr(dev, addr, val); +} + +static int +mt7615_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + u8 delta_on, delta_off; + + delta_off = max_t(u8, *delay_off / 10, 1); + delta_on = max_t(u8, *delay_on / 10, 1); + + mt7615_led_set_config(led_cdev, delta_on, delta_off); + + return 0; +} + +static void +mt7615_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + if (!brightness) + mt7615_led_set_config(led_cdev, 0, 0xff); + else + mt7615_led_set_config(led_cdev, 0xff, 0); +} + static void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) @@ -402,6 +454,12 @@ int mt7615_register_device(struct mt7615_dev *dev) mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + dev->mt76.led_cdev.brightness_set = mt7615_led_set_brightness; + dev->mt76.led_cdev.blink_set = mt7615_led_set_blink; + } + ret = mt76_register_device(&dev->mt76, true, mt7615_rates, ARRAY_SIZE(mt7615_rates)); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 46db0faae93d..b0c14067a832 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -351,6 +351,24 @@ #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) +#define MT_LED_BASE_PHYS 0x80024000 +#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) + +#define MT_LED_CTRL MT_LED_PHYS(0x00) + +#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) +#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) +#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) +#define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) +#define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) +#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) + +#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) +#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) + #define MT_EFUSE_BASE 0x81070000 #define MT_EFUSE_BASE_CTRL 0x000 #define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) From d1ff4a3c2fabe66d7efdbc19d0af4ecc448f1aa4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 16 Dec 2019 14:19:58 +0100 Subject: [PATCH 088/168] mt76: mt76x02: simplify led reg definitions Rely on FIELD_PREP macro for led register definitions and remove open coding Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 12 +++--------- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 6 +++--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 21c0f351fa09..3e722276b5c2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -235,15 +235,9 @@ #define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n)) #define MT_LED_S1_BASE 0x0780 #define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n)) -#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) -#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \ - MT_LED_STATUS_OFF_MASK) -#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) -#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \ - MT_LED_STATUS_ON_MASK) -#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8) -#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \ - MT_LED_STATUS_DURATION_MASK) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 8) #define MT_FCE_PSE_CTRL 0x0800 #define MT_FCE_PARAMETERS 0x0804 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 15a24e04a194..28d8d447fc76 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -96,9 +96,9 @@ mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on, mt76); u32 val; - val = MT_LED_STATUS_DURATION(0xff) | - MT_LED_STATUS_OFF(delay_off) | - MT_LED_STATUS_ON(delay_on); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); mt76_wr(dev, MT_LED_S0(mdev->led_pin), val); mt76_wr(dev, MT_LED_S1(mdev->led_pin), val); From ff44d907ee102feb3a1b64862380ea5264673876 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 16 Dec 2019 14:19:59 +0100 Subject: [PATCH 089/168] mt76: mt7603: simplify led reg definitions Rely on FIELD_PREP macro for led register definitions and remove open coding Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/init.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt7603/regs.h | 15 +++------------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index af346d479258..32fdb81b2bb0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -363,9 +363,9 @@ static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, mt76); u32 val, addr; - val = MT_LED_STATUS_DURATION(0xffff) | - MT_LED_STATUS_OFF(delay_off) | - MT_LED_STATUS_ON(delay_on); + val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | + FIELD_PREP(MT_LED_STATUS_OFF, delay_off) | + FIELD_PREP(MT_LED_STATUS_ON, delay_on); addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); mt76_wr(dev, addr, val); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 6e23ed3dfdff..6741e6907194 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -585,18 +585,9 @@ enum { #define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) #define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) -#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) -#define MT_LED_STATUS_OFF(_v) (((_v) << \ - __ffs(MT_LED_STATUS_OFF_MASK)) & \ - MT_LED_STATUS_OFF_MASK) -#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) -#define MT_LED_STATUS_ON(_v) (((_v) << \ - __ffs(MT_LED_STATUS_ON_MASK)) & \ - MT_LED_STATUS_ON_MASK) -#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 0) -#define MT_LED_STATUS_DURATION(_v) (((_v) << \ - __ffs(MT_LED_STATUS_DURATION_MASK)) &\ - MT_LED_STATUS_DURATION_MASK) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) #define MT_CLIENT_BASE_PHYS_ADDR 0x800c0000 From cd736c474712be9155f2309772f55b09817673da Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 16 Dec 2019 19:32:10 +0100 Subject: [PATCH 090/168] mt76: fix compilation warning in mt76_eeprom_override() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compilation warning in mt76_eeprom_override routine when CONFIG_OF is not set and label 'out' is not actually used drivers/net/wireless/mediatek/mt76/eeprom.c: In function ‘mt76_eeprom_override’: drivers/net/wireless/mediatek/mt76/eeprom.c:100:1: warning: label ‘out’ defined but not used [-Wunused-label] Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/eeprom.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 8f2693748faf..c236e303ccfd 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -87,17 +87,14 @@ mt76_eeprom_override(struct mt76_dev *dev) { #ifdef CONFIG_OF struct device_node *np = dev->dev->of_node; - const u8 *mac; + const u8 *mac = NULL; - if (!np) - goto out; - - mac = of_get_mac_address(np); - if (!IS_ERR(mac)) + if (np) + mac = of_get_mac_address(np); + if (!IS_ERR_OR_NULL(mac)) ether_addr_copy(dev->macaddr, mac); #endif -out: if (!is_valid_ether_addr(dev->macaddr)) { eth_random_addr(dev->macaddr); dev_info(dev->dev, From 2cad515ece8ad4e8d696ccb5cd46940d7fcca2e3 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Tue, 24 Dec 2019 09:24:25 +0800 Subject: [PATCH 091/168] mt76: mt7615: add missing settings for simultaneous dual-band support MT7615 supports dual-wiphy which means that it can run on 2.4G and 5GHz channels simultaneously, and driver should configure each band. Add missing register settings, and refine band related definitions to avoid duplicate codes. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/init.c | 50 ++++++------- .../net/wireless/mediatek/mt76/mt7615/mac.c | 71 +++++++------------ .../net/wireless/mediatek/mt76/mt7615/regs.h | 52 +++++--------- 3 files changed, 68 insertions(+), 105 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index c16df56b0717..a14fd9587b70 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -28,17 +28,17 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN | MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN); - val = mt76_rmw(dev, MT_TMAC_TRCR0, + val = mt76_rmw(dev, MT_TMAC_TRCR(0), MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); - mt76_wr(dev, MT_TMAC_TRCR1, val); + mt76_wr(dev, MT_TMAC_TRCR(1), val); val = MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT); - mt76_wr(dev, MT_AGG_ACR0, val); - mt76_wr(dev, MT_AGG_ACR1, val); + mt76_wr(dev, MT_AGG_ACR(0), val); + mt76_wr(dev, MT_AGG_ACR(1), val); mt76_rmw_field(dev, MT_TMAC_CTCR0, MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); @@ -59,25 +59,27 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); - mt76_wr(dev, MT_AGG_ARUCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); + val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), 2) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1); + mt76_wr(dev, MT_AGG_ARUCR(0), val); + mt76_wr(dev, MT_AGG_ARUCR(1), val); - mt76_wr(dev, MT_AGG_ARDCR, - FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | - FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); + val = FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1); + mt76_wr(dev, MT_AGG_ARDCR(0), val); + mt76_wr(dev, MT_AGG_ARDCR(1), val); mt76_wr(dev, MT_AGG_ARCR, (FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | @@ -93,8 +95,8 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_DMA_RCFR0_RX_DROPPED_MCAST; set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); - mt76_rmw(dev, MT_DMA_BN0RCFR0, mask, set); - mt76_rmw(dev, MT_DMA_BN1RCFR0, mask, set); + mt76_rmw(dev, MT_DMA_RCFR0(0), mask, set); + mt76_rmw(dev, MT_DMA_RCFR0(1), mask, set); for (i = 0; i < MT7615_WTBL_SIZE; i++) mt7615_mac_wtbl_update(dev, i, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 1b52d8b79496..885a57df76eb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -69,7 +69,7 @@ void mt7615_mac_set_timing(struct mt7615_phy *phy) s16 coverage_class = phy->coverage_class; struct mt7615_dev *dev = phy->dev; bool ext_phy = phy != &dev->phy; - u32 val, reg_offset, reg = ext_phy ? MT_TMAC_ICR1 : MT_TMAC_ICR0; + u32 val, reg_offset; u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | @@ -103,7 +103,7 @@ void mt7615_mac_set_timing(struct mt7615_phy *phy) mt76_wr(dev, MT_TMAC_CDTR, cck + reg_offset); mt76_wr(dev, MT_TMAC_ODTR, ofdm + reg_offset); - mt76_wr(dev, reg, + mt76_wr(dev, MT_TMAC_ICR(ext_phy), FIELD_PREP(MT_IFS_EIFS, 360) | FIELD_PREP(MT_IFS_RIFS, 2) | FIELD_PREP(MT_IFS_SIFS, sifs) | @@ -114,15 +114,14 @@ void mt7615_mac_set_timing(struct mt7615_phy *phy) else val = MT7615_CFEND_RATE_11B; - if (ext_phy) { - mt76_rmw_field(dev, MT_AGG_ACR1, MT_AGG_ACR_CFEND_RATE, val); + mt76_rmw_field(dev, MT_AGG_ACR(ext_phy), MT_AGG_ACR_CFEND_RATE, val); + if (ext_phy) mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); - } else { - mt76_rmw_field(dev, MT_AGG_ACR0, MT_AGG_ACR_CFEND_RATE, val); + else mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); - } + } int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) @@ -1322,21 +1321,12 @@ mt7615_mac_set_default_sensitivity(struct mt7615_phy *phy) struct mt7615_dev *dev = phy->dev; bool ext_phy = phy != &dev->phy; - if (!ext_phy) { - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(0x13c)); - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(0x92)); - } else { - mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_OFDM_MASK, - MT_WF_PHY_B1_PD_OFDM(0x13c)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(0x92)); - } + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, 0x13c)); + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, 0x92)); phy->ofdm_sensitivity = -98; phy->cck_sensitivity = -110; @@ -1353,19 +1343,19 @@ void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) goto out; if (enable) { - mt76_set(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); - mt76_set(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_BLK); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); if (is_mt7622(&dev->mt76)) { mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7 << 8); mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7); } } else { - mt76_clear(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); - mt76_clear(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_BLK); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); } mt7615_mac_set_default_sensitivity(&dev->phy); @@ -1453,24 +1443,15 @@ mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, if (ofdm) { val = *sensitivity * 2 + 512; - if (!ext_phy) - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(val)); - else - mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_OFDM_MASK, - MT_WF_PHY_B1_PD_OFDM(val)); + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, val)); } else { val = *sensitivity + 256; if (!ext_phy) - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(val)); - else - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(val)); + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, val)); } phy->last_cca_adj = jiffies; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index b0c14067a832..c42f3a47a2f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -81,7 +81,7 @@ #define MT_WF_PHY_BASE 0x10000 #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) -#define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + ((n) * 0x400)) +#define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + (n) * 0x400) #define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) #define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9)) @@ -94,26 +94,19 @@ #define MT_WF_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) #define MT_WF_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) -#define MT_WF_PHY_B0_MIN_PRI_PWR MT_WF_PHY(0x229c) -#define MT_WF_PHY_B0_PD_OFDM_MASK GENMASK(28, 20) -#define MT_WF_PHY_B0_PD_OFDM(v) ((v) << 20) -#define MT_WF_PHY_B0_PD_BLK BIT(19) - -#define MT_WF_PHY_B1_MIN_PRI_PWR MT_WF_PHY(0x084) -#define MT_WF_PHY_B1_PD_OFDM_MASK GENMASK(24, 16) -#define MT_WF_PHY_B1_PD_OFDM(v) ((v) << 16) -#define MT_WF_PHY_B1_PD_BLK BIT(25) +#define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c) +#define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \ + GENMASK(28, 20)) +#define MT_WF_PHY_PD_OFDM(_phy, v) ((v) << ((_phy) ? 16 : 20)) +#define MT_WF_PHY_PD_BLK(_phy) ((_phy) ? BIT(25) : BIT(19)) #define MT_WF_PHY_RXTD_BASE MT_WF_PHY(0x2200) #define MT_WF_PHY_RXTD(_n) (MT_WF_PHY_RXTD_BASE + ((_n) << 2)) -#define MT_WF_PHY_B0_RXTD_CCK_PD MT_WF_PHY(0x2310) -#define MT_WF_PHY_B0_PD_CCK_MASK GENMASK(8, 1) -#define MT_WF_PHY_B0_PD_CCK(v) ((v) << 1) - -#define MT_WF_PHY_B1_RXTD_CCK_PD MT_WF_PHY(0x2314) -#define MT_WF_PHY_B1_PD_CCK_MASK GENMASK(31, 24) -#define MT_WF_PHY_B1_PD_CCK(v) ((v) << 24) +#define MT_WF_PHY_RXTD_CCK_PD(_phy) MT_WF_PHY((_phy) ? 0x2314 : 0x2310) +#define MT_WF_PHY_PD_CCK_MASK(_phy) (_phy) ? GENMASK(31, 24) : \ + GENMASK(8, 1) +#define MT_WF_PHY_PD_CCK(_phy, v) ((v) << ((_phy) ? 24 : 1)) #define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00) #define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2)) @@ -127,15 +120,6 @@ #define MT_CFG_CCR_MAC_D1_2X_GC_EN BIT(30) #define MT_CFG_CCR_MAC_D0_2X_GC_EN BIT(31) -#define MT_DBDC_CTRL0 MT_WF_CFG(0x050) -#define MT_DBDC_CTRL0_OMAC_00_04 GENMASK(4, 0) -#define MT_DBDC_CTRL0_OMAC_11_1F GENMASK(19, 5) -#define MT_DBDC_CTRL0_MGMT GENMASK(21, 20) -#define MT_DBDC_CTRL0_WMM GENMASK(25, 22) -#define MT_DBDC_CTRL0_DBDC_EN BIT(31) - -#define MT_DBDC_CTRL1 MT_WF_CFG(0x054) - #define MT_WF_AGG_BASE 0x20a00 #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) @@ -146,8 +130,8 @@ #define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) #define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) -#define MT_AGG_ARUCR MT_WF_AGG(0x018) -#define MT_AGG_ARDCR MT_WF_AGG(0x01c) +#define MT_AGG_ARUCR(_band) MT_WF_AGG(0x018 + (_band) * 0x100) +#define MT_AGG_ARDCR(_band) MT_WF_AGG(0x01c + (_band) * 0x100) #define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) #define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ @@ -157,8 +141,7 @@ #define MT_AGG_ASRCR1 MT_WF_AGG(0x064) #define MT_AGG_ASRCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(5, 0)) -#define MT_AGG_ACR0 MT_WF_AGG(0x070) -#define MT_AGG_ACR1 MT_WF_AGG(0x170) +#define MT_AGG_ACR(_band) MT_WF_AGG(0x070 + (_band) * 0x100) #define MT_AGG_ACR_NO_BA_RULE BIT(0) #define MT_AGG_ACR_NO_BA_AR_RULE BIT(1) #define MT_AGG_ACR_PKT_TIME_EN BIT(2) @@ -185,13 +168,11 @@ #define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) #define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) -#define MT_TMAC_TRCR0 MT_WF_TMAC(0x09c) -#define MT_TMAC_TRCR1 MT_WF_TMAC(0x070) +#define MT_TMAC_TRCR(_band) MT_WF_TMAC((_band) ? 0x070 : 0x09c) #define MT_TMAC_TRCR_CCA_SEL GENMASK(31, 30) #define MT_TMAC_TRCR_SEC_CCA_SEL GENMASK(29, 28) -#define MT_TMAC_ICR0 MT_WF_TMAC(0x0a4) -#define MT_TMAC_ICR1 MT_WF_TMAC(0x074) +#define MT_TMAC_ICR(_band) MT_WF_TMAC((_band) ? 0x074 : 0x0a4) #define MT_IFS_EIFS GENMASK(8, 0) #define MT_IFS_RIFS GENMASK(14, 10) #define MT_IFS_SIFS GENMASK(22, 16) @@ -255,8 +236,7 @@ #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) -#define MT_DMA_BN0RCFR0 MT_WF_DMA(0x070) -#define MT_DMA_BN1RCFR0 MT_WF_DMA(0x0b0) +#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) #define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2) #define MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR BIT(3) #define MT_DMA_RCFR0_MCU_RX_CTL_BAR BIT(4) From 4fe9218c5eda4271d9d914c72dd2efb6a9eff680 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 23 Dec 2019 04:11:38 +0800 Subject: [PATCH 092/168] mt76: mt7615: rework set_channel function No need to send both MCU_EXT_CMD_SET_RX_PATH and MCU_EXT_CMD_CHANNEL_SWITCH together to MCU. Split them out by passing the proper command in the corresponding flow. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 5 ++++- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 18 ++++-------------- .../net/wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 52c502af4d4d..14bcff97781e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -11,6 +11,7 @@ #include #include #include "mt7615.h" +#include "mcu.h" static bool mt7615_dev_running(struct mt7615_dev *dev) { @@ -49,6 +50,8 @@ static int mt7615_start(struct ieee80211_hw *hw) mt7615_mac_enable_nf(dev, 1); } + mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); if (running) @@ -226,7 +229,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) phy->dfs_state = -1; mt76_set_channel(phy->mt76); - ret = mt7615_mcu_set_channel(phy); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); if (ret) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index c8d6a36f5d0a..219c872a296d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1364,12 +1364,11 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) &req, sizeof(req), false); } -int mt7615_mcu_set_channel(struct mt7615_phy *phy) +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) { struct mt7615_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; - u8 n_chains = hweight8(phy->mt76->antenna_mask); struct { u8 control_chan; u8 center_chan; @@ -1391,11 +1390,10 @@ int mt7615_mcu_set_channel(struct mt7615_phy *phy) } req = { .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), - .tx_streams = n_chains, - .rx_streams_mask = n_chains, + .tx_streams = hweight8(phy->mt76->antenna_mask), + .rx_streams_mask = phy->chainmask, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - int ret; if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; @@ -1434,15 +1432,7 @@ int mt7615_mcu_set_channel(struct mt7615_phy *phy) } memset(req.txpower_sku, 0x3f, 49); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, - &req, sizeof(req), true); - if (ret) - return ret; - - req.rx_streams_mask = phy->chainmask; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, - &req, sizeof(req), true); + return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index eaafae9cc279..1edcc5599ecc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -253,7 +253,7 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool en); int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en); -int mt7615_mcu_set_channel(struct mt7615_phy *phy); +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, From 0d88aea88f1d2c9960d00ac4fc4b7ed71864d37e Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 23 Dec 2019 04:11:39 +0800 Subject: [PATCH 093/168] mt76: mt7615: add set_antenna callback Add a set_antenna callback to setup per phy tx/rx streams. Signed-off-by: Shayne Chen Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 14bcff97781e..93fb619626a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -642,6 +642,32 @@ mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) mt7615_mac_set_timing(phy); } +static int +mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int max_nss = hweight8(hw->wiphy->available_antennas_tx); + bool ext_phy = phy != &dev->phy; + + if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + return -EINVAL; + + if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) + tx_ant = BIT(ffs(tx_ant) - 1) - 1; + + mutex_lock(&dev->mt76.mutex); + + phy->mt76->antenna_mask = tx_ant; + phy->chainmask = ext_phy ? tx_ant << 2 : tx_ant; + + mt76_set_stream_caps(&dev->mt76, true); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + const struct ieee80211_ops mt7615_ops = { .tx = mt7615_tx, .start = mt7615_start, @@ -666,5 +692,6 @@ const struct ieee80211_ops mt7615_ops = { .channel_switch_beacon = mt7615_channel_switch_beacon, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, + .set_antenna = mt7615_set_antenna, .set_coverage_class = mt7615_set_coverage_class, }; From 31affc967f0461b1a88bcc4669e1e6f84b985177 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 28 Dec 2019 11:05:10 +0800 Subject: [PATCH 094/168] mt76: mt7615: report TSF information This adds a get_tsf() callback for ibss. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 93fb619626a2..c75347699512 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -633,6 +633,26 @@ mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_STA_NOTEXIST); } +static u64 +mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + union { + u64 t64; + u32 t32[2]; + } tsf; + + mutex_lock(&dev->mt76.mutex); + + mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1); + + mutex_unlock(&dev->mt76.mutex); + + return tsf.t64; +} + static void mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { @@ -690,6 +710,7 @@ const struct ieee80211_ops mt7615_ops = { .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, .channel_switch_beacon = mt7615_channel_switch_beacon, + .get_tsf = mt7615_get_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, .set_antenna = mt7615_set_antenna, From 679b23fef8a45575e818d629110325d7f1003f94 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 28 Dec 2019 11:05:11 +0800 Subject: [PATCH 095/168] mt76: mt7615: add per-phy mib statistics Update per-phy mib counters every 500ms. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 56 +++++++++++++------ .../wireless/mediatek/mt76/mt7615/mt7615.h | 9 +++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 16 ++++-- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 885a57df76eb..004ab588dbee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1461,25 +1461,14 @@ static void mt7615_mac_scs_check(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; - u32 val, rts_cnt = 0, rts_retries_cnt = 0, rts_err_rate = 0; + struct mib_stats *mib = &phy->mib; + u32 val, rts_err_rate = 0; u32 mdrdy_cck, mdrdy_ofdm, pd_cck, pd_ofdm; bool ext_phy = phy != &dev->phy; - int i; if (!dev->scs_en) return; - for (i = 0; i < 4; i++) { - u32 data; - - val = mt76_rr(dev, MT_MIB_MB_SDR(ext_phy, i)); - data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (data > rts_retries_cnt) { - rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - rts_retries_cnt = data; - } - } - val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS0(ext_phy)); pd_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_CCK, val); pd_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_OFDM, val); @@ -1492,9 +1481,9 @@ mt7615_mac_scs_check(struct mt7615_phy *phy) phy->false_cca_cck = pd_cck - mdrdy_cck; mt7615_mac_cca_stats_reset(phy); - if (rts_cnt + rts_retries_cnt) - rts_err_rate = MT_FRAC(rts_retries_cnt, - rts_cnt + rts_retries_cnt); + if (mib->rts_cnt + mib->rts_retries_cnt) + rts_err_rate = MT_FRAC(mib->rts_retries_cnt, + mib->rts_cnt + mib->rts_retries_cnt); /* cck */ mt7615_mac_adjust_sensitivity(phy, rts_err_rate, false); @@ -1569,6 +1558,36 @@ void mt7615_update_channel(struct mt76_dev *mdev) mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +static void +mt7615_mac_update_mib_stats(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + bool ext_phy = phy != &dev->phy; + int i; + + memset(mib, 0, sizeof(*mib)); + + mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); + + for (i = 0; i < 4; i++) { + u32 data, val, val2; + + val = mt76_get_field(dev, MT_MIB_MB_SDR1(ext_phy, i), + MT_MIB_ACK_FAIL_COUNT_MASK); + if (val > mib->ack_fail_cnt) + mib->ack_fail_cnt = val; + + val2 = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); + data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val2); + if (data > mib->rts_retries_cnt) { + mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val2); + mib->rts_retries_cnt = data; + } + } +} + void mt7615_mac_work(struct work_struct *work) { struct mt7615_dev *dev; @@ -1583,9 +1602,12 @@ void mt7615_mac_work(struct work_struct *work) if (++dev->mac_work_count == 5) { ext_phy = mt7615_ext_phy(dev); + mt7615_mac_update_mib_stats(&dev->phy); mt7615_mac_scs_check(&dev->phy); - if (ext_phy) + if (ext_phy) { + mt7615_mac_update_mib_stats(ext_phy); mt7615_mac_scs_check(ext_phy); + } dev->mac_work_count = 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 1edcc5599ecc..e50b02b58461 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -87,6 +87,13 @@ struct mt7615_vif { struct mt7615_sta sta; }; +struct mib_stats { + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; +}; + struct mt7615_phy { struct mt76_phy *mt76; struct mt7615_dev *dev; @@ -112,6 +119,8 @@ struct mt7615_phy { __le32 rx_ampdu_ts; u32 ampdu_ref; + + struct mib_stats mib; }; struct mt7615_dev { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index c42f3a47a2f1..33e6087b58fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -313,10 +313,9 @@ #define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs)) #define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c) -#define MT_MIB_MB_SDR(_band, n) MT_WF_MIB(0x100 + ((_band) << 9) + \ - ((n) << 4)) -#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_SDR3(n) MT_WF_MIB(0x014 + ((n) << 9)) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0) #define MT_MIB_SDR9(n) MT_WF_MIB(0x02c + ((n) << 9)) #define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) @@ -329,6 +328,15 @@ #define MT_MIB_SDR37(n) MT_WF_MIB(0x09c + ((n) << 9)) #define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(0x100 + ((_band) << 9) + \ + ((n) << 4)) +#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(0x104 + ((_band) << 9) + \ + ((n) << 4)) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16) + #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) #define MT_LED_BASE_PHYS 0x80024000 From c388d8584bc8391c0e0a4cdb1e524eb25f3cb7e1 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 28 Dec 2019 11:05:12 +0800 Subject: [PATCH 096/168] mt76: mt7615: add a get_stats() callback Add a get_stats() callback for mib statistics. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index c75347699512..9d895c840b0c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -633,6 +633,21 @@ mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_STA_NOTEXIST); } +static int +mt7615_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + struct mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + return 0; +} + static u64 mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -710,6 +725,7 @@ const struct ieee80211_ops mt7615_ops = { .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, .channel_switch_beacon = mt7615_channel_switch_beacon, + .get_stats = mt7615_get_stats, .get_tsf = mt7615_get_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, From a3f657ec1f9ad93cf261bc4a1348b00e107eb6f9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 29 Dec 2019 11:03:05 +0100 Subject: [PATCH 097/168] mt76: move dev_irq tracepoint in mt76 module Move dev_irq tracepoint in common code in order to be reused by mt7603 and mt7615 drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7603/core.c | 3 +++ .../net/wireless/mediatek/mt76/mt7615/pci.c | 3 +++ .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 4 ++-- .../wireless/mediatek/mt76/mt76x02_trace.h | 23 ------------------- drivers/net/wireless/mediatek/mt76/trace.c | 2 ++ drivers/net/wireless/mediatek/mt76/trace.h | 23 +++++++++++++++++++ 6 files changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c index 693a91be070a..60a996b63c0c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/core.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ISC #include "mt7603.h" +#include "../trace.h" void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { @@ -20,6 +21,8 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + intr &= dev->mt76.mmio.irqmask; if (intr & MT_INT_MAC_IRQ3) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 7e3556c3b6eb..828f11087b08 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -11,6 +11,7 @@ #include "mt7615.h" #include "mac.h" +#include "../trace.h" static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, @@ -46,6 +47,8 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + intr &= dev->mt76.mmio.irqmask; if (intr & MT_INT_TX_DONE_ALL) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 094a4228b591..93d56d7ce5db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -9,7 +9,7 @@ #include "mt76x02.h" #include "mt76x02_mcu.h" -#include "mt76x02_trace.h" +#include "trace.h" static void mt76x02_pre_tbtt_tasklet(unsigned long arg) { @@ -271,7 +271,7 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; - trace_dev_irq(dev, intr, dev->mt76.mmio.irqmask); + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); intr &= dev->mt76.mmio.irqmask; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index 61ecaf0fe065..eea9afe154df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -100,29 +100,6 @@ TRACE_EVENT(mac_txstat_fetch, ) ); -TRACE_EVENT(dev_irq, - TP_PROTO(struct mt76x02_dev *dev, u32 val, u32 mask), - - TP_ARGS(dev, val, mask), - - TP_STRUCT__entry( - DEV_ENTRY - __field(u32, val) - __field(u32, mask) - ), - - TP_fast_assign( - DEV_ASSIGN; - __entry->val = val; - __entry->mask = mask; - ), - - TP_printk( - DEV_PR_FMT " %08x & %08x", - DEV_PR_ARG, __entry->val, __entry->mask - ) -); - #endif #undef TRACE_INCLUDE_PATH diff --git a/drivers/net/wireless/mediatek/mt76/trace.c b/drivers/net/wireless/mediatek/mt76/trace.c index ed3df3c8b4b3..3c63f3b8a499 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.c +++ b/drivers/net/wireless/mediatek/mt76/trace.c @@ -9,4 +9,6 @@ #define CREATE_TRACE_POINTS #include "trace.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(dev_irq); + #endif diff --git a/drivers/net/wireless/mediatek/mt76/trace.h b/drivers/net/wireless/mediatek/mt76/trace.h index 0b3e635da868..41706a874afa 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.h +++ b/drivers/net/wireless/mediatek/mt76/trace.h @@ -51,6 +51,29 @@ DEFINE_EVENT(dev_reg_evt, reg_wr, TP_ARGS(dev, reg, val) ); +TRACE_EVENT(dev_irq, + TP_PROTO(struct mt76_dev *dev, u32 val, u32 mask), + + TP_ARGS(dev, val, mask), + + TP_STRUCT__entry( + DEV_ENTRY + __field(u32, val) + __field(u32, mask) + ), + + TP_fast_assign( + DEV_ASSIGN; + __entry->val = val; + __entry->mask = mask; + ), + + TP_printk( + DEV_PR_FMT " %08x & %08x", + DEV_PR_ARG, __entry->val, __entry->mask + ) +); + #endif #undef TRACE_INCLUDE_PATH From 5498974bd5d060e203e814789a16bb347cc5b880 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 29 Dec 2019 11:03:06 +0100 Subject: [PATCH 098/168] mt76: move mac_txdone tracepoint in mt76 module Move mac_txdone tracepoint in common code in order to be reused by mt7603 and mt7615 drivers Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7603/mac.c | 3 ++ .../net/wireless/mediatek/mt76/mt7615/mac.c | 3 ++ .../net/wireless/mediatek/mt76/mt76x02_mac.c | 3 +- .../wireless/mediatek/mt76/mt76x02_trace.h | 23 ------------- drivers/net/wireless/mediatek/mt76/trace.c | 1 + drivers/net/wireless/mediatek/mt76/trace.h | 33 +++++++++++++++++-- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 2a384fd0f088..8f5ca9283f7d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -4,6 +4,7 @@ #include #include "mt7603.h" #include "mac.h" +#include "../trace.h" #define MT_PSE_PAGE_SIZE 128 @@ -1193,6 +1194,8 @@ mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, if (pid < MT_PACKET_ID_FIRST) return false; + trace_mac_txdone(mdev, sta->wcid.idx, pid); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); if (skb) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 004ab588dbee..de80e8c7245b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -10,6 +10,7 @@ #include #include #include "mt7615.h" +#include "../trace.h" #include "../dma.h" #include "mac.h" @@ -1218,6 +1219,8 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev, if (pid < MT_PACKET_ID_FIRST) return false; + trace_mac_txdone(mdev, sta->wcid.idx, pid); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); if (skb) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 484cb5770fd9..8345f7617fef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -6,6 +6,7 @@ #include "mt76x02.h" #include "mt76x02_trace.h" +#include "trace.h" void mt76x02_mac_reset_counters(struct mt76x02_dev *dev) { @@ -910,7 +911,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, txwi_ptr = mt76_get_txwi_ptr(mdev, e->txwi); txwi = (struct mt76x02_txwi *)txwi_ptr; - trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid); + trace_mac_txdone(mdev, txwi->wcid, txwi->pktid); mt76_tx_complete_skb(mdev, e->skb); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index eea9afe154df..6a98092e996b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -20,7 +20,6 @@ #define DEV_PR_ARG __entry->wiphy_name #define TXID_ENTRY __field(u8, wcid) __field(u8, pktid) -#define TXID_ASSIGN __entry->wcid = wcid; __entry->pktid = pktid #define TXID_PR_FMT " [%d:%d]" #define TXID_PR_ARG __entry->wcid, __entry->pktid @@ -36,28 +35,6 @@ DECLARE_EVENT_CLASS(dev_evt, TP_printk(DEV_PR_FMT, DEV_PR_ARG) ); -DECLARE_EVENT_CLASS(dev_txid_evt, - TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), - TP_ARGS(dev, wcid, pktid), - TP_STRUCT__entry( - DEV_ENTRY - TXID_ENTRY - ), - TP_fast_assign( - DEV_ASSIGN; - TXID_ASSIGN; - ), - TP_printk( - DEV_PR_FMT TXID_PR_FMT, - DEV_PR_ARG, TXID_PR_ARG - ) -); - -DEFINE_EVENT(dev_txid_evt, mac_txdone_add, - TP_PROTO(struct mt76x02_dev *dev, u8 wcid, u8 pktid), - TP_ARGS(dev, wcid, pktid) -); - DEFINE_EVENT(dev_evt, mac_txstat_poll, TP_PROTO(struct mt76x02_dev *dev), TP_ARGS(dev) diff --git a/drivers/net/wireless/mediatek/mt76/trace.c b/drivers/net/wireless/mediatek/mt76/trace.c index 3c63f3b8a499..f199fcd2a63d 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.c +++ b/drivers/net/wireless/mediatek/mt76/trace.c @@ -9,6 +9,7 @@ #define CREATE_TRACE_POINTS #include "trace.h" +EXPORT_TRACEPOINT_SYMBOL_GPL(mac_txdone); EXPORT_TRACEPOINT_SYMBOL_GPL(dev_irq); #endif diff --git a/drivers/net/wireless/mediatek/mt76/trace.h b/drivers/net/wireless/mediatek/mt76/trace.h index 41706a874afa..c3d0ef8e2890 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.h +++ b/drivers/net/wireless/mediatek/mt76/trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEVICE_ASSIGN strlcpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name @@ -24,6 +24,11 @@ #define REG_PR_FMT " %04x=%08x" #define REG_PR_ARG __entry->reg, __entry->val +#define TXID_ENTRY __field(u8, wcid) __field(u8, pktid) +#define TXID_ASSIGN __entry->wcid = wcid; __entry->pktid = pktid +#define TXID_PR_FMT " [%d:%d]" +#define TXID_PR_ARG __entry->wcid, __entry->pktid + DECLARE_EVENT_CLASS(dev_reg_evt, TP_PROTO(struct mt76_dev *dev, u32 reg, u32 val), TP_ARGS(dev, reg, val), @@ -32,7 +37,7 @@ DECLARE_EVENT_CLASS(dev_reg_evt, REG_ENTRY ), TP_fast_assign( - DEV_ASSIGN; + DEVICE_ASSIGN; REG_ASSIGN; ), TP_printk( @@ -63,7 +68,7 @@ TRACE_EVENT(dev_irq, ), TP_fast_assign( - DEV_ASSIGN; + DEVICE_ASSIGN; __entry->val = val; __entry->mask = mask; ), @@ -74,6 +79,28 @@ TRACE_EVENT(dev_irq, ) ); +DECLARE_EVENT_CLASS(dev_txid_evt, + TP_PROTO(struct mt76_dev *dev, u8 wcid, u8 pktid), + TP_ARGS(dev, wcid, pktid), + TP_STRUCT__entry( + DEV_ENTRY + TXID_ENTRY + ), + TP_fast_assign( + DEVICE_ASSIGN; + TXID_ASSIGN; + ), + TP_printk( + DEV_PR_FMT TXID_PR_FMT, + DEV_PR_ARG, TXID_PR_ARG + ) +); + +DEFINE_EVENT(dev_txid_evt, mac_txdone, + TP_PROTO(struct mt76_dev *dev, u8 wcid, u8 pktid), + TP_ARGS(dev, wcid, pktid) +); + #endif #undef TRACE_INCLUDE_PATH From 9cd82366a7c09a7cf2461fdb6c38ec603005fab4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 29 Dec 2019 11:03:07 +0100 Subject: [PATCH 099/168] mt76: mt7615: add tracing support Introduce token tracing support in mt7615_mac_tx_free routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/Makefile | 4 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 7 ++- .../mediatek/mt76/mt7615/mt7615_trace.h | 56 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/trace.c | 12 ++++ 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/trace.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile index 5aaac69849d6..dcd6b0e7ce84 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -2,5 +2,7 @@ obj-$(CONFIG_MT7615E) += mt7615e.o +CFLAGS_trace.o := -I$(src) + mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ - debugfs.o + debugfs.o trace.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index de80e8c7245b..16233ced0058 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -12,6 +12,7 @@ #include "mt7615.h" #include "../trace.h" #include "../dma.h" +#include "mt7615_trace.h" #include "mac.h" #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) @@ -1300,13 +1301,17 @@ void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); for (i = 0; i < count; i++) { + u16 token = le16_to_cpu(free->token[i]); + spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, le16_to_cpu(free->token[i])); + txwi = idr_remove(&dev->token, token); spin_unlock_bh(&dev->token_lock); if (!txwi) continue; + trace_mac_tx_free(dev, token); + mt7615_txp_skb_unmap(mdev, txwi); if (txwi->skb) { mt76_tx_complete_skb(mdev, txwi->skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h new file mode 100644 index 000000000000..d3eb49d83b98 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (C) 2019 Lorenzo Bianconi + */ + +#if !defined(__MT7615_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT7615_TRACE_H + +#include +#include "mt7615.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mt7615 + +#define MAXNAME 32 +#define DEV_ENTRY __array(char, wiphy_name, 32) +#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ + wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) +#define DEV_PR_FMT "%s" +#define DEV_PR_ARG __entry->wiphy_name + +#define TOKEN_ENTRY __field(u16, token) +#define TOKEN_ASSIGN __entry->token = token +#define TOKEN_PR_FMT " %d" +#define TOKEN_PR_ARG __entry->token + +DECLARE_EVENT_CLASS(dev_token, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token), + TP_STRUCT__entry( + DEV_ENTRY + TOKEN_ENTRY + ), + TP_fast_assign( + DEV_ASSIGN; + TOKEN_ASSIGN; + ), + TP_printk( + DEV_PR_FMT TOKEN_PR_FMT, + DEV_PR_ARG, TOKEN_PR_ARG + ) +); + +DEFINE_EVENT(dev_token, mac_tx_free, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mt7615_trace + +#include diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/trace.c b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c new file mode 100644 index 000000000000..6c02d5aff68f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Lorenzo Bianconi + */ + +#include + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt7615_trace.h" + +#endif From d9d8be11f88bce9e09149fe4e3aae68946d48a1b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 29 Dec 2019 11:03:08 +0100 Subject: [PATCH 100/168] mt76: mt76x2: get rid of leftover target Remove tracing leftover target in mt76x2 Makefile Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile index 7b2b187fbf47..caf089538c11 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/Makefile @@ -13,5 +13,3 @@ mt76x2e-y := \ mt76x2u-y := \ usb.o usb_init.o usb_main.o usb_mac.o usb_mcu.o \ usb_phy.o - -CFLAGS_pci_trace.o := -I$(src) From 2ce73efe0f8e5947c116870166902bad15c2215c Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 31 Dec 2019 13:25:23 +0100 Subject: [PATCH 101/168] mt76: mt7615: initialize radar specs from host driver Introduce dfs radar pattern specs in mt7615 driver in order to make dfs debugging easier. Radar pulse/pattern thresholds are taken from vendor SDK. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 78 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mac.h | 32 ++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 48 ++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.h | 1 + .../wireless/mediatek/mt76/mt7615/mt7615.h | 7 ++ 5 files changed, 166 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 16233ced0058..49924d502daa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -17,6 +17,44 @@ #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) +static const struct mt7615_dfs_radar_spec etsi_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [5] = { 1, 0, 6, 32, 28, 0, 17, 990, 5010, 1, 1 }, + [6] = { 1, 0, 9, 32, 28, 0, 27, 615, 5010, 1, 1 }, + [7] = { 1, 0, 15, 32, 28, 0, 27, 240, 445, 1, 1 }, + [8] = { 1, 0, 12, 32, 28, 0, 42, 240, 510, 1, 1 }, + [9] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 12, 32, 28 }, + [10] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 15, 32, 24 }, + [11] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 18, 32, 28 }, + [12] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 27, 32, 24 }, + }, +}; + +static const struct mt7615_dfs_radar_spec fcc_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 9, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 255, 28, 0, 13, 323, 343, 1, 32 }, + }, +}; + +static const struct mt7615_dfs_radar_spec jp_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 8, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 32, 28, 0, 13, 323, 343, 1, 32 }, + [13] = { 1, 0, 8, 32, 28, 0, 14, 3836, 3856, 1, 1 }, + [14] = { 1, 0, 8, 32, 28, 0, 14, 3990, 4010, 1, 1 }, + }, +}; + static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) { @@ -1685,6 +1723,40 @@ static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) return 0; } +static int +mt7615_dfs_init_radar_specs(struct mt7615_phy *phy) +{ + const struct mt7615_dfs_radar_spec *radar_specs; + struct mt7615_dev *dev = phy->dev; + int err, i; + + switch (dev->mt76.region) { + case NL80211_DFS_FCC: + radar_specs = &fcc_radar_specs; + err = mt7615_mcu_set_fcc5_lpn(dev, 8); + if (err < 0) + return err; + break; + case NL80211_DFS_ETSI: + radar_specs = &etsi_radar_specs; + break; + case NL80211_DFS_JP: + radar_specs = &jp_radar_specs; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { + err = mt7615_mcu_set_radar_th(dev, i, + &radar_specs->radar_pattern[i]); + if (err < 0) + return err; + } + + return mt7615_mcu_set_pulse_th(dev, &radar_specs->pulse_th); +} + int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) { struct cfg80211_chan_def *chandef = &phy->mt76->chandef; @@ -1706,6 +1778,12 @@ int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) if (phy->dfs_state == chandef->chan->dfs_state) return 0; + err = mt7615_dfs_init_radar_specs(phy); + if (err < 0) { + phy->dfs_state = -1; + goto stop; + } + phy->dfs_state = chandef->chan->dfs_state; if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 8579b829778d..8f053fadd3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -306,6 +306,38 @@ struct mt7615_tx_free { #define MT_TXS6_F1_RCPI_1 GENMASK(15, 8) #define MT_TXS6_F1_RCPI_0 GENMASK(7, 0) +struct mt7615_dfs_pulse { + u32 max_width; /* us */ + int max_pwr; /* dbm */ + int min_pwr; /* dbm */ + u32 min_stgr_pri; /* us */ + u32 max_stgr_pri; /* us */ + u32 min_cr_pri; /* us */ + u32 max_cr_pri; /* us */ +}; + +struct mt7615_dfs_pattern { + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u8 max_pw; + u32 min_pri; + u32 max_pri; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; +}; + +struct mt7615_dfs_radar_spec { + struct mt7615_dfs_pulse pulse_th; + struct mt7615_dfs_pattern radar_pattern[16]; +}; + enum mt7615_cipher_type { MT_CIPHER_NONE, MT_CIPHER_WEP40, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 219c872a296d..281616b8d7fd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1333,6 +1333,54 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, &req, sizeof(req), true); } +int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) +{ + struct { + u16 tag; + u16 min_lpn; + } req = { + .tag = 0x1, + .min_lpn = val, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, + const struct mt7615_dfs_pulse *pulse) +{ + struct { + u16 tag; + struct mt7615_dfs_pulse pulse; + } req = { + .tag = 0x3, + }; + + memcpy(&req.pulse, pulse, sizeof(*pulse)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern) +{ + struct { + u16 tag; + u16 radar_type; + struct mt7615_dfs_pattern pattern; + } req = { + .tag = 0x2, + .radar_type = index, + }; + + memcpy(&req.pattern, pattern, sizeof(*pattern)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); +} + int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 8d057c72366a..b47d12a4c608 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -152,6 +152,7 @@ enum { MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_SET_RDD_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index e50b02b58461..09b5b34049a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -46,6 +46,8 @@ struct mt7615_vif; struct mt7615_sta; +struct mt7615_dfs_pulse; +struct mt7615_dfs_pattern; enum mt7615_hw_txq_id { MT7615_TXQ_MAIN, @@ -341,6 +343,11 @@ void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force); +int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val); +int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, + const struct mt7615_dfs_pulse *pulse); +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern); int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_init_debugfs(struct mt7615_dev *dev); From 26b4876697564f3190badbd5b192321c84940831 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Wed, 1 Jan 2020 13:56:25 +0800 Subject: [PATCH 102/168] mt76: mt7615: fix endianness in mt7615_mcu_set_eeprom The field 'u16 len' should be __le16. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 281616b8d7fd..cb1de4e1efd0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -598,10 +598,10 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) struct { u8 buffer_mode; u8 pad; - u16 len; + __le16 len; } __packed req_hdr = { .buffer_mode = 1, - .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, + .len = cpu_to_le16(__MT_EE_MAX - MT_EE_NIC_CONF_0), }; int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; From fecde5da035eb4b7308c85ef35ba21bd67fd5ef7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 7 Jan 2020 14:59:34 +0100 Subject: [PATCH 103/168] mt76: move WIPHY_FLAG_HAS_CHANNEL_SWITCH in mt76_phy_init Move WIPHY_FLAG_HAS_CHANNEL_SWITCH in mt76-core module since now all drivers support Channel Switch Announcement Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + drivers/net/wireless/mediatek/mt76/mt7603/init.c | 1 - drivers/net/wireless/mediatek/mt76/mt7615/init.c | 1 - drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index d752fb539351..8295bdb974fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -279,6 +279,7 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) SET_IEEE80211_PERM_ADDR(hw, dev->macaddr); wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 32fdb81b2bb0..182ce5a86f65 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -564,7 +564,6 @@ int mt7603_register_device(struct mt7603_dev *dev) dev->mt76.led_cdev.blink_set = mt7603_led_set_blink; } - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy->reg_notifier = mt7603_regd_notifier; ret = mt76_register_device(&dev->mt76, true, mt7603_rates, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index a14fd9587b70..1af941f83213 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -341,7 +341,6 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) wiphy->iface_combinations = if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7615_regd_notifier; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 28d8d447fc76..48da4f3a17db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -175,7 +175,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev) } } - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); hw->sta_data_size = sizeof(struct mt76x02_sta); From 1b784c3343ed27d5954040dce5f0ef4e74004b3f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 9 Jan 2020 14:26:53 +0100 Subject: [PATCH 104/168] mt76: mt7615: remove leftover routine declaration Get rid of mt76_dfs_start_rdd unused declaration Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 09b5b34049a8..900e48592afa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -342,7 +342,6 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); -int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force); int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val); int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, const struct mt7615_dfs_pulse *pulse); From 85b7a5d0b2ab183504014f5bfc3c3b1e76b595d7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 9 Dec 2019 17:53:04 +0100 Subject: [PATCH 105/168] mt76: rely on mac80211 utility routines to compute airtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rely on mac80211 airitme utility routines and remove mt76 duplicated code to estimate tx/rx airtime Signed-off-by: Lorenzo Bianconi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/airtime.c | 326 ------------------ drivers/net/wireless/mediatek/mt76/mac80211.c | 10 +- drivers/net/wireless/mediatek/mt76/mt76.h | 4 - .../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 5 files changed, 11 insertions(+), 333 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/airtime.c diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 99bbc74acda8..d7a1ddc9e407 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ - tx.o agg-rx.o mcu.o airtime.o + tx.o agg-rx.o mcu.o mt76-$(CONFIG_PCI) += pci.o diff --git a/drivers/net/wireless/mediatek/mt76/airtime.c b/drivers/net/wireless/mediatek/mt76/airtime.c deleted file mode 100644 index a4a785467748..000000000000 --- a/drivers/net/wireless/mediatek/mt76/airtime.c +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: ISC -/* - * Copyright (C) 2019 Felix Fietkau - */ - -#include "mt76.h" - -#define AVG_PKT_SIZE 1024 - -/* Number of bits for an average sized packet */ -#define MCS_NBITS (AVG_PKT_SIZE << 3) - -/* Number of symbols for a packet with (bps) bits per symbol */ -#define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) - -/* Transmission time (1024 usec) for a packet containing (syms) * symbols */ -#define MCS_SYMBOL_TIME(sgi, syms) \ - (sgi ? \ - ((syms) * 18 * 1024 + 4 * 1024) / 5 : /* syms * 3.6 us */ \ - ((syms) * 1024) << 2 /* syms * 4 us */ \ - ) - -/* Transmit duration for the raw data part of an average sized packet */ -#define MCS_DURATION(streams, sgi, bps) \ - MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) - -#define BW_20 0 -#define BW_40 1 -#define BW_80 2 - -/* - * Define group sort order: HT40 -> SGI -> #streams - */ -#define MT_MAX_STREAMS 4 -#define MT_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */ -#define MT_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */ - -#define MT_HT_GROUPS_NB (MT_MAX_STREAMS * \ - MT_HT_STREAM_GROUPS) -#define MT_VHT_GROUPS_NB (MT_MAX_STREAMS * \ - MT_VHT_STREAM_GROUPS) -#define MT_GROUPS_NB (MT_HT_GROUPS_NB + \ - MT_VHT_GROUPS_NB) - -#define MT_HT_GROUP_0 0 -#define MT_VHT_GROUP_0 (MT_HT_GROUP_0 + MT_HT_GROUPS_NB) - -#define MCS_GROUP_RATES 10 - -#define HT_GROUP_IDX(_streams, _sgi, _ht40) \ - MT_HT_GROUP_0 + \ - MT_MAX_STREAMS * 2 * _ht40 + \ - MT_MAX_STREAMS * _sgi + \ - _streams - 1 - -#define _MAX(a, b) (((a)>(b))?(a):(b)) - -#define GROUP_SHIFT(duration) \ - _MAX(0, 16 - __builtin_clz(duration)) - -/* MCS rate information for an MCS group */ -#define __MCS_GROUP(_streams, _sgi, _ht40, _s) \ - [HT_GROUP_IDX(_streams, _sgi, _ht40)] = { \ - .shift = _s, \ - .duration = { \ - MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \ - MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \ - } \ -} - -#define MCS_GROUP_SHIFT(_streams, _sgi, _ht40) \ - GROUP_SHIFT(MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26)) - -#define MCS_GROUP(_streams, _sgi, _ht40) \ - __MCS_GROUP(_streams, _sgi, _ht40, \ - MCS_GROUP_SHIFT(_streams, _sgi, _ht40)) - -#define VHT_GROUP_IDX(_streams, _sgi, _bw) \ - (MT_VHT_GROUP_0 + \ - MT_MAX_STREAMS * 2 * (_bw) + \ - MT_MAX_STREAMS * (_sgi) + \ - (_streams) - 1) - -#define BW2VBPS(_bw, r3, r2, r1) \ - (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1) - -#define __VHT_GROUP(_streams, _sgi, _bw, _s) \ - [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \ - .shift = _s, \ - .duration = { \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 117, 54, 26)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 234, 108, 52)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 351, 162, 78)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 468, 216, 104)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 702, 324, 156)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 936, 432, 208)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1053, 486, 234)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1170, 540, 260)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1404, 648, 312)) >> _s, \ - MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 1560, 720, 346)) >> _s \ - } \ -} - -#define VHT_GROUP_SHIFT(_streams, _sgi, _bw) \ - GROUP_SHIFT(MCS_DURATION(_streams, _sgi, \ - BW2VBPS(_bw, 117, 54, 26))) - -#define VHT_GROUP(_streams, _sgi, _bw) \ - __VHT_GROUP(_streams, _sgi, _bw, \ - VHT_GROUP_SHIFT(_streams, _sgi, _bw)) - -struct mcs_group { - u8 shift; - u16 duration[MCS_GROUP_RATES]; -}; - -static const struct mcs_group airtime_mcs_groups[] = { - MCS_GROUP(1, 0, BW_20), - MCS_GROUP(2, 0, BW_20), - MCS_GROUP(3, 0, BW_20), - MCS_GROUP(4, 0, BW_20), - - MCS_GROUP(1, 1, BW_20), - MCS_GROUP(2, 1, BW_20), - MCS_GROUP(3, 1, BW_20), - MCS_GROUP(4, 1, BW_20), - - MCS_GROUP(1, 0, BW_40), - MCS_GROUP(2, 0, BW_40), - MCS_GROUP(3, 0, BW_40), - MCS_GROUP(4, 0, BW_40), - - MCS_GROUP(1, 1, BW_40), - MCS_GROUP(2, 1, BW_40), - MCS_GROUP(3, 1, BW_40), - MCS_GROUP(4, 1, BW_40), - - VHT_GROUP(1, 0, BW_20), - VHT_GROUP(2, 0, BW_20), - VHT_GROUP(3, 0, BW_20), - VHT_GROUP(4, 0, BW_20), - - VHT_GROUP(1, 1, BW_20), - VHT_GROUP(2, 1, BW_20), - VHT_GROUP(3, 1, BW_20), - VHT_GROUP(4, 1, BW_20), - - VHT_GROUP(1, 0, BW_40), - VHT_GROUP(2, 0, BW_40), - VHT_GROUP(3, 0, BW_40), - VHT_GROUP(4, 0, BW_40), - - VHT_GROUP(1, 1, BW_40), - VHT_GROUP(2, 1, BW_40), - VHT_GROUP(3, 1, BW_40), - VHT_GROUP(4, 1, BW_40), - - VHT_GROUP(1, 0, BW_80), - VHT_GROUP(2, 0, BW_80), - VHT_GROUP(3, 0, BW_80), - VHT_GROUP(4, 0, BW_80), - - VHT_GROUP(1, 1, BW_80), - VHT_GROUP(2, 1, BW_80), - VHT_GROUP(3, 1, BW_80), - VHT_GROUP(4, 1, BW_80), -}; - -static u32 -mt76_calc_legacy_rate_duration(const struct ieee80211_rate *rate, bool short_pre, - int len) -{ - u32 duration; - - switch (rate->hw_value >> 8) { - case MT_PHY_TYPE_CCK: - duration = 144 + 48; /* preamble + PLCP */ - if (short_pre) - duration >>= 1; - - duration += 10; /* SIFS */ - break; - case MT_PHY_TYPE_OFDM: - duration = 20 + 16; /* premable + SIFS */ - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - len <<= 3; - duration += (len * 10) / rate->bitrate; - - return duration; -} - -u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status, - int len) -{ - struct ieee80211_supported_band *sband; - const struct ieee80211_rate *rate; - bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI; - bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE; - int bw, streams; - u32 duration; - int group, idx; - - switch (status->bw) { - case RATE_INFO_BW_20: - bw = BW_20; - break; - case RATE_INFO_BW_40: - bw = BW_40; - break; - case RATE_INFO_BW_80: - bw = BW_80; - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - switch (status->encoding) { - case RX_ENC_LEGACY: - if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ)) - return 0; - - sband = dev->hw->wiphy->bands[status->band]; - if (!sband || status->rate_idx >= sband->n_bitrates) - return 0; - - rate = &sband->bitrates[status->rate_idx]; - - return mt76_calc_legacy_rate_duration(rate, sp, len); - case RX_ENC_VHT: - streams = status->nss; - idx = status->rate_idx; - group = VHT_GROUP_IDX(streams, sgi, bw); - break; - case RX_ENC_HT: - streams = ((status->rate_idx >> 3) & 3) + 1; - idx = status->rate_idx & 7; - group = HT_GROUP_IDX(streams, sgi, bw); - break; - default: - WARN_ON_ONCE(1); - return 0; - } - - if (WARN_ON_ONCE(streams > 4)) - return 0; - - duration = airtime_mcs_groups[group].duration[idx]; - duration <<= airtime_mcs_groups[group].shift; - duration *= len; - duration /= AVG_PKT_SIZE; - duration /= 1024; - - duration += 36 + (streams << 2); - - return duration; -} - -u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info, - int len) -{ - struct mt76_rx_status stat = { - .band = info->band, - }; - u32 duration = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(info->status.rates); i++) { - struct ieee80211_tx_rate *rate = &info->status.rates[i]; - u32 cur_duration; - - if (rate->idx < 0 || !rate->count) - break; - - if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) - stat.bw = RATE_INFO_BW_80; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - stat.bw = RATE_INFO_BW_40; - else - stat.bw = RATE_INFO_BW_20; - - stat.enc_flags = 0; - if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - stat.enc_flags |= RX_ENC_FLAG_SHORTPRE; - if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - stat.enc_flags |= RX_ENC_FLAG_SHORT_GI; - - stat.rate_idx = rate->idx; - if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { - stat.encoding = RX_ENC_VHT; - stat.rate_idx = ieee80211_rate_get_vht_mcs(rate); - stat.nss = ieee80211_rate_get_vht_nss(rate); - } else if (rate->flags & IEEE80211_TX_RC_MCS) { - stat.encoding = RX_ENC_HT; - } else { - stat.encoding = RX_ENC_LEGACY; - } - - cur_duration = mt76_calc_rx_airtime(dev, &stat, len); - duration += cur_duration * rate->count; - } - - return duration; -} -EXPORT_SYMBOL_GPL(mt76_calc_tx_airtime); diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 8295bdb974fc..9d11e4f68db6 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -746,10 +746,18 @@ mt76_airtime_report(struct mt76_dev *dev, struct mt76_rx_status *status, int len) { struct mt76_wcid *wcid = status->wcid; + struct ieee80211_rx_status info = { + .enc_flags = status->enc_flags, + .rate_idx = status->rate_idx, + .encoding = status->encoding, + .band = status->band, + .nss = status->nss, + .bw = status->bw, + }; struct ieee80211_sta *sta; u32 airtime; - airtime = mt76_calc_rx_airtime(dev, status, len); + airtime = ieee80211_calc_rx_airtime(dev->hw, &info, len); spin_lock(&dev->cc_lock); dev->cur_cc_bss_rx += airtime; spin_unlock(&dev->cc_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index c050d95dc7ac..0f98050bc7bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -820,8 +820,6 @@ void mt76_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -u32 mt76_calc_tx_airtime(struct mt76_dev *dev, struct ieee80211_tx_info *info, - int len); /* internal */ static inline struct ieee80211_hw * @@ -846,8 +844,6 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, struct napi_struct *napi); void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames); -u32 mt76_calc_rx_airtime(struct mt76_dev *dev, struct mt76_rx_status *status, - int len); /* usb */ static inline bool mt76u_urb_error(struct urb *urb) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 8345f7617fef..8b072277ea10 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -631,7 +631,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, if (!len) goto out; - duration = mt76_calc_tx_airtime(&dev->mt76, &info, len); + duration = ieee80211_calc_tx_airtime(mt76_hw(dev), &info, len); spin_lock_bh(&dev->mt76.cc_lock); dev->tx_airtime += duration; From a1ea1d688d0b5cf1dffd80ea2b08e2c18c00099a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 23 Dec 2019 14:03:32 +0100 Subject: [PATCH 106/168] mt76: mt76x02u: avoid overwrite max_tx_fragments Starting from 'commit ee8040139ab1 ("mt76: do not overwrite max_tx_fragments if it has been set")' we can avoid overwriting max_tx_fragments for mt76x02u devices Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 8 ++------ drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index abf0a19ee70e..68a00795c91e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -182,16 +182,12 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) if (err < 0) goto out_err; + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1; err = mt76x0_register_device(dev); if (err < 0) goto out_err; - /* check hw sg support in order to enable AMSDU */ - if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; - else - hw->max_tx_fragments = 1; - set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 62e5e89baf23..d2ca8fe42655 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -207,17 +207,13 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) goto fail; + /* check hw sg support in order to enable AMSDU */ + hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1; err = mt76_register_device(&dev->mt76, true, mt76x02_rates, ARRAY_SIZE(mt76x02_rates)); if (err) goto fail; - /* check hw sg support in order to enable AMSDU */ - if (dev->mt76.usb.sg_en) - hw->max_tx_fragments = MT_TX_SG_MAX_SIZE; - else - hw->max_tx_fragments = 1; - set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); mt76x02_init_debugfs(dev); From f4021e1f06913f8e962f98d21cecf2353f52a0e6 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:41 +0100 Subject: [PATCH 107/168] mt76: mt76u: check tx_status_data pointer in mt76u_tx_tasklet New devices (e.g. mt7663u) do not rely on stats workqueue to load tx statistics but will be reported by the firmware. Check tx_status_data pointer in mt76u_tx_tasklet in order to reuse tx tasklet for new devices Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 22dacf040123..fbc4c0bb0102 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -708,7 +708,8 @@ static void mt76u_tx_tasklet(unsigned long data) mt76_txq_schedule(&dev->phy, i); - if (!test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) + if (dev->drv->tx_status_data && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) queue_work(dev->usb.stat_wq, &dev->usb.stat_work); if (wake) ieee80211_wake_queue(dev->hw, i); From 840728899c842c817fc1df706488dec24622797f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:42 +0100 Subject: [PATCH 108/168] mt76: mt76u: add mt76u_process_rx_queue utility routine Introduce mt76u_process_rx_queue routine to process rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 30 +++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index fbc4c0bb0102..9b0a4104ec0e 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -468,9 +468,9 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) } static int -mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) +mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, + int buf_size) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer; int data_len = urb->num_sgs ? urb->sg[0].length : urb->actual_length; int len, nsgs = 1; @@ -484,7 +484,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) return 0; data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); - skb = mt76u_build_rx_skb(data, data_len, q->buf_size); + skb = mt76u_build_rx_skb(data, data_len, buf_size); if (!skb) return 0; @@ -493,8 +493,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, sg_page(&urb->sg[nsgs]), - urb->sg[nsgs].offset, - data_len, q->buf_size); + urb->sg[nsgs].offset, data_len, + buf_size); len -= data_len; nsgs++; } @@ -545,20 +545,19 @@ mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb) return usb_submit_urb(urb, GFP_ATOMIC); } -static void mt76u_rx_tasklet(unsigned long data) +static void +mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76_dev *dev = (struct mt76_dev *)data; + int qid = q - &dev->q_rx[MT_RXQ_MAIN]; struct urb *urb; int err, count; - rcu_read_lock(); - while (true) { urb = mt76u_get_next_rx_entry(dev); if (!urb) break; - count = mt76u_process_rx_entry(dev, urb); + count = mt76u_process_rx_entry(dev, urb, q->buf_size); if (count > 0) { err = mt76u_refill_rx(dev, urb, count, GFP_ATOMIC); if (err < 0) @@ -566,8 +565,17 @@ static void mt76u_rx_tasklet(unsigned long data) } mt76u_submit_rx_buf(dev, urb); } - mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); + if (qid == MT_RXQ_MAIN) + mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); +} +static void mt76u_rx_tasklet(unsigned long data) +{ + struct mt76_dev *dev = (struct mt76_dev *)data; + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + + rcu_read_lock(); + mt76u_process_rx_queue(dev, q); rcu_read_unlock(); } From 0d1862104e6a8e01fffebe9ed3c8f490b24e0a35 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:43 +0100 Subject: [PATCH 109/168] mt76: mt76u: add mt76_queue to mt76u_get_next_rx_entry signature Rely on mt76_queue pointer in mt76u_get_next_rx_entry in order to add support for new devices (e.g 7663u) that reports fw events through hw rx mcu queue Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 9b0a4104ec0e..23973ec6c92c 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -398,10 +398,9 @@ mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, urb->context = context; } -static inline struct urb * -mt76u_get_next_rx_entry(struct mt76_dev *dev) +static struct urb * +mt76u_get_next_rx_entry(struct mt76_queue *q) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct urb *urb = NULL; unsigned long flags; @@ -553,7 +552,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) int err, count; while (true) { - urb = mt76u_get_next_rx_entry(dev); + urb = mt76u_get_next_rx_entry(q); if (!urb) break; From ab221b207b60aee9dd9acdc2f5556ecd13574216 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:44 +0100 Subject: [PATCH 110/168] mt76: mt76u: add mt76_queue to mt76u_refill_rx signature Introduce mt76_queue parameter to mt76u_refill_rx signature in order to reuse it for mcu hw rx queue Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 23973ec6c92c..65b819f0d18a 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -318,11 +318,12 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb, } static int -mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) +mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, + struct urb *urb, int nsgs, gfp_t gfp) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; - if (dev->usb.sg_en) + if (qid == MT_RXQ_MAIN && dev->usb.sg_en) return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp); urb->transfer_buffer_length = q->buf_size; @@ -355,13 +356,14 @@ mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, static int mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) { + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; int err; err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); if (err) return err; - return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, + return mt76u_refill_rx(dev, q, e->urb, MT_RX_SG_MAX_SIZE, GFP_KERNEL); } @@ -558,7 +560,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) count = mt76u_process_rx_entry(dev, urb, q->buf_size); if (count > 0) { - err = mt76u_refill_rx(dev, urb, count, GFP_ATOMIC); + err = mt76u_refill_rx(dev, q, urb, count, GFP_ATOMIC); if (err < 0) break; } From 2fe6a5564d599c84e690b072eede5b167724eb3a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:45 +0100 Subject: [PATCH 111/168] mt76: mt76u: use mt76_queue as mt76u_complete_rx context In order to reuse mt76u_complete_rx for both data and mcu rx queue, rely on mt76_queue as urb context in mt76u_complete_rx. Moreover set usb rx endoint according to rx queue in mt76u_submit_rx_buf. This is a preliminary patch to add mt7663u support Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 65b819f0d18a..88be4d553b70 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -506,8 +506,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, static void mt76u_complete_rx(struct urb *urb) { - struct mt76_dev *dev = urb->context; - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_dev *dev = dev_get_drvdata(&urb->dev->dev); + struct mt76_queue *q = urb->context; unsigned long flags; trace_rx_urb(dev, urb); @@ -537,10 +537,13 @@ static void mt76u_complete_rx(struct urb *urb) } static int -mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb) +mt76u_submit_rx_buf(struct mt76_dev *dev, enum mt76_rxq_id qid, + struct urb *urb) { - mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, urb, - mt76u_complete_rx, dev); + int ep = qid == MT_RXQ_MAIN ? MT_EP_IN_PKT_RX : MT_EP_IN_CMD_RESP; + + mt76u_fill_bulk_urb(dev, USB_DIR_IN, ep, urb, + mt76u_complete_rx, &dev->q_rx[qid]); trace_submit_urb(dev, urb); return usb_submit_urb(urb, GFP_ATOMIC); @@ -564,7 +567,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) if (err < 0) break; } - mt76u_submit_rx_buf(dev, urb); + mt76u_submit_rx_buf(dev, qid, urb); } if (qid == MT_RXQ_MAIN) mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL); @@ -588,7 +591,7 @@ static int mt76u_submit_rx_buffers(struct mt76_dev *dev) spin_lock_irqsave(&q->lock, flags); for (i = 0; i < q->ndesc; i++) { - err = mt76u_submit_rx_buf(dev, q->entry[i].urb); + err = mt76u_submit_rx_buf(dev, MT_RXQ_MAIN, q->entry[i].urb); if (err < 0) break; } From 37ec6a03d7281f29a0a43486ae9963626231ef11 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:46 +0100 Subject: [PATCH 112/168] mt76: mt76u: add queue id parameter to mt76u_submit_rx_buffers Add queue_id parameter to mt76u_submit_rx_buffers in order to reuse it adding mt7663u support Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 88be4d553b70..678720c53886 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -583,15 +583,16 @@ static void mt76u_rx_tasklet(unsigned long data) rcu_read_unlock(); } -static int mt76u_submit_rx_buffers(struct mt76_dev *dev) +static int +mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q = &dev->q_rx[qid]; unsigned long flags; int i, err = 0; spin_lock_irqsave(&q->lock, flags); for (i = 0; i < q->ndesc; i++) { - err = mt76u_submit_rx_buf(dev, MT_RXQ_MAIN, q->entry[i].urb); + err = mt76u_submit_rx_buf(dev, qid, q->entry[i].urb); if (err < 0) break; } @@ -628,7 +629,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) return err; } - return mt76u_submit_rx_buffers(dev); + return mt76u_submit_rx_buffers(dev, MT_RXQ_MAIN); } static void mt76u_free_rx(struct mt76_dev *dev) @@ -668,7 +669,7 @@ int mt76u_resume_rx(struct mt76_dev *dev) for (i = 0; i < q->ndesc; i++) usb_unpoison_urb(q->entry[i].urb); - return mt76u_submit_rx_buffers(dev); + return mt76u_submit_rx_buffers(dev, MT_RXQ_MAIN); } EXPORT_SYMBOL_GPL(mt76u_resume_rx); From 9aeb0d114d4e1794233a99dd9f4e6efc402a317e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:47 +0100 Subject: [PATCH 113/168] mt76: mt76u: move mcu buffer allocation in mt76x02u drivers Move mcu buffer allocation in mt76x2u/mt76x0u drivers since newer chipsets (e.g. mt7663u) does not rely on synchronous mcu communication Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 6 ++++++ drivers/net/wireless/mediatek/mt76/usb.c | 5 ----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 68a00795c91e..f70718ce3ae8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -172,8 +172,14 @@ static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset) static int mt76x0u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = dev->mt76.hw; + struct mt76_usb *usb = &dev->mt76.usb; int err; + usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE, + GFP_KERNEL); + if (!usb->mcu.data) + return -ENOMEM; + err = mt76u_alloc_queues(&dev->mt76); if (err < 0) goto out_err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index d2ca8fe42655..ffc2deba29ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -190,6 +190,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) int mt76x2u_register_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_usb *usb = &dev->mt76.usb; int err; INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate); @@ -199,6 +200,11 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) return err; + usb->mcu.data = devm_kmalloc(dev->mt76.dev, MCU_RESP_URB_SIZE, + GFP_KERNEL); + if (!usb->mcu.data) + return -ENOMEM; + err = mt76u_alloc_queues(&dev->mt76); if (err < 0) goto fail; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 678720c53886..96269e8eb170 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -605,14 +605,9 @@ mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid) static int mt76u_alloc_rx(struct mt76_dev *dev) { - struct mt76_usb *usb = &dev->usb; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; int i, err; - usb->mcu.data = devm_kmalloc(dev->dev, MCU_RESP_URB_SIZE, GFP_KERNEL); - if (!usb->mcu.data) - return -ENOMEM; - spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, MT_NUM_RX_ENTRIES, sizeof(*q->entry), From 38e09a49f449e77849a271f1457489d1932b7182 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:48 +0100 Subject: [PATCH 114/168] mt76: mt76u: introduce mt76u_free_rx_queue utility routine Introduce mt76u_free_rx_queue utility routine to free rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 96269e8eb170..8f0d92c11abf 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -627,9 +627,9 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) return mt76u_submit_rx_buffers(dev, MT_RXQ_MAIN); } -static void mt76u_free_rx(struct mt76_dev *dev) +static void +mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; struct page *page; int i; @@ -644,6 +644,13 @@ static void mt76u_free_rx(struct mt76_dev *dev) memset(&q->rx_page, 0, sizeof(q->rx_page)); } +static void mt76u_free_rx(struct mt76_dev *dev) +{ + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + + mt76u_free_rx_queue(dev, q); +} + void mt76u_stop_rx(struct mt76_dev *dev) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; From b430b7db3889cd5998616518d91e0be8ae645a39 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:49 +0100 Subject: [PATCH 115/168] mt76: mt76u: stop/free all possible rx queues Stop/free all configured rx queues (data/mcu) in mt76u_stop_rx/mt76u_free_rx. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 25 ++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 8f0d92c11abf..dde1ee34d23d 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -646,18 +646,31 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) static void mt76u_free_rx(struct mt76_dev *dev) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q; + int i; - mt76u_free_rx_queue(dev, q); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; + if (!q->ndesc) + continue; + + mt76u_free_rx_queue(dev, q); + } } void mt76u_stop_rx(struct mt76_dev *dev) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i; + struct mt76_queue *q; + int i, j; - for (i = 0; i < q->ndesc; i++) - usb_poison_urb(q->entry[i].urb); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; + if (!q->ndesc) + continue; + + for (j = 0; j < q->ndesc; j++) + usb_poison_urb(q->entry[j].urb); + } tasklet_kill(&dev->usb.rx_tasklet); } From 63deaab0dd8fdb6b0d8f8a26382b24ca482dd586 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:50 +0100 Subject: [PATCH 116/168] mt76: mt76u: add mt76u_alloc_rx_queue utility routine Introduce mt76u_alloc_rx_queue routine to allocate rx hw queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index dde1ee34d23d..e1112899a207 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -603,9 +603,10 @@ mt76u_submit_rx_buffers(struct mt76_dev *dev, enum mt76_rxq_id qid) return err; } -static int mt76u_alloc_rx(struct mt76_dev *dev) +static int +mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + struct mt76_queue *q = &dev->q_rx[qid]; int i, err; spin_lock_init(&q->lock); @@ -624,7 +625,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) return err; } - return mt76u_submit_rx_buffers(dev, MT_RXQ_MAIN); + return mt76u_submit_rx_buffers(dev, qid); } static void @@ -966,7 +967,7 @@ int mt76u_alloc_queues(struct mt76_dev *dev) { int err; - err = mt76u_alloc_rx(dev); + err = mt76u_alloc_rx_queue(dev, MT_RXQ_MAIN); if (err < 0) return err; From 87999d4e6b154c87a19f80fe97bdfc7cad0f97bf Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:51 +0100 Subject: [PATCH 117/168] mt76: mt76u: add queue parameter to mt76u_rx_urb_alloc Add mt76_queue parameter to mt76u_rx_urb_alloc signature since this routine will be used to allocate urbs for mcu hw queue used by new chipset generation (e.g. mt7663u). Check sg_max_size in in mt76u_urb_alloc in order to use linear urb for mcu queue Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index e1112899a207..f80380c674a1 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -347,24 +347,25 @@ mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, usb_init_urb(e->urb); - if (dev->usb.sg_en) + if (dev->usb.sg_en && sg_max_size > 0) e->urb->sg = (struct scatterlist *)(e->urb + 1); return 0; } static int -mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76_queue_entry *e) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int err; + enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN]; + int err, sg_size; - err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); + sg_size = qid == MT_RXQ_MAIN ? MT_RX_SG_MAX_SIZE : 0; + err = mt76u_urb_alloc(dev, e, sg_size); if (err) return err; - return mt76u_refill_rx(dev, q, e->urb, MT_RX_SG_MAX_SIZE, - GFP_KERNEL); + return mt76u_refill_rx(dev, q, e->urb, sg_size, GFP_KERNEL); } static void mt76u_urb_free(struct urb *urb) @@ -620,7 +621,7 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) q->buf_size = PAGE_SIZE; for (i = 0; i < q->ndesc; i++) { - err = mt76u_rx_urb_alloc(dev, &q->entry[i]); + err = mt76u_rx_urb_alloc(dev, q, &q->entry[i]); if (err < 0) return err; } From 1d54bc27165d4850120b89e410db52b9d88fd7a0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:52 +0100 Subject: [PATCH 118/168] mt76: mt76u: resume all rx queue in mt76u_resume_rx Resume all possible rx queues after suspend. This is a preliminary patch to support mt7663u devices Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index f80380c674a1..d85268c6df70 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -680,13 +680,24 @@ EXPORT_SYMBOL_GPL(mt76u_stop_rx); int mt76u_resume_rx(struct mt76_dev *dev) { - struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i; + struct mt76_queue *q; + int i, j, err; - for (i = 0; i < q->ndesc; i++) - usb_unpoison_urb(q->entry[i].urb); + for (i = 0; i < __MT_RXQ_MAX; i++) { + q = &dev->q_rx[i]; - return mt76u_submit_rx_buffers(dev, MT_RXQ_MAIN); + if (!q->ndesc) + continue; + + for (j = 0; j < q->ndesc; j++) + usb_unpoison_urb(q->entry[j].urb); + + err = mt76u_submit_rx_buffers(dev, i); + if (err < 0) + return err; + } + + return 0; } EXPORT_SYMBOL_GPL(mt76u_resume_rx); From 94e1cfa890b74ee37ea80af76da704775b202b4b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:53 +0100 Subject: [PATCH 119/168] mt76: mt76u: introduce mt76u_alloc_mcu_queue utility routine Add mt76u_alloc_mcu_queue utility routine to allocate mcu hw rx queue. This is a preliminary patch to support new devices (e.g. mt7663u) that rely on a hw queue for mcu messages Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/usb.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0f98050bc7bd..afcee5a87a09 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -885,6 +885,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); +int mt76u_alloc_mcu_queue(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_tx(struct mt76_dev *dev); void mt76u_stop_rx(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index d85268c6df70..4e0a115c6fd2 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -629,6 +629,12 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid) return mt76u_submit_rx_buffers(dev, qid); } +int mt76u_alloc_mcu_queue(struct mt76_dev *dev) +{ + return mt76u_alloc_rx_queue(dev, MT_RXQ_MCU); +} +EXPORT_SYMBOL_GPL(mt76u_alloc_mcu_queue); + static void mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q) { From 1e816c65cb382fd7b9e43994e76f83faf97d2977 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:54 +0100 Subject: [PATCH 120/168] mt76: mt76u: add {read/write}_extended utility routines Introduce extended utility routines to read/write data o usb bus. New devices (e.g. mt7663u) will rely on both upper and lower part of the register address. Add ext parameter to mt76u_init signature in order to reuse the code adding mt7663u support. Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +- .../net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- .../net/wireless/mediatek/mt76/mt76x2/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 142 ++++++++++++++---- 4 files changed, 123 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index afcee5a87a09..4968b596f3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -359,12 +359,15 @@ struct mt76_rate_power { enum mt_vendor_req { MT_VEND_DEV_MODE = 0x1, MT_VEND_WRITE = 0x2, + MT_VEND_POWER_ON = 0x4, MT_VEND_MULTI_WRITE = 0x6, MT_VEND_MULTI_READ = 0x7, MT_VEND_READ_EEPROM = 0x9, MT_VEND_WRITE_FCE = 0x42, MT_VEND_WRITE_CFG = 0x46, MT_VEND_READ_CFG = 0x47, + MT_VEND_READ_EXT = 0x63, + MT_VEND_WRITE_EXT = 0x66, }; enum mt76u_in_ep { @@ -883,8 +886,9 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, void *buf, size_t len); void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); -int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); +int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf, + bool ext); int mt76u_alloc_mcu_queue(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_tx(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index f70718ce3ae8..747d21b3ee57 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -242,7 +242,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); mt76x02u_init_mcu(mdev); - ret = mt76u_init(mdev, usb_intf); + ret = mt76u_init(mdev, usb_intf, false); if (ret) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 2c07063eadfe..eafa283ca699 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -54,7 +54,7 @@ static int mt76x2u_probe(struct usb_interface *intf, usb_set_intfdata(intf, dev); mt76x02u_init_mcu(mdev); - err = mt76u_init(mdev, intf); + err = mt76u_init(mdev, intf, false); if (err < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 4e0a115c6fd2..6b31a7a99072 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -62,12 +62,25 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, } EXPORT_SYMBOL_GPL(mt76u_vendor_request); -static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) +static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr) { struct mt76_usb *usb = &dev->usb; u32 data = ~0; - u16 offset; int ret; + + ret = __mt76u_vendor_request(dev, req, + USB_DIR_IN | USB_TYPE_VENDOR, + addr >> 16, addr, &usb->reg_val, + sizeof(__le32)); + if (ret == sizeof(__le32)) + data = le32_to_cpu(usb->reg_val); + trace_usb_reg_rr(dev, addr, data); + + return data; +} + +static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) +{ u8 req; switch (addr & MT_VEND_TYPE_MASK) { @@ -81,16 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr) req = MT_VEND_MULTI_READ; break; } - offset = addr & ~MT_VEND_TYPE_MASK; - ret = __mt76u_vendor_request(dev, req, - USB_DIR_IN | USB_TYPE_VENDOR, - 0, offset, &usb->reg_val, sizeof(__le32)); - if (ret == sizeof(__le32)) - data = le32_to_cpu(usb->reg_val); - trace_usb_reg_rr(dev, addr, data); - - return data; + return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK); } static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) @@ -104,10 +109,32 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr) return ret; } -static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) +static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void ___mt76u_wr(struct mt76_dev *dev, u8 req, + u32 addr, u32 val) { struct mt76_usb *usb = &dev->usb; - u16 offset; + + usb->reg_val = cpu_to_le32(val); + __mt76u_vendor_request(dev, req, + USB_DIR_OUT | USB_TYPE_VENDOR, + addr >> 16, addr, &usb->reg_val, + sizeof(__le32)); + trace_usb_reg_wr(dev, addr, val); +} + +static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ u8 req; switch (addr & MT_VEND_TYPE_MASK) { @@ -118,13 +145,7 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) req = MT_VEND_MULTI_WRITE; break; } - offset = addr & ~MT_VEND_TYPE_MASK; - - usb->reg_val = cpu_to_le32(val); - __mt76u_vendor_request(dev, req, - USB_DIR_OUT | USB_TYPE_VENDOR, 0, - offset, &usb->reg_val, sizeof(__le32)); - trace_usb_reg_wr(dev, addr, val); + ___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val); } static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) @@ -134,6 +155,13 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val) mutex_unlock(&dev->usb.usb_ctrl_mtx); } +static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) { @@ -145,6 +173,17 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr, return val; } +static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr, + u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} + static void mt76u_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) { @@ -177,6 +216,55 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset, mutex_unlock(&usb->usb_ctrl_mtx); } +static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset, + const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + +static void +mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset, + void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int i = 0, batch_len, ret; + u8 *val = data; + + len = round_up(len, 4); + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + ret = __mt76u_vendor_request(dev, MT_VEND_READ_EXT, + USB_DIR_IN | USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + memcpy(val + i, usb->data, batch_len); + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} + void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val) { @@ -1008,13 +1096,10 @@ void mt76u_deinit(struct mt76_dev *dev) EXPORT_SYMBOL_GPL(mt76u_deinit); int mt76u_init(struct mt76_dev *dev, - struct usb_interface *intf) + struct usb_interface *intf, bool ext) { - static const struct mt76_bus_ops mt76u_ops = { - .rr = mt76u_rr, - .wr = mt76u_wr, - .rmw = mt76u_rmw, - .write_copy = mt76u_copy, + static struct mt76_bus_ops mt76u_ops = { + .read_copy = mt76u_read_copy_ext, .wr_rp = mt76u_wr_rp, .rd_rp = mt76u_rd_rp, .type = MT76_BUS_USB, @@ -1022,6 +1107,11 @@ int mt76u_init(struct mt76_dev *dev, struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; + mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr; + mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr; + mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw; + mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy; + tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev); tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); INIT_WORK(&usb->stat_work, mt76u_tx_status_data); From 16d6dac00939970e7e715aaa115952f6736102b9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:55 +0100 Subject: [PATCH 121/168] mt76: mt76u: take into account different queue mapping for 7663 7663u devices rely on a different endpoint mapping. Take it into account in mt76u_alloc_tx routine Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 6b31a7a99072..1f29cd905fdd 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -964,6 +964,14 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) } } +static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac) +{ + if (mt76_chip(dev) == 0x7663) + return ac ^ 0x3; + + return mt76_ac_to_hwq(ac); +} + static int mt76u_alloc_tx(struct mt76_dev *dev) { struct mt76_queue *q; @@ -982,7 +990,7 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) return -ENOMEM; spin_lock_init(&q->lock); - q->hw_idx = mt76_ac_to_hwq(i); + q->hw_idx = mt76u_ac_to_hwq(dev, i); dev->q_tx[i].q = q; q->entry = devm_kcalloc(dev->dev, From 9803b7b1617670f18ca88dbd9530d92890f84877 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:56 +0100 Subject: [PATCH 122/168] mt76: mt76u: introduce mt76u_skb_dma_info routine Introduce mt76u_skb_dma_info utility routine in mt76-usb module in order to be reused adding mt7663u support Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../wireless/mediatek/mt76/mt76x02_usb_core.c | 25 ++-------------- drivers/net/wireless/mediatek/mt76/usb.c | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 4968b596f3df..d906e0f0bf2e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -881,6 +881,7 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); } +int mt76u_skb_dma_info(struct sk_buff *skb, u32 info); int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index bf3198ec193b..0180b6200b17 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -46,8 +46,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_mac_start); int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) { - struct sk_buff *iter, *last = skb; - u32 info, pad; + u32 info; /* Buffer layout: * | 4B | xfer len | pad | 4B | @@ -57,28 +56,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) */ info = FIELD_PREP(MT_TXD_INFO_LEN, round_up(skb->len, 4)) | FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags; - put_unaligned_le32(info, skb_push(skb, sizeof(info))); - /* Add zero pad of 4 - 7 bytes */ - pad = round_up(skb->len, 4) + 4 - skb->len; - - /* First packet of a A-MSDU burst keeps track of the whole burst - * length, need to update length of it and the last packet. - */ - skb_walk_frags(skb, iter) { - last = iter; - if (!iter->next) { - skb->data_len += pad; - skb->len += pad; - break; - } - } - - if (skb_pad(last, pad)) - return -ENOMEM; - __skb_put(last, pad); - - return 0; + return mt76u_skb_dma_info(skb, info); } int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 1f29cd905fdd..57d2590165e3 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -907,6 +907,35 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, return urb->num_sgs; } +int mt76u_skb_dma_info(struct sk_buff *skb, u32 info) +{ + struct sk_buff *iter, *last = skb; + u32 pad; + + put_unaligned_le32(info, skb_push(skb, sizeof(info))); + /* Add zero pad of 4 - 7 bytes */ + pad = round_up(skb->len, 4) + 4 - skb->len; + + /* First packet of a A-MSDU burst keeps track of the whole burst + * length, need to update length of it and the last packet. + */ + skb_walk_frags(skb, iter) { + last = iter; + if (!iter->next) { + skb->data_len += pad; + skb->len += pad; + break; + } + } + + if (skb_pad(last, pad)) + return -ENOMEM; + __skb_put(last, pad); + + return 0; +} +EXPORT_SYMBOL_GPL(mt76u_skb_dma_info); + static int mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, struct mt76_wcid *wcid, From 3bcd979c8a24ba8999213521f18f8bf34a1713a3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:57 +0100 Subject: [PATCH 123/168] mt76: mt76u: add endpoint to mt76u_bulk_msg signature This is a preliminary patch to support mt7663u usb dongles Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index d906e0f0bf2e..0123c279051f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -866,7 +866,7 @@ static inline u8 q2ep(u8 qid) static inline int mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, - int timeout) + int timeout, int ep) { struct usb_interface *uintf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(uintf); @@ -874,9 +874,9 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, unsigned int pipe; if (actual_len) - pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]); + pipe = usb_rcvbulkpipe(udev, usb->in_ep[ep]); else - pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); + pipe = usb_sndbulkpipe(udev, usb->out_ep[ep]); return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index 106ff4b3e6ff..c58282baee46 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -55,7 +55,8 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) u32 rxfce; for (i = 0; i < 5; i++) { - ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300); + ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, + 300, MT_EP_IN_CMD_RESP); if (ret == -ETIMEDOUT) continue; if (ret) @@ -103,7 +104,8 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, if (ret) return ret; - ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500); + ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500, + MT_EP_OUT_INBAND_CMD); if (ret) return ret; @@ -248,7 +250,8 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, data_len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000); + err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000, + MT_EP_OUT_INBAND_CMD); if (err) { dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); return err; From 94d4d07675fa3aae05b8db8ee2544e196adc2c00 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 15 Jan 2020 11:58:58 +0100 Subject: [PATCH 124/168] mt76: mt76u: introduce MT_DRV_RX_DMA_HDR flag Define MT_DRV_RX_DMA_HDR flag in drv_flag in order to not skip rx frame dma header since new devices (e.g. mt7663u) reports rx frame info in the usb dma header Co-developed-by: Sean Wang Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/usb.c | 31 ++++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0123c279051f..815d08486002 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -286,6 +286,7 @@ struct mt76_hw_cap { #define MT_DRV_TXWI_NO_FREE BIT(0) #define MT_DRV_TX_ALIGNED4_SKBS BIT(1) #define MT_DRV_SW_RX_AIRTIME BIT(2) +#define MT_DRV_RX_DMA_HDR BIT(3) struct mt76_driver_ops { u32 drv_flags; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 57d2590165e3..981d8a985557 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -506,14 +506,17 @@ mt76u_get_next_rx_entry(struct mt76_queue *q) return urb; } -static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) +static int +mt76u_get_rx_entry_len(struct mt76_dev *dev, u8 *data, + u32 data_len) { u16 dma_len, min_len; dma_len = get_unaligned_le16(data); - min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN + - MT_FCE_INFO_LEN; + if (dev->drv->drv_flags & MT_DRV_RX_DMA_HDR) + return dma_len; + min_len = MT_DMA_HDR_LEN + MT_RX_RXWI_LEN + MT_FCE_INFO_LEN; if (data_len < min_len || !dma_len || dma_len + MT_DMA_HDR_LEN > data_len || (dma_len & 0x3)) @@ -522,11 +525,14 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) } static struct sk_buff * -mt76u_build_rx_skb(void *data, int len, int buf_size) +mt76u_build_rx_skb(struct mt76_dev *dev, void *data, + int len, int buf_size) { + int head_room, drv_flags = dev->drv->drv_flags; struct sk_buff *skb; - if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) { + head_room = drv_flags & MT_DRV_RX_DMA_HDR ? 0 : MT_DMA_HDR_LEN; + if (SKB_WITH_OVERHEAD(buf_size) < head_room + len) { struct page *page; /* slow path, not enough space for data and @@ -536,8 +542,8 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) if (!skb) return NULL; - skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN); - data += (MT_DMA_HDR_LEN + MT_SKB_HEAD_LEN); + skb_put_data(skb, data + head_room, MT_SKB_HEAD_LEN); + data += head_room + MT_SKB_HEAD_LEN; page = virt_to_head_page(data); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, data - page_address(page), @@ -551,7 +557,7 @@ mt76u_build_rx_skb(void *data, int len, int buf_size) if (!skb) return NULL; - skb_reserve(skb, MT_DMA_HDR_LEN); + skb_reserve(skb, head_room); __skb_put(skb, len); return skb; @@ -563,18 +569,19 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb, { u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer; int data_len = urb->num_sgs ? urb->sg[0].length : urb->actual_length; - int len, nsgs = 1; + int len, nsgs = 1, head_room, drv_flags = dev->drv->drv_flags; struct sk_buff *skb; if (!test_bit(MT76_STATE_INITIALIZED, &dev->phy.state)) return 0; - len = mt76u_get_rx_entry_len(data, urb->actual_length); + len = mt76u_get_rx_entry_len(dev, data, urb->actual_length); if (len < 0) return 0; - data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); - skb = mt76u_build_rx_skb(data, data_len, buf_size); + head_room = drv_flags & MT_DRV_RX_DMA_HDR ? 0 : MT_DMA_HDR_LEN; + data_len = min_t(int, len, data_len - head_room); + skb = mt76u_build_rx_skb(dev, data, data_len, buf_size); if (!skb) return 0; From 5ffc6b5a98404db51529c427ccbccd4878593cea Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 20 Jan 2020 12:07:09 +0100 Subject: [PATCH 125/168] mt76: set dma-done flag for flushed descriptors Avoids a theoretical corner case where the hardware could try to process a stale descriptor after a watchdog reset Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 9e03a7871ff4..e69329feed78 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -246,7 +246,9 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, if (!q->queued) return NULL; - if (!flush && !(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) + if (flush) + q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE); + else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE))) return NULL; q->tail = (q->tail + 1) % q->ndesc; From 93eaec7625f13cffb593b471405b017c7e64d4ee Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 20 Jan 2020 12:08:30 +0100 Subject: [PATCH 126/168] mt76: fix handling full tx queues in mt76_dma_tx_queue_skb_raw Fixes a theoretical issue where it could potentially overwrite an existing descriptor entry (and leaking its skb) Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e69329feed78..bcb11bb9aeeb 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -271,10 +271,13 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct mt76_queue_buf buf; dma_addr_t addr; + if (q->queued + 1 >= q->ndesc - 1) + goto error; + addr = dma_map_single(dev->dev, skb->data, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev->dev, addr))) - return -ENOMEM; + goto error; buf.addr = addr; buf.len = skb->len; @@ -285,6 +288,10 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, spin_unlock_bh(&q->lock); return 0; + +error: + dev_kfree_skb(skb); + return -ENOMEM; } static int From 8f6c4f7ba1a143737f73a3f087d41bb198a35ce3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 20 Jan 2020 12:11:07 +0100 Subject: [PATCH 127/168] mt76: dma: do not write cpu_idx on rx queue reset until after refill The hardware should only start processing the ring after at least one buffer has been added Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index bcb11bb9aeeb..e5dd7080e88e 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -132,6 +132,11 @@ mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q) writel(q->ndesc, &q->regs->ring_size); q->head = readl(&q->regs->dma_idx); q->tail = q->head; +} + +static void +mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) +{ writel(q->head, &q->regs->cpu_idx); } @@ -193,8 +198,10 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, enum mt76_txq_id qid, bool flush) dev->q_tx[__MT_TXQ_MAX + i].swq_queued -= n_swq_queued[4 + i]; } - if (flush) + if (flush) { mt76_dma_sync_idx(dev, q); + mt76_dma_kick_queue(dev, q); + } wake = wake && q->stopped && qid < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; @@ -257,12 +264,6 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, return mt76_dma_get_buf(dev, q, idx, len, info, more); } -static void -mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) -{ - writel(q->head, &q->regs->cpu_idx); -} - static int mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, u32 tx_info) From e970e6659899158871bae82e7c5aaf7eeabacb72 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 20 Jan 2020 12:14:56 +0100 Subject: [PATCH 128/168] mt76: mt7603: increase dma mcu rx ring size The ring is used for looping back tx powersave filtered frames, so it could use some more room, in case more than one aggregate was queued Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c index 57428467fe96..a08b85281170 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -221,7 +221,7 @@ int mt7603_dma_init(struct mt7603_dev *dev) return ret; ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, - MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); + MT7603_MCU_RX_RING_SIZE, MT_RX_BUF_SIZE); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 12fd2db2df10..ef374641fe80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -15,6 +15,7 @@ #define MT7603_RATE_RETRY 2 +#define MT7603_MCU_RX_RING_SIZE 64 #define MT7603_RX_RING_SIZE 128 #define MT7603_FIRMWARE_E1 "mt7603_e1.bin" From d9c54264d818b5a9609a7c3c6bca81e42246202e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 20 Jan 2020 12:16:26 +0100 Subject: [PATCH 129/168] mt76: enable Airtime Queue Limit support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is supported by all drivers Acked-by: Toke Høiland-Jørgensen Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 9d11e4f68db6..a9909debf9de 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -283,6 +283,7 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL); wiphy->available_antennas_tx = dev->phy.antenna_mask; wiphy->available_antennas_rx = dev->phy.antenna_mask; From cd82b0e0ca712e11a831004cda038a246f25cd68 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 30 Jan 2020 13:22:25 +0100 Subject: [PATCH 130/168] dt-bindings: net: wireless: mt76: document bindings for MT7622 MT7622 is a SoC that includes a 2.4 GHz 4x4 802.11n WMAC. Its feature set is comparable to a MT7615 chip, but limited to 2.4 GHz. Reviewed-by: Rob Herring Signed-off-by: Felix Fietkau --- .../bindings/net/wireless/mediatek,mt76.txt | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt index d4d982f7ab37..3a76d8faaaed 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.txt @@ -4,13 +4,21 @@ This node provides properties for configuring the MediaTek mt76xx wireless device. The node is expected to be specified as a child node of the PCI controller to which the wireless chip is connected. -Alternatively, it can specify the wireless part of the MT7628/MT7688 SoC. -For SoC, use the compatible string "mediatek,mt7628-wmac" and the following -properties: +Alternatively, it can specify the wireless part of the MT7628/MT7688 or +MT7622 SoC. For SoC, use the following compatible strings: +compatible: +- "mediatek,mt7628-wmac" for MT7628/MT7688 +- "mediatek,mt7622-wmac" for MT7622 + +properties: - reg: Address and length of the register set for the device. - interrupts: Main device interrupt +MT7622 specific properties: +- power-domains: phandle to the power domain that the WMAC is part of +- mediatek,infracfg: phandle to the infrastructure bus fabric syscon node + Optional properties: - ieee80211-freq-limit: See ieee80211.txt @@ -53,3 +61,15 @@ wmac: wmac@10300000 { mediatek,mtd-eeprom = <&factory 0x0000>; }; + +MT7622 example: + +wmac: wmac@18000000 { + compatible = "mediatek,mt7622-wmac"; + reg = <0 0x18000000 0 0x100000>; + interrupts = ; + + mediatek,infracfg = <&infracfg>; + + power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; +}; From 13602c9d20cda52f84c193bd669174ce338a841b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Dec 2019 14:24:47 +0100 Subject: [PATCH 131/168] mt76: mt7615: add __aligned(4) to txp structs The beginning of the struct is guaranteed to be 4-byte aligned, and this attribute allows the compiler to generate more efficient code Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mac.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 8f053fadd3df..9b7c45bf1ec5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -243,7 +243,7 @@ struct mt7615_txp { u8 nbuf; __le32 buf[MT_TXP_MAX_BUF_NUM]; __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed; +} __packed __aligned(4); struct mt7615_tx_free { __le16 rx_byte_cnt; @@ -251,7 +251,7 @@ struct mt7615_tx_free { u8 txd_cnt; u8 rsv[3]; __le16 token[]; -} __packed; +} __packed __aligned(4); #define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0) From 57ec55e9f7750fb79473a3ec2830b58b2f2c2a10 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 16 Dec 2019 18:39:44 +0100 Subject: [PATCH 132/168] mt76: mt7615: move mmio related code from pci.c to mmio.c Will be shared with MT7622 SoC support Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/Makefile | 2 +- .../net/wireless/mediatek/mt76/mt7615/mmio.c | 105 ++++++++++++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 1 + .../net/wireless/mediatek/mt76/mt7615/pci.c | 97 +--------------- 4 files changed, 108 insertions(+), 97 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/mmio.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile index dcd6b0e7ce84..a93d147edf44 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_MT7615E) += mt7615e.o CFLAGS_trace.o := -I$(src) -mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ +mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o mmio.o \ debugfs.o trace.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c new file mode 100644 index 000000000000..4575bfda81c0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -0,0 +1,105 @@ +#include +#include + +#include "mt7615.h" +#include "mac.h" +#include "../trace.h" + +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) +{ + u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; + u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + + mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} + +static void +mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); +} + +static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) +{ + struct mt7615_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_TX_DONE_ALL) { + mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); + napi_schedule(&dev->mt76.tx_napi); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(0)); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE(1)) { + mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); + napi_schedule(&dev->mt76.napi[1]); + } + + return IRQ_HANDLED; +} + +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp), + .drv_flags = MT_DRV_TXWI_NO_FREE, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7615_tx_prepare_skb, + .tx_complete_skb = mt7615_tx_complete_skb, + .rx_skb = mt7615_queue_rx_skb, + .rx_poll_complete = mt7615_rx_poll_complete, + .sta_ps = mt7615_sta_ps, + .sta_add = mt7615_mac_sta_add, + .sta_remove = mt7615_mac_sta_remove, + .update_survey = mt7615_update_channel, + }; + struct mt7615_dev *dev; + struct mt76_dev *mdev; + int ret; + + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7615_ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7615_dev, mt76); + mt76_mmio_init(&dev->mt76, mem_base); + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7615_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 900e48592afa..5348bd28001c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -231,6 +231,7 @@ mt7615_ext_phy(struct mt7615_dev *dev) extern const struct ieee80211_ops mt7615_ops; extern struct pci_driver mt7615_pci_driver; +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq); u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); int mt7615_register_device(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 828f11087b08..caaad936a34a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -10,86 +10,15 @@ #include #include "mt7615.h" -#include "mac.h" -#include "../trace.h" static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, { }, }; -u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) -{ - u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; - u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; - - mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); - - return MT_PCIE_REMAP_BASE_2 + offset; -} - -static void -mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - mt7615_irq_enable(dev, MT_INT_RX_DONE(q)); -} - -static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) -{ - struct mt7615_dev *dev = dev_instance; - u32 intr; - - intr = mt76_rr(dev, MT_INT_SOURCE_CSR); - mt76_wr(dev, MT_INT_SOURCE_CSR, intr); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return IRQ_NONE; - - trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); - - intr &= dev->mt76.mmio.irqmask; - - if (intr & MT_INT_TX_DONE_ALL) { - mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL); - napi_schedule(&dev->mt76.tx_napi); - } - - if (intr & MT_INT_RX_DONE(0)) { - mt7615_irq_disable(dev, MT_INT_RX_DONE(0)); - napi_schedule(&dev->mt76.napi[0]); - } - - if (intr & MT_INT_RX_DONE(1)) { - mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); - napi_schedule(&dev->mt76.napi[1]); - } - - return IRQ_HANDLED; -} - static int mt7615_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - static const struct mt76_driver_ops drv_ops = { - /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp), - .drv_flags = MT_DRV_TXWI_NO_FREE, - .survey_flags = SURVEY_INFO_TIME_TX | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_BSS_RX, - .tx_prepare_skb = mt7615_tx_prepare_skb, - .tx_complete_skb = mt7615_tx_complete_skb, - .rx_skb = mt7615_queue_rx_skb, - .rx_poll_complete = mt7615_rx_poll_complete, - .sta_ps = mt7615_sta_ps, - .sta_add = mt7615_mac_sta_add, - .sta_remove = mt7615_mac_sta_remove, - .update_survey = mt7615_update_channel, - }; - struct mt7615_dev *dev; - struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -106,31 +35,7 @@ static int mt7615_pci_probe(struct pci_dev *pdev, if (ret) return ret; - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7615_ops, - &drv_ops); - if (!mdev) - return -ENOMEM; - - dev = container_of(mdev, struct mt7615_dev, mt76); - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - - mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | - (mt76_rr(dev, MT_HW_REV) & 0xff); - dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - - ret = devm_request_irq(mdev->dev, pdev->irq, mt7615_irq_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (ret) - goto error; - - ret = mt7615_register_device(dev); - if (ret) - goto error; - - return 0; -error: - ieee80211_free_hw(mt76_hw(dev)); - return ret; + return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], pdev->irq); } static void mt7615_pci_remove(struct pci_dev *pdev) From 1c88e7e0aee49b3d6dd6f3f6c52841b5476aa6f3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Dec 2019 04:57:50 +0100 Subject: [PATCH 133/168] mt76: mt7615: split up firmware loading functions Preparation for adding MT7622 support Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index cb1de4e1efd0..097d3fc365f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -345,7 +345,7 @@ static int mt7615_driver_own(struct mt7615_dev *dev) return 0; } -static int mt7615_load_patch(struct mt7615_dev *dev) +static int mt7615_load_patch(struct mt7615_dev *dev, const char *name) { const struct mt7615_patch_hdr *hdr; const struct firmware *fw = NULL; @@ -362,7 +362,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev) return -EAGAIN; } - ret = request_firmware(&fw, MT7615_ROM_PATCH, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) goto out; @@ -458,13 +458,13 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, return 0; } -static int mt7615_load_ram(struct mt7615_dev *dev) +static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) { const struct mt7615_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7615_FIRMWARE_N9, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -491,9 +491,18 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; } +out: release_firmware(fw); + return ret; +} - ret = request_firmware(&fw, MT7615_FIRMWARE_CR4, dev->mt76.dev); +static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name) +{ + const struct mt7615_fw_trailer *hdr; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -529,6 +538,17 @@ static int mt7615_load_ram(struct mt7615_dev *dev) return ret; } +static int mt7615_load_ram(struct mt7615_dev *dev) +{ + int ret; + + ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9); + if (ret) + return ret; + + return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4); +} + static int mt7615_load_firmware(struct mt7615_dev *dev) { int ret; @@ -541,7 +561,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - ret = mt7615_load_patch(dev); + ret = mt7615_load_patch(dev, MT7615_ROM_PATCH); if (ret) return ret; From 4e569727da74358a773bef08a1426e22c7d8b0eb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Dec 2019 04:59:05 +0100 Subject: [PATCH 134/168] mt76: mt7615: store N9 firmware version instead of CR4 CR4 is used very little, N9 is the main firmware that the driver interacts with Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 097d3fc365f7..2352e7687790 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -491,6 +491,10 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) goto out; } + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + out: release_firmware(fw); return ret; @@ -528,10 +532,6 @@ static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name) goto out; } - snprintf(dev->mt76.hw->wiphy->fw_version, - sizeof(dev->mt76.hw->wiphy->fw_version), - "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - out: release_firmware(fw); From 853fb35c503d60428d8f7039fdbba11eb98134f8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 16 Dec 2019 18:27:42 +0100 Subject: [PATCH 135/168] mt76: mt7615: fix MT_INT_TX_DONE_ALL definition for MT7622 MT7622 uses more interrupt bits for queue tx completion events. Enabling those extra bits is harmless on MT7615 Co-developed-by: Shayne Chen Co-developed-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 33e6087b58fe..1d764c587d25 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -37,7 +37,7 @@ #define MT_INT_RX_DONE(_n) BIT(_n) #define MT_INT_RX_DONE_ALL GENMASK(1, 0) -#define MT_INT_TX_DONE_ALL GENMASK(7, 4) +#define MT_INT_TX_DONE_ALL GENMASK(19, 4) #define MT_INT_TX_DONE(_n) BIT((_n) + 4) #define MT_WPDMA_GLO_CFG MT_HIF(0x208) From cdad4874057d5db2fab9537e435063ff1ee96745 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Dec 2019 06:49:29 +0100 Subject: [PATCH 136/168] mt76: mt7615: add dma and tx queue initialization for MT7622 MT7622 queue mapping is different from MT7615 and requires an extra dma scheduler init and a few register tweaks Co-developed-by: Shayne Chen Co-developed-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/dma.c | 176 ++++++++++++------ .../wireless/mediatek/mt76/mt7615/mt7615.h | 16 ++ .../net/wireless/mediatek/mt76/mt7615/regs.h | 21 +++ 3 files changed, 158 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 285d4f1d6178..41dea1aa58db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -12,31 +12,7 @@ #include "mac.h" static int -mt7615_init_tx_queues(struct mt7615_dev *dev, int n_desc) -{ - struct mt76_sw_queue *q; - struct mt76_queue *hwq; - int err, i; - - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; - - err = mt76_queue_alloc(dev, hwq, 0, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; - - for (i = 0; i < MT_TXQ_MCU; i++) { - q = &dev->mt76.q_tx[i]; - INIT_LIST_HEAD(&q->swq); - q->q = hwq; - } - - return 0; -} - -static int -mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, +mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, int idx, int n_desc) { struct mt76_queue *hwq; @@ -56,6 +32,68 @@ mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, return 0; } +static int +mt7622_init_tx_queues_multi(struct mt7615_dev *dev) +{ + static const u8 wmm_queue_map[] = { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_AC3, + }; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[i], + wmm_queue_map[i], + MT7615_TX_RING_SIZE / 2); + if (ret) + return ret; + } + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], + MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE); + if (ret) + return ret; + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE); + return ret; +} + +static int +mt7615_init_tx_queues(struct mt7615_dev *dev) +{ + struct mt76_sw_queue *q; + int ret, i; + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], + MT7615_TXQ_FWDL, + MT7615_TX_FWDL_RING_SIZE); + if (ret) + return ret; + + if (!is_mt7615(&dev->mt76)) + return mt7622_init_tx_queues_multi(dev); + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[0], 0, + MT7615_TX_RING_SIZE); + if (ret) + return ret; + + for (i = 1; i < MT_TXQ_MCU; i++) { + q = &dev->mt76.q_tx[i]; + INIT_LIST_HEAD(&q->swq); + q->q = dev->mt76.q_tx[0].q; + } + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7615_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE); + return 0; +} + void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb) { @@ -90,25 +128,32 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } +static void +mt7615_tx_cleanup(struct mt7615_dev *dev) +{ + int i; + + mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); + if (is_mt7615(&dev->mt76)) { + mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); + } else { + for (i = 0; i < IEEE80211_NUM_ACS; i++) + mt76_queue_tx_cleanup(dev, i, false); + } +} + static int mt7615_poll_tx(struct napi_struct *napi, int budget) { - static const u8 queue_map[] = { - MT_TXQ_MCU, - MT_TXQ_BE - }; struct mt7615_dev *dev; - int i; dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); if (napi_complete_done(napi, 0)) mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); mt7615_mac_sta_poll(dev); @@ -117,6 +162,30 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) return 0; } +static void mt7622_dma_sched_init(struct mt7615_dev *dev) +{ + u32 reg = mt7615_reg_map(dev, MT_DMASHDL_BASE); + int i; + + mt76_rmw(dev, reg + MT_DMASHDL_PKT_MAX_SIZE, + MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE, + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) | + FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8)); + + for (i = 0; i <= 5; i++) + mt76_wr(dev, reg + MT_DMASHDL_GROUP_QUOTA(i), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x10) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800)); + + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(0), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(1), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(2), 0x5); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(3), 0); + + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET0, 0x6012345f); + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET1, 0xedcba987); +} + int mt7615_dma_init(struct mt7615_dev *dev) { int ret; @@ -126,9 +195,12 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_wr(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE | MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN | - MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY | MT_WPDMA_GLO_CFG_OMIT_TX_INFO); + if (!is_mt7622(&dev->mt76)) + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY); + mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0, 0x1); @@ -141,28 +213,19 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3); - mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); - mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); - mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); - mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); - mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); - mt76_set(dev, 0x7158, BIT(16)); - mt76_clear(dev, 0x7000, BIT(23)); + if (is_mt7615(&dev->mt76)) { + mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); + mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); + mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); + mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); + mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); + mt76_set(dev, 0x7158, BIT(16)); + mt76_clear(dev, 0x7000, BIT(23)); + } + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); - ret = mt7615_init_tx_queues(dev, MT7615_TX_RING_SIZE); - if (ret) - return ret; - - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], - MT7615_TXQ_MCU, - MT7615_TX_MCU_RING_SIZE); - if (ret) - return ret; - - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], - MT7615_TXQ_FWDL, - MT7615_TX_FWDL_RING_SIZE); + ret = mt7615_init_tx_queues(dev); if (ret) return ret; @@ -201,6 +264,9 @@ int mt7615_dma_init(struct mt7615_dev *dev) /* enable interrupts for TX/RX rings */ mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); + if (is_mt7622(&dev->mt76)) + mt7622_dma_sched_init(dev); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 5348bd28001c..d9e487ba98e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -20,6 +20,7 @@ #define MT7615_RATE_RETRY 2 #define MT7615_TX_RING_SIZE 1024 +#define MT7615_TX_MGMT_RING_SIZE 128 #define MT7615_TX_MCU_RING_SIZE 128 #define MT7615_TX_FWDL_RING_SIZE 128 @@ -56,6 +57,16 @@ enum mt7615_hw_txq_id { MT7615_TXQ_FWDL, }; +enum mt7622_hw_txq_id { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_FWDL = MT7615_TXQ_FWDL, + MT7622_TXQ_AC3, + MT7622_TXQ_MGMT, + MT7622_TXQ_MCU = 15, +}; + struct mt7615_rate_set { struct ieee80211_tx_rate probe_rate; struct ieee80211_tx_rate rates[4]; @@ -287,6 +298,11 @@ static inline bool is_mt7622(struct mt76_dev *dev) return mt76_chip(dev) == 0x7622; } +static inline bool is_mt7615(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7615; +} + static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 1d764c587d25..de71d2672cf7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -339,6 +339,27 @@ #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) +#define MT_DMASHDL_BASE 0x5000a000 +#define MT_DMASHDL_OPTIONAL 0x008 +#define MT_DMASHDL_PAGE 0x00c + +#define MT_DMASHDL_REFILL 0x010 + +#define MT_DMASHDL_PKT_MAX_SIZE 0x01c +#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) +#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) + +#define MT_DMASHDL_GROUP_QUOTA(_n) (0x020 + ((_n) << 2)) +#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) +#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) + +#define MT_DMASHDL_SCHED_SET0 0x0b0 +#define MT_DMASHDL_SCHED_SET1 0x0b4 + +#define MT_DMASHDL_Q_MAP(_n) (0x0d0 + ((_n) << 2)) +#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) +#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) + #define MT_LED_BASE_PHYS 0x80024000 #define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) From 5dff21eef6e52bab82053ea2b628cf35118f9fa8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 17 Dec 2019 12:56:00 +0100 Subject: [PATCH 137/168] mt76: mt7615: add eeprom support for MT7622 When sending EEPROM data to the MCU, MT7622 uses a longer buffer Co-developed-by: Shayne Chen Co-developed-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/eeprom.c | 1 + .../net/wireless/mediatek/mt76/mt7615/eeprom.h | 3 ++- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 17 +++++++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index c295c00759af..50ed6bd38f8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -84,6 +84,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: + case 0x7622: return 0; default: return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index c3bc69ac210e..18c7301521b7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -21,7 +21,8 @@ enum mt7615_eeprom_field { MT_EE_TX2_5G_G0_TARGET_POWER = 0x142, MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a, - __MT_EE_MAX = 0x3bf + MT7615_EE_MAX = 0x3bf, + MT7622_EE_MAX = 0x3db, }; #define MT_EE_NIC_CONF_TX_MASK GENMASK(7, 4) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 2352e7687790..e51e584bf81f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -621,18 +621,23 @@ int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) __le16 len; } __packed req_hdr = { .buffer_mode = 1, - .len = cpu_to_le16(__MT_EE_MAX - MT_EE_NIC_CONF_0), }; - int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + int ret, len, eep_len; u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + if (is_mt7622(&dev->mt76)) + eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0; + else + eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0; + + len = sizeof(req_hdr) + eep_len; req = kzalloc(len, GFP_KERNEL); if (!req) return -ENOMEM; + req_hdr.len = cpu_to_le16(eep_len); memcpy(req, &req_hdr, sizeof(req_hdr)); - memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); + memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, eep_len); ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, req, len, true); @@ -1285,7 +1290,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_phy *phy) }; s8 tx_power; - len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; + len = sizeof(req_hdr) + MT7615_EE_MAX - MT_EE_NIC_CONF_0; req = kzalloc(len, GFP_KERNEL); if (!req) return -ENOMEM; @@ -1293,7 +1298,7 @@ int mt7615_mcu_set_tx_power(struct mt7615_phy *phy) memcpy(req, &req_hdr, sizeof(req_hdr)); data = req + sizeof(req_hdr); memcpy(data, eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); + MT7615_EE_MAX - MT_EE_NIC_CONF_0); tx_power = hw->conf.power_level * 2; switch (n_chains) { From 8acb7afc693b9db2841bb5395c928063efafa7a5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 19 Dec 2019 22:57:40 +0100 Subject: [PATCH 138/168] mt76: mt7615: add calibration free support for MT7622 MT7622 uses fewer efuse overrides than MT7615 Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/eeprom.c | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 50ed6bd38f8b..b383d85df2c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -211,6 +211,26 @@ static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; } +static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) +{ + static const u16 ical[] = { + 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b + }; + u8 *eeprom = dev->mt76.eeprom.data; + u8 *otp = dev->mt76.otp.data; + int i; + + if (!otp) + return; + + for (i = 0; i < ARRAY_SIZE(ical); i++) { + if (!otp[ical[i]]) + continue; + + eeprom[ical[i]] = otp[ical[i]]; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -223,6 +243,8 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) if (ret && dev->mt76.otp.data) memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); + else if (is_mt7622(&dev->mt76)) + mt7622_apply_cal_free_data(dev); else mt7615_apply_cal_free_data(dev); From c3ad5e9d00af19c53dec1d8ae647a78ac377b593 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Dec 2019 11:15:20 +0100 Subject: [PATCH 139/168] mt76: mt7615: disable 5 GHz on MT7622 It is not supported by the chip, so avoid issues with potentially wrong EEPROM configurations. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index b383d85df2c3..ecf0f4458575 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -112,6 +112,9 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) break; } + if (is_mt7622(&dev->mt76)) + dev->mt76.cap.has_5ghz = false; + /* read tx-rx mask from eeprom */ val = mt76_rr(dev, MT_TOP_STRAP_STA); max_nss = val & MT_TOP_3NSS ? 3 : 4; From 35da599fcdc2af4db091a5ece968379d1d1d9d6e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Dec 2019 10:48:23 +0100 Subject: [PATCH 140/168] mt76: mt7615: implement probing and firmware loading on MT7622 MT7622 does not have a CR4 microcontroller, so it only uses its own N9 firmware. Co-developed-by: Shayne Chen Co-developed-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/Makefile | 1 + .../net/wireless/mediatek/mt76/mt7615/init.c | 4 + .../net/wireless/mediatek/mt76/mt7615/main.c | 28 ++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 85 ++++++++++++++++--- .../wireless/mediatek/mt76/mt7615/mt7615.h | 19 +++++ .../net/wireless/mediatek/mt76/mt7615/pci.c | 3 - .../net/wireless/mediatek/mt76/mt7615/regs.h | 9 ++ .../net/wireless/mediatek/mt76/mt7615/soc.c | 77 +++++++++++++++++ 8 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7615/soc.c diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile index a93d147edf44..5c6a220ed7e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -6,3 +6,4 @@ CFLAGS_trace.o := -I$(src) mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o mmio.o \ debugfs.o trace.o +mt7615e-$(CONFIG_MT7622_WMAC) += soc.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 1af941f83213..df6ef323f7a2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -442,6 +442,10 @@ int mt7615_register_device(struct mt7615_dev *dev) INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); + ret = mt7622_wmac_init(dev); + if (ret) + return ret; + ret = mt7615_init_hardware(dev); if (ret) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 9d895c840b0c..85066e842479 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -732,3 +732,31 @@ const struct ieee80211_ops mt7615_ops = { .set_antenna = mt7615_set_antenna, .set_coverage_class = mt7615_set_coverage_class, }; + +static int __init mt7615_init(void) +{ + int ret; + + ret = pci_register_driver(&mt7615_pci_driver); + if (ret) + return ret; + + if (IS_ENABLED(CONFIG_MT7622_WMAC)) { + ret = platform_driver_register(&mt7622_wmac_driver); + if (ret) + pci_unregister_driver(&mt7615_pci_driver); + } + + return ret; +} + +static void __exit mt7615_exit(void) +{ + if (IS_ENABLED(CONFIG_MT7622_WMAC)) + platform_driver_unregister(&mt7622_wmac_driver); + pci_unregister_driver(&mt7615_pci_driver); +} + +module_init(mt7615_init); +module_exit(mt7615_exit); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index e51e584bf81f..d8bdd88d9fe9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -29,7 +29,8 @@ struct mt7615_fw_trailer { __le32 len; } __packed; -#define MCU_PATCH_ADDRESS 0x80000 +#define MT7615_PATCH_ADDRESS 0x80000 +#define MT7622_PATCH_ADDRESS 0x9c000 #define N9_REGION_NUM 2 #define CR4_REGION_NUM 1 @@ -333,19 +334,50 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) &req, sizeof(req), true); } +static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +{ + if (!is_mt7622(&dev->mt76)) + return; + + regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC, + MT_INFRACFG_MISC_AP2CONN_WAKE, + !en * MT_INFRACFG_MISC_AP2CONN_WAKE); +} + static int mt7615_driver_own(struct mt7615_dev *dev) { mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN); + + mt7622_trigger_hif_int(dev, true); if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST, - MT_CFG_LPCR_HOST_FW_OWN, 0, 500)) { + MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } + mt7622_trigger_hif_int(dev, false); return 0; } -static int mt7615_load_patch(struct mt7615_dev *dev, const char *name) +static int mt7615_firmware_own(struct mt7615_dev *dev) +{ + mt7622_trigger_hif_int(dev, true); + + mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); + + if (is_mt7622(&dev->mt76) && + !mt76_poll_msec(dev, MT_CFG_LPCR_HOST, + MT_CFG_LPCR_HOST_FW_OWN, + MT_CFG_LPCR_HOST_FW_OWN, 3000)) { + dev_err(dev->mt76.dev, "Timeout for firmware own\n"); + return -EIO; + } + mt7622_trigger_hif_int(dev, false); + + return 0; +} + +static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) { const struct mt7615_patch_hdr *hdr; const struct firmware *fw = NULL; @@ -379,8 +411,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev, const char *name) len = fw->size - sizeof(*hdr); - ret = mt7615_mcu_init_download(dev, MCU_PATCH_ADDRESS, len, - DL_MODE_NEED_RSP); + ret = mt7615_mcu_init_download(dev, addr, len, DL_MODE_NEED_RSP); if (ret) { dev_err(dev->mt76.dev, "Download request failed\n"); goto out; @@ -561,7 +592,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - ret = mt7615_load_patch(dev, MT7615_ROM_PATCH); + ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH); if (ret) return ret; @@ -576,9 +607,38 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + return 0; +} - dev_dbg(dev->mt76.dev, "Firmware init done\n"); +static int mt7622_load_firmware(struct mt7615_dev *dev) +{ + int ret; + u32 val; + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE); + if (val != FW_STATE_FW_DOWNLOAD) { + dev_err(dev->mt76.dev, "Firmware is not ready for download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH); + if (ret) + return ret; + + ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE, + FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE, + FW_STATE_NORMAL_TRX), 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); return 0; } @@ -597,10 +657,15 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - ret = mt7615_load_firmware(dev); + if (is_mt7622(&dev->mt76)) + ret = mt7622_load_firmware(dev); + else + ret = mt7615_load_firmware(dev); if (ret) return ret; + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + dev_dbg(dev->mt76.dev, "Firmware init done\n"); set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); return 0; @@ -609,7 +674,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) void mt7615_mcu_exit(struct mt7615_dev *dev) { __mt76_mcu_restart(&dev->mt76); - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); + mt7615_firmware_own(dev); skb_queue_purge(&dev->mt76.mmio.mcu.res_q); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index d9e487ba98e0..9eb5cfcfe704 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -6,6 +6,7 @@ #include #include +#include #include "../mt76.h" #include "regs.h" @@ -31,6 +32,9 @@ #define MT7615_FIRMWARE_N9 "mediatek/mt7615_n9.bin" #define MT7615_ROM_PATCH "mediatek/mt7615_rom_patch.bin" +#define MT7622_FIRMWARE_N9 "mediatek/mt7622_n9.bin" +#define MT7622_ROM_PATCH "mediatek/mt7622_rom_patch.bin" + #define MT7615_EEPROM_SIZE 1024 #define MT7615_TOKEN_SIZE 4096 @@ -148,6 +152,8 @@ struct mt7615_dev { u16 chainmask; + struct regmap *infracfg; + struct work_struct mcu_work; struct list_head sta_poll_list; @@ -241,6 +247,16 @@ mt7615_ext_phy(struct mt7615_dev *dev) extern const struct ieee80211_ops mt7615_ops; extern struct pci_driver mt7615_pci_driver; +extern struct platform_driver mt7622_wmac_driver; + +#ifdef CONFIG_MT7622_WMAC +int mt7622_wmac_init(struct mt7615_dev *dev); +#else +static inline int mt7622_wmac_init(struct mt7615_dev *dev) +{ + return 0; +} +#endif int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq); u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr); @@ -295,6 +311,9 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); static inline bool is_mt7622(struct mt76_dev *dev) { + if (!IS_ENABLED(CONFIG_MT7622_WMAC)) + return false; + return mt76_chip(dev) == 0x7622; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index caaad936a34a..43e02128cc48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -53,10 +53,7 @@ struct pci_driver mt7615_pci_driver = { .remove = mt7615_pci_remove, }; -module_pci_driver(mt7615_pci_driver); - MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table); MODULE_FIRMWARE(MT7615_FIRMWARE_CR4); MODULE_FIRMWARE(MT7615_FIRMWARE_N9); MODULE_FIRMWARE(MT7615_ROM_PATCH); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index de71d2672cf7..abecb3bfbc4b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -8,6 +8,10 @@ #define MT_HW_CHIPID 0x1008 #define MT_TOP_STRAP_STA 0x1010 #define MT_TOP_3NSS BIT(24) + +#define MT_TOP_OFF_RSV 0x1128 +#define MT_TOP_OFF_RSV_FW_STATE GENMASK(18, 16) + #define MT_TOP_MISC2 0x1134 #define MT_TOP_MISC2_FW_STATE GENMASK(2, 0) @@ -49,6 +53,7 @@ #define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) #define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0 BIT(9) +#define MT_WPDMA_GLO_CFG_BYPASS_TX_SCH BIT(9) /* MT7622 */ #define MT_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) #define MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21 GENMASK(23, 22) @@ -395,4 +400,8 @@ #define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) #define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) +/* INFRACFG host register range on MT7622 */ +#define MT_INFRACFG_MISC 0x700 +#define MT_INFRACFG_MISC_AP2CONN_WAKE BIT(1) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c new file mode 100644 index 000000000000..07ec9ec282f5 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee + * Felix Fietkau + */ + +#include +#include +#include +#include +#include +#include +#include "mt7615.h" + +int mt7622_wmac_init(struct mt7615_dev *dev) +{ + struct device_node *np = dev->mt76.dev->of_node; + + if (!is_mt7622(&dev->mt76)) + return 0; + + dev->infracfg = syscon_regmap_lookup_by_phandle(np, "mediatek,infracfg"); + if (IS_ERR(dev->infracfg)) { + dev_err(dev->mt76.dev, "Cannot find infracfg controller\n"); + return PTR_ERR(dev->infracfg); + } + + return 0; +} + +static int mt7622_wmac_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + void __iomem *mem_base; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get device IRQ\n"); + return irq; + } + + mem_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mem_base)) { + dev_err(&pdev->dev, "Failed to get memory resource\n"); + return PTR_ERR(mem_base); + } + + return mt7615_mmio_probe(&pdev->dev, mem_base, irq); +} + +static int mt7622_wmac_remove(struct platform_device *pdev) +{ + struct mt7615_dev *dev = platform_get_drvdata(pdev); + + mt7615_unregister_device(dev); + + return 0; +} + +static const struct of_device_id mt7622_wmac_of_match[] = { + { .compatible = "mediatek,mt7622-wmac" }, + {}, +}; + +struct platform_driver mt7622_wmac_driver = { + .driver = { + .name = "mt7622-wmac", + .of_match_table = mt7622_wmac_of_match, + }, + .probe = mt7622_wmac_probe, + .remove = mt7622_wmac_remove, +}; + +MODULE_FIRMWARE(MT7622_FIRMWARE_N9); +MODULE_FIRMWARE(MT7622_ROM_PATCH); From 6aa4ed7927f11620c6b06c408ebcfae4250ce7ca Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Dec 2019 17:46:27 +0100 Subject: [PATCH 141/168] mt76: mt7615: implement DMA support for MT7622 MT7622 does not have the CR4 microcontroller sitting in the data path. Because of that, it uses the chip's native tx descriptor format instead of something parsed and converted by the firmware. Co-developed-by: Shayne Chen Co-developed-by: Ryder Lee Signed-off-by: Felix Fietkau Signed-off-by: Lorenzo Bianconi --- .../net/wireless/mediatek/mt76/mt7615/init.c | 5 +- .../net/wireless/mediatek/mt76/mt7615/mac.c | 229 +++++++++++++----- .../net/wireless/mediatek/mt76/mt7615/mac.h | 32 ++- .../net/wireless/mediatek/mt76/mt7615/mmio.c | 2 +- 4 files changed, 204 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index df6ef323f7a2..79b177ac4261 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -346,7 +346,10 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); - hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + if (is_mt7615(&phy->dev->mt76)) + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + else + hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM; } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 49924d502daa..b8ee49fc02ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -396,13 +396,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, if (e->skb == DMA_DUMMY_DATA) { struct mt76_txwi_cache *t; struct mt7615_dev *dev; - struct mt7615_txp *txp; + struct mt7615_txp_common *txp; + u16 token; dev = container_of(mdev, struct mt7615_dev, mt76); txp = mt7615_txwi_to_txp(mdev, e->txwi); + if (is_mt7615(&dev->mt76)) + token = le16_to_cpu(txp->fw.token); + else + token = le16_to_cpu(txp->hw.msdu_id[0]) & + ~MT_MSDU_ID_VALID; + spin_lock_bh(&dev->token_lock); - t = idr_remove(&dev->token, le16_to_cpu(txp->token)); + t = idr_remove(&dev->token, token); spin_unlock_bh(&dev->token_lock); e->skb = t ? t->skb : NULL; } @@ -621,18 +628,56 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, return 0; } -void mt7615_txp_skb_unmap(struct mt76_dev *dev, - struct mt76_txwi_cache *t) +static void +mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) { - struct mt7615_txp *txp; int i; - txp = mt7615_txwi_to_txp(dev, t); for (i = 1; i < txp->nbuf; i++) dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); } +static void +mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { + struct mt7615_txp_ptr *ptr = &txp->ptr[i]; + bool last; + u16 len; + + len = le16_to_cpu(ptr->len0); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, + DMA_TO_DEVICE); + if (last) + break; + + len = le16_to_cpu(ptr->len1); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, + DMA_TO_DEVICE); + if (last) + break; + } +} + +void mt7615_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt7615_txp_common *txp; + + txp = mt7615_txwi_to_txp(dev, t); + if (is_mt7615(dev)) + mt7615_txp_skb_unmap_fw(dev, &txp->fw); + else + mt7615_txp_skb_unmap_hw(dev, &txp->hw); +} + static u32 mt7615_mac_wtbl_addr(int wcid) { return MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE; @@ -1022,21 +1067,93 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, return err; } +static void +mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id) +{ + struct mt7615_hw_txp *txp = txp_ptr; + struct mt7615_txp_ptr *ptr = &txp->ptr[0]; + int nbuf = tx_info->nbuf - 1; + int i; + + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); + tx_info->nbuf = 1; + + txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); + + for (i = 0; i < nbuf; i++) { + u32 addr = tx_info->buf[i + 1].addr; + u16 len = tx_info->buf[i + 1].len; + + if (i == nbuf - 1) + len |= MT_TXD_LEN_MSDU_LAST | + MT_TXD_LEN_AMSDU_LAST; + + if (i & 1) { + ptr->buf1 = cpu_to_le32(addr); + ptr->len1 = cpu_to_le16(len); + ptr++; + } else { + ptr->buf0 = cpu_to_le32(addr); + ptr->len0 = cpu_to_le16(len); + } + } +} + +static void +mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info, + void *txp_ptr, u32 id) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); + struct ieee80211_key_conf *key = info->control.hw_key; + struct ieee80211_vif *vif = info->control.vif; + struct mt7615_fw_txp *txp = txp_ptr; + int nbuf = tx_info->nbuf - 1; + int i; + + for (i = 0; i < nbuf; i++) { + txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); + txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); + } + txp->nbuf = nbuf; + + /* pass partial skb header to fw */ + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); + tx_info->buf[1].len = MT_CT_PARSE_LEN; + tx_info->nbuf = MT_CT_DMA_BUF_NUM; + + txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); + + if (!key) + txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); + + if (ieee80211_is_mgmt(hdr->frame_control)) + txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); + + if (vif) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + + txp->bss_idx = mvif->idx; + } + + txp->token = cpu_to_le16(id); + txp->rept_wds_wcid = 0xff; +} + int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data; struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; - struct ieee80211_vif *vif = info->control.vif; - int i, pid, id, nbuf = tx_info->nbuf - 1; + int pid, id; u8 *txwi = (u8 *)txwi_ptr; struct mt76_txwi_cache *t; - struct mt7615_txp *txp; + void *txp; if (!wcid) wcid = &dev->mt76.global_wcid; @@ -1056,34 +1173,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, spin_unlock_bh(&dev->mt76.lock); } - mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, - pid, key); - - txp = (struct mt7615_txp *)(txwi + MT_TXD_SIZE); - for (i = 0; i < nbuf; i++) { - txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); - txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); - } - txp->nbuf = nbuf; - - /* pass partial skb header to fw */ - tx_info->buf[1].len = MT_CT_PARSE_LEN; - tx_info->nbuf = MT_CT_DMA_BUF_NUM; - - txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD); - - if (!key) - txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME); - - if (ieee80211_is_mgmt(hdr->frame_control)) - txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME); - - if (vif) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - - txp->bss_idx = mvif->idx; - } - t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; @@ -1093,8 +1182,16 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (id < 0) return id; - txp->token = cpu_to_le16(id); - txp->rept_wds_wcid = 0xff; + mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, + pid, key); + + txp = txwi + MT_TXD_SIZE; + memset(txp, 0, sizeof(struct mt7615_txp_common)); + if (is_mt7615(&dev->mt76)) + mt7615_write_fw_txp(dev, tx_info, txp, id); + else + mt7615_write_hw_txp(dev, tx_info, txp, id); + tx_info->skb = DMA_DUMMY_DATA; return 0; @@ -1330,34 +1427,48 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) rcu_read_unlock(); } +static void +mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) +{ + struct mt76_dev *mdev = &dev->mt76; + struct mt76_txwi_cache *txwi; + + trace_mac_tx_free(dev, token); + + spin_lock_bh(&dev->token_lock); + txwi = idr_remove(&dev->token, token); + spin_unlock_bh(&dev->token_lock); + + if (!txwi) + return; + + mt7615_txp_skb_unmap(mdev, txwi); + if (txwi->skb) { + mt76_tx_complete_skb(mdev, txwi->skb); + txwi->skb = NULL; + } + + mt76_put_txwi(mdev, txwi); +} + void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; - struct mt76_dev *mdev = &dev->mt76; - struct mt76_txwi_cache *txwi; u8 i, count; count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); - for (i = 0; i < count; i++) { - u16 token = le16_to_cpu(free->token[i]); + if (is_mt7615(&dev->mt76)) { + __le16 *token = &free->token[0]; - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, token); - spin_unlock_bh(&dev->token_lock); + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i])); + } else { + __le32 *token = (__le32 *)&free->token[0]; - if (!txwi) - continue; - - trace_mac_tx_free(dev, token); - - mt7615_txp_skb_unmap(mdev, txwi); - if (txwi->skb) { - mt76_tx_complete_skb(mdev, txwi->skb); - txwi->skb = NULL; - } - - mt76_put_txwi(mdev, txwi); + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i])); } + dev_kfree_skb(skb); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 9b7c45bf1ec5..bf12eba549f7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -233,8 +233,27 @@ enum tx_phy_bandwidth { #define MT_TX_RATE_IDX GENMASK(5, 0) #define MT_TXP_MAX_BUF_NUM 6 +#define MT_HW_TXP_MAX_MSDU_NUM 4 +#define MT_HW_TXP_MAX_BUF_NUM 4 -struct mt7615_txp { +#define MT_MSDU_ID_VALID BIT(15) + +#define MT_TXD_LEN_MSDU_LAST BIT(14) +#define MT_TXD_LEN_AMSDU_LAST BIT(15) + +struct mt7615_txp_ptr { + __le32 buf0; + __le16 len0; + __le16 len1; + __le32 buf1; +} __packed __aligned(4); + +struct mt7615_hw_txp { + __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; + struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; +} __packed __aligned(4); + +struct mt7615_fw_txp { __le16 flags; __le16 token; u8 bss_idx; @@ -245,6 +264,13 @@ struct mt7615_txp { __le16 len[MT_TXP_MAX_BUF_NUM]; } __packed __aligned(4); +struct mt7615_txp_common { + union { + struct mt7615_fw_txp fw; + struct mt7615_hw_txp hw; + }; +}; + struct mt7615_tx_free { __le16 rx_byte_cnt; __le16 ctrl; @@ -353,7 +379,7 @@ enum mt7615_cipher_type { MT_CIPHER_GCMP_256, }; -static inline struct mt7615_txp * +static inline struct mt7615_txp_common * mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) { u8 *txwi; @@ -363,7 +389,7 @@ mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) txwi = mt76_get_txwi_ptr(dev, t); - return (struct mt7615_txp *)(txwi + MT_TXD_SIZE); + return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE); } #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index 4575bfda81c0..fcd8a8b4e816 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -60,7 +60,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq) { static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ - .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp), + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), .drv_flags = MT_DRV_TXWI_NO_FREE, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | From 8c90c2253eeaebc3ab708ea550c17c2668b6ff6c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 19 Dec 2019 22:21:44 +0100 Subject: [PATCH 142/168] mt76: mt7615: decrease rx ring size for MT7622 Since it's 2.4 GHz only, it needs fewer buffers Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/dma.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 41dea1aa58db..aeccb35e14f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -188,6 +188,7 @@ static void mt7622_dma_sched_init(struct mt7615_dev *dev) int mt7615_dma_init(struct mt7615_dev *dev) { + int rx_ring_size = MT7615_RX_RING_SIZE; int ret; mt76_dma_attach(&dev->mt76); @@ -236,9 +237,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret) return ret; + if (!is_mt7615(&dev->mt76)) + rx_ring_size /= 2; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, - MT7615_RX_RING_SIZE, MT_RX_BUF_SIZE, - MT_RX_RING_BASE); + rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE); if (ret) return ret; From eacf61101260dfe4839a7657ecf013c50ced77c0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 21 Dec 2019 22:57:07 +0100 Subject: [PATCH 143/168] mt76: mt7615: disable DBDC on MT7622 It is only supported on MT7615 Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 79b177ac4261..2f6ad2b24464 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -383,6 +383,9 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) struct mt76_phy *mphy; int ret; + if (!is_mt7615(&dev->mt76)) + return -EOPNOTSUPP; + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) return -EINVAL; From 8351943d3c70bff3fbbd8cab30e9f203e83b1ca9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 18 Dec 2019 17:49:59 +0100 Subject: [PATCH 144/168] mt76: mt7615: add Kconfig entry for MT7622 This enables building support for the MT7622 SoC built-in WLAN chip Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig index 4cabba9aa2ea..6afd4aea67ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig @@ -11,3 +11,14 @@ config MT7615E MU-MIMO up to 4 users/group and 160MHz channels. To compile this driver as a module, choose M here. + +config MT7622_WMAC + bool "MT7622 (SoC) WMAC support" + depends on MT7615E + depends on ARCH_MEDIATEK || COMPILE_TEST + select REGMAP + default y + help + This adds support for the built-in WMAC on MT7622 SoC devices + which has the same feature set as a MT7615, but limited to + 2.4 GHz only. From 15d9a5d7b556d776490082da67cae120c9db870d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 30 Jan 2020 14:12:43 +0100 Subject: [PATCH 145/168] mt76: mt7615: fix and rework tx power handling Setting the tx power by manipulating EEPROM may in some cases not be enough, since it only covers the base target power and not per-rate offsets. In other cases, it could limit tx power of rates too much, possibly reducing throughput or range. Use firmware support for applying per-rate limit and power offsets for different values of Nss. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 7 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 114 +++++++----------- .../net/wireless/mediatek/mt76/mt7615/mcu.h | 57 +++++++++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- 4 files changed, 105 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 85066e842479..4e40630f6107 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -241,6 +241,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mt7615_mac_set_timing(phy); ret = mt7615_dfs_init_radar_detector(phy); mt7615_mac_cca_stats_reset(phy); + mt7615_mcu_set_sku_en(phy, true); mt7615_mac_reset_counters(dev); phy->noise = 0; @@ -313,7 +314,8 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) bool band = phy != &dev->phy; int ret = 0; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | + IEEE80211_CONF_CHANGE_POWER)) { ieee80211_stop_queues(hw); ret = mt7615_set_channel(phy); ieee80211_wake_queues(hw); @@ -321,9 +323,6 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&dev->mt76.mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) - ret = mt7615_mcu_set_tx_power(phy); - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index d8bdd88d9fe9..1face7abb9bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1333,75 +1333,6 @@ int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, &req, sizeof(req), true); } -int mt7615_mcu_set_tx_power(struct mt7615_phy *phy) -{ - struct mt7615_dev *dev = phy->dev; - struct mt76_phy *mphy = phy->mt76; - int i, ret, n_chains = hweight8(mphy->antenna_mask); - struct cfg80211_chan_def *chandef = &mphy->chandef; - int freq = chandef->center_freq1, len, target_chains; - u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; - enum nl80211_band band = chandef->chan->band; - struct ieee80211_hw *hw = mphy->hw; - struct { - u8 center_chan; - u8 dbdc_idx; - u8 band; - u8 rsv; - } __packed req_hdr = { - .center_chan = ieee80211_frequency_to_channel(freq), - .band = band, - .dbdc_idx = phy != &dev->phy, - }; - s8 tx_power; - - len = sizeof(req_hdr) + MT7615_EE_MAX - MT_EE_NIC_CONF_0; - req = kzalloc(len, GFP_KERNEL); - if (!req) - return -ENOMEM; - - memcpy(req, &req_hdr, sizeof(req_hdr)); - data = req + sizeof(req_hdr); - memcpy(data, eep + MT_EE_NIC_CONF_0, - MT7615_EE_MAX - MT_EE_NIC_CONF_0); - - tx_power = hw->conf.power_level * 2; - switch (n_chains) { - case 4: - tx_power -= 12; - break; - case 3: - tx_power -= 8; - break; - case 2: - tx_power -= 6; - break; - default: - break; - } - tx_power = max_t(s8, tx_power, 0); - mphy->txpower_cur = tx_power; - - target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; - for (i = 0; i < target_chains; i++) { - int index = -MT_EE_NIC_CONF_0; - - ret = mt7615_eeprom_get_power_index(dev, chandef->chan, i); - if (ret < 0) - goto out; - - index += ret; - data[index] = min_t(u8, data[index], tx_power); - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, - req, len, true); -out: - kfree(req); - - return ret; -} - int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val) @@ -1502,6 +1433,30 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) &req, sizeof(req), false); } +static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) +{ + static const u8 nss_delta[4] = { 0, 6, 8, 12 }; + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_hw *hw = mphy->hw; + int n_chains = hweight8(mphy->antenna_mask); + int tx_power; + int i; + + tx_power = hw->conf.power_level * 2 - nss_delta[n_chains - 1]; + mphy->txpower_cur = tx_power; + + for (i = 0; i < MT_SKU_1SS_DELTA; i++) + sku[i] = tx_power; + + for (i = 0; i < 4; i++) { + int delta = 0; + + if (i < n_chains - 1) + delta = nss_delta[n_chains - 1] - nss_delta[i]; + sku[MT_SKU_1SS_DELTA + i] = delta; + } +} + int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) { struct mt7615_dev *dev = phy->dev; @@ -1568,7 +1523,8 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) req.bw = CMD_CBW_20MHZ; break; } - memset(req.txpower_sku, 0x3f, 49); + + mt7615_mcu_set_txpower_sku(phy, req.txpower_sku); return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } @@ -1837,3 +1793,21 @@ int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, sizeof(req), true); } + +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) +{ + struct mt7615_dev *dev = phy->dev; + struct { + u8 format_id; + u8 sku_enable; + u8 band_idx; + u8 rsv; + } req = { + .format_id = 0, + .band_idx = phy != &dev->phy, + .sku_enable = enable, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, + sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index b47d12a4c608..640b00b8aa32 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -45,6 +45,62 @@ enum { MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, }; +enum { + MT_SKU_CCK_1_2 = 0, + MT_SKU_CCK_55_11, + MT_SKU_OFDM_6_9, + MT_SKU_OFDM_12_18, + MT_SKU_OFDM_24_36, + MT_SKU_OFDM_48, + MT_SKU_OFDM_54, + MT_SKU_HT20_0_8, + MT_SKU_HT20_32, + MT_SKU_HT20_1_2_9_10, + MT_SKU_HT20_3_4_11_12, + MT_SKU_HT20_5_13, + MT_SKU_HT20_6_14, + MT_SKU_HT20_7_15, + MT_SKU_HT40_0_8, + MT_SKU_HT40_32, + MT_SKU_HT40_1_2_9_10, + MT_SKU_HT40_3_4_11_12, + MT_SKU_HT40_5_13, + MT_SKU_HT40_6_14, + MT_SKU_HT40_7_15, + MT_SKU_VHT20_0, + MT_SKU_VHT20_1_2, + MT_SKU_VHT20_3_4, + MT_SKU_VHT20_5_6, + MT_SKU_VHT20_7, + MT_SKU_VHT20_8, + MT_SKU_VHT20_9, + MT_SKU_VHT40_0, + MT_SKU_VHT40_1_2, + MT_SKU_VHT40_3_4, + MT_SKU_VHT40_5_6, + MT_SKU_VHT40_7, + MT_SKU_VHT40_8, + MT_SKU_VHT40_9, + MT_SKU_VHT80_0, + MT_SKU_VHT80_1_2, + MT_SKU_VHT80_3_4, + MT_SKU_VHT80_5_6, + MT_SKU_VHT80_7, + MT_SKU_VHT80_8, + MT_SKU_VHT80_9, + MT_SKU_VHT160_0, + MT_SKU_VHT160_1_2, + MT_SKU_VHT160_3_4, + MT_SKU_VHT160_5_6, + MT_SKU_VHT160_7, + MT_SKU_VHT160_8, + MT_SKU_VHT160_9, + MT_SKU_1SS_DELTA, + MT_SKU_2SS_DELTA, + MT_SKU_3SS_DELTA, + MT_SKU_4SS_DELTA, +}; + struct mt7615_mcu_rxd { __le32 rxd[4]; @@ -152,6 +208,7 @@ enum { MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, MCU_EXT_CMD_SET_RDD_TH = 0x7c, MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 9eb5cfcfe704..b43a09894487 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -357,7 +357,6 @@ int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable); int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val); int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int enter); int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index); -int mt7615_mcu_set_tx_power(struct mt7615_phy *phy); void mt7615_mcu_exit(struct mt7615_dev *dev); int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, @@ -383,6 +382,7 @@ int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, const struct mt7615_dfs_pulse *pulse); int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, const struct mt7615_dfs_pattern *pattern); +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_init_debugfs(struct mt7615_dev *dev); From f347f81a8ac98b5a2d67777222f0fce7d21685be Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 29 Dec 2019 13:49:18 +0100 Subject: [PATCH 146/168] mt76: mt7615: report firmware log event messages Useful for debugging firmware issues. Can be turned on via the "fw_debug" debugfs file Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 28 +++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.c | 39 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.h | 1 + .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 + 4 files changed, 70 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 783f145b7d02..158c0c183e9c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -71,6 +71,33 @@ mt7615_dbdc_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get, mt7615_dbdc_set, "%lld\n"); +static int +mt7615_fw_debug_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + dev->fw_debug = val; + mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0); + + return 0; +} + +static int +mt7615_fw_debug_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = dev->fw_debug; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get, + mt7615_fw_debug_set, "%lld\n"); + static int mt7615_ampdu_stat_read(struct seq_file *file, void *data) { @@ -222,6 +249,7 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("scs", 0600, dir, dev, &fops_scs); debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); + debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 1face7abb9bb..cd25ff8aed22 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -201,6 +201,28 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) dev->hw_pattern++; } +static void +mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; + const char *data = (char *)&rxd[1]; + const char *type; + + switch (rxd->s2d_index) { + case 0: + type = "N9"; + break; + case 2: + type = "CR4"; + break; + default: + type = "unknown"; + break; + } + + wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); +} + static void mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) { @@ -215,6 +237,9 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) IEEE80211_IFACE_ITER_RESUME_ALL, mt7615_mcu_csa_finish, dev); break; + case MCU_EXT_EVENT_FW_LOG_2_HOST: + mt7615_mcu_rx_log_message(dev, skb); + break; default: break; } @@ -643,6 +668,19 @@ static int mt7622_load_firmware(struct mt7615_dev *dev) return 0; } +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) +{ + struct { + u8 ctrl_val; + u8 pad[3]; + } data = { + .ctrl_val = ctrl + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, + &data, sizeof(data), true); +} + int mt7615_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7615_mcu_ops = { @@ -667,6 +705,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev) mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); dev_dbg(dev->mt76.dev, "Firmware init done\n"); set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt7615_mcu_fw_log_2_host(dev, 0); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 640b00b8aa32..2fbfbdb2c53d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -195,6 +195,7 @@ enum { MCU_EXT_CMD_PM_STATE_CTRL = 0x07, MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, + MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, MCU_EXT_CMD_STA_REC_UPDATE = 0x25, MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index b43a09894487..b4748cf079b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -169,6 +169,7 @@ struct mt7615_dev { u8 mac_work_count; bool scs_en; + bool fw_debug; spinlock_t token_lock; struct idr token; @@ -308,6 +309,7 @@ int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl); static inline bool is_mt7622(struct mt76_dev *dev) { From 61c4fa72196845b060147c044af7b25632ff6376 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 30 Jan 2020 17:42:55 +0100 Subject: [PATCH 147/168] mt76: mt7615: implement hardware reset support When the firmware detects a problem, it needs the host to stop/reset DMA and resume it again when the hardware state has been reset. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mcu.c | 3 +- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/dma.c | 3 +- .../net/wireless/mediatek/mt76/mt7615/init.c | 2 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 125 ++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mmio.c | 10 ++ .../wireless/mediatek/mt76/mt7615/mt7615.h | 6 + .../net/wireless/mediatek/mt76/mt7615/regs.h | 23 ++++ 8 files changed, 171 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 2a976688804d..b0fb0830c9e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -35,7 +35,8 @@ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, timeout = expires - jiffies; wait_event_timeout(dev->mmio.mcu.wait, - !skb_queue_empty(&dev->mmio.mcu.res_q), + (!skb_queue_empty(&dev->mmio.mcu.res_q) || + test_bit(MT76_MCU_RESET, &dev->phy.state)), timeout); return skb_dequeue(&dev->mmio.mcu.res_q); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 815d08486002..81f7df013073 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -274,6 +274,7 @@ enum { MT76_STATE_MCU_RUNNING, MT76_SCANNING, MT76_RESET, + MT76_MCU_RESET, MT76_REMOVED, MT76_READING_STATS, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index aeccb35e14f3..1bc71f5081ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -265,7 +265,8 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_RX_DMA_EN); /* enable interrupts for TX/RX rings */ - mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); + mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); if (is_mt7622(&dev->mt76)) mt7622_dma_sched_init(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 2f6ad2b24464..e7f251957fca 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -447,6 +447,8 @@ int mt7615_register_device(struct mt7615_dev *dev) INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); + init_waitqueue_head(&dev->reset_wait); + INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); ret = mt7622_wmac_init(dev); if (ret) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b8ee49fc02ed..b0d41ec68b77 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1782,6 +1782,131 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } +static bool +mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) +{ + bool ret; + + ret = wait_event_timeout(dev->reset_wait, + (READ_ONCE(dev->reset_state) & state), + MT7615_RESET_TIMEOUT); + WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); + return ret; +} + +static void +mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct ieee80211_hw *hw = priv; + + mt7615_mcu_set_bcn(hw, vif, vif->bss_conf.enable_beacon); +} + +static void +mt7615_update_beacons(struct mt7615_dev *dev) +{ + ieee80211_iterate_active_interfaces(dev->mt76.hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.hw); + + if (!dev->mt76.phy2) + return; + + ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.phy2->hw); +} + +static void +mt7615_dma_reset(struct mt7615_dev *dev) +{ + int i; + + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + usleep_range(1000, 2000); + + for (i = 0; i < __MT_TXQ_MAX; i++) + mt76_queue_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_queue_rx_reset(dev, i); + + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); +} + +void mt7615_mac_reset_work(struct work_struct *work) +{ + struct mt7615_dev *dev; + + dev = container_of(work, struct mt7615_dev, reset_work); + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_stop_queues(dev->mt76.phy2->hw); + + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + wake_up(&dev->mt76.mmio.mcu.wait); + cancel_delayed_work_sync(&dev->mt76.mac_work); + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (dev->mt76.phy2) + mt76_txq_schedule_all(dev->mt76.phy2); + + tasklet_disable(&dev->mt76.tx_tasklet); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); + + mutex_lock(&dev->mt76.mutex); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED); + + if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7615_dma_reset(dev); + + mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_INIT); + mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + } + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_RESET, &dev->mphy.state); + + tasklet_enable(&dev->mt76.tx_tasklet); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); + + napi_enable(&dev->mt76.napi[0]); + napi_schedule(&dev->mt76.napi[0]); + + napi_enable(&dev->mt76.napi[1]); + napi_schedule(&dev->mt76.napi[1]); + + ieee80211_wake_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_wake_queues(dev->mt76.phy2->hw); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mutex_unlock(&dev->mt76.mutex); + + mt7615_update_beacons(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); +} + static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index fcd8a8b4e816..0b445471b6e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -53,6 +53,16 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance) napi_schedule(&dev->mt76.napi[1]); } + if (intr & MT_INT_MCU_CMD) { + u32 val = mt76_rr(dev, MT_MCU_CMD); + + if (val & MT_MCU_CMD_ERROR_MASK) { + dev->reset_state = val; + ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + wake_up(&dev->reset_wait); + } + } + return IRQ_HANDLED; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index b4748cf079b1..95973e49c4a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -18,6 +18,7 @@ MT7615_MAX_INTERFACES) #define MT7615_WATCHDOG_TIME (HZ / 10) +#define MT7615_RESET_TIMEOUT (30 * HZ) #define MT7615_RATE_RETRY 2 #define MT7615_TX_RING_SIZE 1024 @@ -156,6 +157,10 @@ struct mt7615_dev { struct work_struct mcu_work; + struct work_struct reset_work; + wait_queue_head_t reset_wait; + u32 reset_state; + struct list_head sta_poll_list; spinlock_t sta_poll_lock; @@ -352,6 +357,7 @@ void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd); +void mt7615_mac_reset_work(struct work_struct *work); int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index abecb3bfbc4b..fe68f6b2cbf8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -35,6 +35,12 @@ #define MT_CFG_LPCR_HOST_FW_OWN BIT(0) #define MT_CFG_LPCR_HOST_DRV_OWN BIT(1) +#define MT_MCU_INT_EVENT MT_HIF(0x1f8) +#define MT_MCU_INT_EVENT_PDMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_PDMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + #define MT_INT_SOURCE_CSR MT_HIF(0x200) #define MT_INT_MASK_CSR MT_HIF(0x204) #define MT_DELAY_INT_CFG MT_HIF(0x210) @@ -43,6 +49,7 @@ #define MT_INT_RX_DONE_ALL GENMASK(1, 0) #define MT_INT_TX_DONE_ALL GENMASK(19, 4) #define MT_INT_TX_DONE(_n) BIT((_n) + 4) +#define MT_INT_MCU_CMD BIT(30) #define MT_WPDMA_GLO_CFG MT_HIF(0x208) #define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) @@ -63,6 +70,22 @@ #define MT_WPDMA_RST_IDX MT_HIF(0x20c) +#define MT_WPDMA_MEM_RNG_ERR MT_HIF(0x224) + +#define MT_MCU_CMD MT_HIF(0x234) +#define MT_MCU_CMD_CLEAR_FW_OWN BIT(0) +#define MT_MCU_CMD_STOP_PDMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_PDMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_LMAC_ERROR BIT(24) +#define MT_MCU_CMD_PSE_ERROR BIT(25) +#define MT_MCU_CMD_PLE_ERROR BIT(26) +#define MT_MCU_CMD_PDMA_ERROR BIT(27) +#define MT_MCU_CMD_PCIE_ERROR BIT(28) +#define MT_MCU_CMD_ERROR_MASK (GENMASK(5, 1) | GENMASK(28, 24)) + #define MT_TX_RING_BASE MT_HIF(0x300) #define MT_RX_RING_BASE MT_HIF(0x400) From 35492cd28f2a06623279a61955539fa6c5ae6067 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 31 Jan 2020 11:10:29 +0100 Subject: [PATCH 148/168] mt76: mt7615: add support for testing hardware reset Send an undersized corrupt packet to the DMA queue, which causes the firmware to issue a full chip reset Signed-off-by: Felix Fietkau --- .../wireless/mediatek/mt76/mt7615/debugfs.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 158c0c183e9c..7d8e53ac51ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -98,6 +98,28 @@ mt7615_fw_debug_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get, mt7615_fw_debug_set, "%lld\n"); +static int +mt7615_reset_test_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + struct sk_buff *skb; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + skb = alloc_skb(1, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_put(skb, 1); + mt76_tx_queue_skb_raw(dev, 0, skb, 0); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL, + mt7615_reset_test_set, "%lld\n"); + static int mt7615_ampdu_stat_read(struct seq_file *file, void *data) { @@ -264,6 +286,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) &dev->radar_pattern.power); debugfs_create_file("radar_trigger", 0200, dir, dev, &fops_radar_pattern); + debugfs_create_file("reset_test", 0200, dir, dev, + &fops_reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, mt7615_read_temperature); From dc80bb6f6ee64f6c7be2744cef96ec5973eee448 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:46 +0800 Subject: [PATCH 149/168] mt76: mt7615: simplify mcu_set_bmc flow Move set_bmc_wtbl into sta_rec function to simplify flow. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 3 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 97 ++++++++----------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 6 +- 3 files changed, 45 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 4e40630f6107..692cb8ae8e9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -427,8 +427,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BEACON_ENABLED) { mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); - mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); + mt7615_mcu_set_bmc(dev, vif, info->enable_beacon); } if (changed & (BSS_CHANGED_BEACON | diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index cd25ff8aed22..933a67c38ba8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1107,57 +1107,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, return ret; } -static int -mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, - struct mt7615_vif *mvif) -{ - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = 0xe, - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = 1, - .rca2 = 1, - .rv = 1, - }, - }; - eth_broadcast_addr(req.g_wtbl.peer_addr); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - - if (!enable) { - struct wtbl_req_hdr req = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); - } - - return mt7615_mcu_add_wtbl_bmc(dev, mvif); -} - int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { @@ -1217,14 +1166,15 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) &req, sizeof(req), true); } -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en) +int mt7615_mcu_set_bmc(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct { struct sta_req_hdr hdr; struct sta_rec_basic basic; - } req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = mvif->sta.wcid.idx, @@ -1238,8 +1188,18 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), }, }; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_generic *wtbl_g; + struct wtbl_rx *wtbl_rx; + u8 *buf = req.buf; + eth_broadcast_addr(req.basic.peer_addr); + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = mvif->sta.wcid.idx; + wtbl_hdr->operation = WTBL_RESET_AND_SET; + if (en) { req.basic.conn_state = CONN_STATE_PORT_SECURE; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | @@ -1247,10 +1207,37 @@ int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + + __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &req, (u8 *)wtbl_hdr - (u8 *)&req, true); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + (u8 *)wtbl_hdr, buf - (u8 *)wtbl_hdr, + true); } + wtbl_g = (struct wtbl_generic *)buf; + buf += sizeof(*wtbl_g); + wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); + wtbl_g->muar_idx = 0xe; + eth_broadcast_addr(wtbl_g->peer_addr); + + wtbl_rx = (struct wtbl_rx *)buf; + buf += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rv = 1; + wtbl_rx->rca1 = 1; + wtbl_rx->rca2 = 1; + + wtbl_hdr->tlv_num = cpu_to_le16(2); + + __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + (u8 *)wtbl_hdr, buf - (u8 *)wtbl_hdr, true); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, sizeof(req), true); + &req, (u8 *)wtbl_hdr - (u8 *)&req, true); } int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 95973e49c4a9..1c31b0f6f8b9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -286,14 +286,12 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, - bool enable); int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en); +int mt7615_mcu_set_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool en); int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool en); int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, From 20c3604f3e7c82eb01f5ab420e56e3e33be99852 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:47 +0800 Subject: [PATCH 150/168] mt76: mt7615: simplify mcu_set_sta flow Move mcu_add_wtbl and mcu_set_ht_cap into mcu_set_sta to simplify flow. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/main.c | 9 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 326 ++++++++---------- .../wireless/mediatek/mt76/mt7615/mt7615.h | 9 +- 3 files changed, 153 insertions(+), 191 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 692cb8ae8e9b..5df9521a654f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -470,10 +470,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_add_wtbl(dev, vif, sta); - mt7615_mcu_set_sta_rec(dev, vif, sta, 1); - if (sta->ht_cap.ht_supported) - mt7615_mcu_set_ht_cap(dev, vif, sta); + mt7615_mcu_set_sta(dev, vif, sta, 1); return 0; } @@ -484,9 +481,7 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - mt7615_mcu_set_sta_rec(dev, vif, sta, 0); - mt7615_mcu_del_wtbl(dev, sta); - + mt7615_mcu_set_sta(dev, vif, sta, 0); mt7615_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 933a67c38ba8..cecb534cad5e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1107,55 +1107,6 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, return ret; } -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = mvif->omac_idx, - .qos = sta->wme, - .partial_aid = cpu_to_le16(sta->aid), - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = vif->type != NL80211_IFTYPE_AP, - .rca2 = 1, - .rv = 1, - }, - }; - memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_req_hdr req = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) { struct wtbl_req_hdr req = { @@ -1240,8 +1191,8 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, &req, (u8 *)wtbl_hdr - (u8 *)&req, true); } -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en) +int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -1249,7 +1200,8 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, struct { struct sta_req_hdr hdr; struct sta_rec_basic basic; - } req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, @@ -1264,6 +1216,12 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, .aid = cpu_to_le16(sta->aid), }, }; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_generic *wtbl_g; + struct wtbl_rx *wtbl_rx; + u8 *buf = req.buf; + u8 wtlv = 0, stlv = 1; + memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); switch (vif->type) { @@ -1289,10 +1247,148 @@ int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); + + /* wtbl reset */ + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_RESET_AND_SET; + + __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + &req, req.buf - (u8 *)&req, true); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + req.buf, buf - req.buf, true); } + /* sta_rec ht */ + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *sta_ht; + + sta_ht = (struct sta_rec_ht *)buf; + buf += sizeof(*sta_ht); + sta_ht->tag = cpu_to_le16(STA_REC_HT); + sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); + sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + stlv++; + + /* sta_rec vht */ + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *sta_vht; + + sta_vht = (struct sta_rec_vht *)buf; + buf += sizeof(*sta_vht); + sta_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); + sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + sta_vht->vht_rx_mcs_map = + sta->vht_cap.vht_mcs.rx_mcs_map; + sta_vht->vht_tx_mcs_map = + sta->vht_cap.vht_mcs.tx_mcs_map; + stlv++; + } + } + + /* wtbl */ + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_RESET_AND_SET; + + wtbl_g = (struct wtbl_generic *)buf; + buf += sizeof(*wtbl_g); + wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); + wtbl_g->len = cpu_to_le16(sizeof(*wtbl_g)); + wtbl_g->muar_idx = mvif->omac_idx; + wtbl_g->qos = sta->wme; + wtbl_g->partial_aid = cpu_to_le16(sta->aid); + memcpy(wtbl_g->peer_addr, sta->addr, ETH_ALEN); + wtlv++; + + wtbl_rx = (struct wtbl_rx *)buf; + buf += sizeof(*wtbl_rx); + wtbl_rx->tag = cpu_to_le16(WTBL_RX); + wtbl_rx->len = cpu_to_le16(sizeof(*wtbl_rx)); + wtbl_rx->rv = 1; + wtbl_rx->rca1 = vif->type != NL80211_IFTYPE_AP; + wtbl_rx->rca2 = 1; + wtlv++; + + /* wtbl ht */ + if (sta->ht_cap.ht_supported) { + struct wtbl_ht *wtbl_ht; + struct wtbl_raw *wtbl_raw; + u32 val = 0, msk; + + wtbl_ht = (struct wtbl_ht *)buf; + buf += sizeof(*wtbl_ht); + wtbl_ht->tag = cpu_to_le16(WTBL_HT); + wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); + wtbl_ht->ht = 1; + wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + wtbl_ht->af = sta->ht_cap.ampdu_factor; + wtbl_ht->mm = sta->ht_cap.ampdu_density; + wtlv++; + + /* wtbl vht */ + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *wtbl_vht; + + wtbl_vht = (struct wtbl_vht *)buf; + buf += sizeof(*wtbl_vht); + wtbl_vht->tag = cpu_to_le16(WTBL_VHT); + wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); + wtbl_vht->vht = 1; + wtbl_vht->ldpc = sta->vht_cap.cap & + IEEE80211_VHT_CAP_RXLDPC; + wtlv++; + + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + val |= MT_WTBL_W5_SHORT_GI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + val |= MT_WTBL_W5_SHORT_GI_160; + } + + /* wtbl smps */ + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { + struct wtbl_smps *wtbl_smps; + + wtbl_smps = (struct wtbl_smps *)buf; + buf += sizeof(*wtbl_smps); + wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); + wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); + wtbl_smps->smps = 1; + wtlv++; + } + + /* sgi */ + msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | + MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; + + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + val |= MT_WTBL_W5_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + val |= MT_WTBL_W5_SHORT_GI_40; + + wtbl_raw = (struct wtbl_raw *)buf; + buf += sizeof(*wtbl_raw); + wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); + wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); + wtbl_raw->wtbl_idx = 1; + wtbl_raw->dw = 5; + wtbl_raw->msk = cpu_to_le32(~msk); + wtbl_raw->val = cpu_to_le32(val); + wtlv++; + } + + wtbl_hdr->tlv_num = cpu_to_le16(wtlv); + req.hdr.tlv_num = cpu_to_le16(stlv); + + __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, true); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, sizeof(req), true); + &req, (u8 *)wtbl_hdr - (u8 *)&req, true); } int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1555,130 +1651,6 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sta_req_hdr *sta_hdr; - struct wtbl_raw *wtbl_raw; - struct sta_rec_ht *sta_ht; - struct wtbl_ht *wtbl_ht; - int buf_len, ret, ntlv = 2; - u32 msk, val = 0; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_SET; - buf_len = sizeof(*wtbl_hdr); - - /* ht basic */ - wtbl_ht = (struct wtbl_ht *)(buf + buf_len); - wtbl_ht->tag = cpu_to_le16(WTBL_HT); - wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); - wtbl_ht->ht = 1; - wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; - wtbl_ht->af = sta->ht_cap.ampdu_factor; - wtbl_ht->mm = sta->ht_cap.ampdu_density; - buf_len += sizeof(*wtbl_ht); - - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - val |= MT_WTBL_W5_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - val |= MT_WTBL_W5_SHORT_GI_40; - - /* vht basic */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *wtbl_vht; - - wtbl_vht = (struct wtbl_vht *)(buf + buf_len); - buf_len += sizeof(*wtbl_vht); - wtbl_vht->tag = cpu_to_le16(WTBL_VHT); - wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); - wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; - wtbl_vht->vht = 1; - ntlv++; - - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) - val |= MT_WTBL_W5_SHORT_GI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) - val |= MT_WTBL_W5_SHORT_GI_160; - } - - /* smps */ - if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { - struct wtbl_smps *wtbl_smps; - - wtbl_smps = (struct wtbl_smps *)(buf + buf_len); - buf_len += sizeof(*wtbl_smps); - wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); - wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); - wtbl_smps->smps = 1; - ntlv++; - } - - /* sgi */ - msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | - MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; - - wtbl_raw = (struct wtbl_raw *)(buf + buf_len); - buf_len += sizeof(*wtbl_raw); - wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); - wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); - wtbl_raw->wtbl_idx = 1; - wtbl_raw->dw = 5; - wtbl_raw->msk = cpu_to_le32(~msk); - wtbl_raw->val = cpu_to_le32(val); - - wtbl_hdr->tlv_num = cpu_to_le16(ntlv); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - buf, buf_len, true); - if (ret) - goto out; - - memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); - - sta_hdr = (struct sta_req_hdr *)buf; - sta_hdr->bss_idx = mvif->idx; - sta_hdr->wlan_idx = msta->wcid.idx; - sta_hdr->is_tlv_append = 1; - ntlv = sta->vht_cap.vht_supported ? 2 : 1; - sta_hdr->tlv_num = cpu_to_le16(ntlv); - sta_hdr->muar_idx = mvif->omac_idx; - buf_len = sizeof(*sta_hdr); - - sta_ht = (struct sta_rec_ht *)(buf + buf_len); - sta_ht->tag = cpu_to_le16(STA_REC_HT); - sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); - sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - buf_len += sizeof(*sta_ht); - - if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_vht; - - sta_vht = (struct sta_rec_vht *)(buf + buf_len); - buf_len += sizeof(*sta_vht); - sta_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); - sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; - sta_vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - buf, buf_len, true); -out: - kfree(buf); - - return ret; -} - int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 1c31b0f6f8b9..688d45261696 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -286,14 +286,11 @@ int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); int mt7615_mcu_set_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en); -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en); +int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool en); int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int en); int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); @@ -305,8 +302,6 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, struct ieee80211_ampdu_params *params, bool add); -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, From 9190d90daa2c387b449282196976629e0c8ce3bf Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:48 +0800 Subject: [PATCH 151/168] mt76: mt7615: add a helper to encapsulate sta_rec operation Operating command is simpler and just as clear Signed-off-by: Ryder Lee Signed-off-by: Shayne Chen Tested-by: Sean Wang Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 124 ++++++++++-------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index cecb534cad5e..90ff69610c41 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1117,6 +1117,33 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) &req, sizeof(req), true); } +static int +mt7615_mcu_send_sta_rec(struct mt7615_dev *dev, u8 *req, u8 *wreq, + u8 wlen, bool enable) +{ + u32 slen = wreq - req; + int ret; + + if (!enable) { + ret = __mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD_STA_REC_UPDATE, + req, slen, true); + if (ret) + return ret; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + wreq, wlen, true); + } + + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, wreq, + wlen, true); + if (ret) + return ret; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + req, slen, true); +} + int mt7615_mcu_set_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool en) { @@ -1158,13 +1185,7 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - - __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, (u8 *)wtbl_hdr - (u8 *)&req, true); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - (u8 *)wtbl_hdr, buf - (u8 *)wtbl_hdr, - true); + goto out; } wtbl_g = (struct wtbl_generic *)buf; @@ -1184,11 +1205,9 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, wtbl_hdr->tlv_num = cpu_to_le16(2); - __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - (u8 *)wtbl_hdr, buf - (u8 *)wtbl_hdr, true); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, (u8 *)wtbl_hdr - (u8 *)&req, true); +out: + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, en); } int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, @@ -1205,7 +1224,6 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), .is_tlv_append = 1, .muar_idx = mvif->omac_idx, }, @@ -1244,49 +1262,38 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, req.basic.conn_state = CONN_STATE_PORT_SECURE; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | EXTRA_INFO_NEW); + + /* sta_rec ht */ + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *sta_ht; + + sta_ht = (struct sta_rec_ht *)buf; + buf += sizeof(*sta_ht); + sta_ht->tag = cpu_to_le16(STA_REC_HT); + sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); + sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + stlv++; + + /* sta_rec vht */ + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *sta_vht; + + sta_vht = (struct sta_rec_vht *)buf; + buf += sizeof(*sta_vht); + sta_vht->tag = cpu_to_le16(STA_REC_VHT); + sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); + sta_vht->vht_cap = + cpu_to_le32(sta->vht_cap.cap); + sta_vht->vht_rx_mcs_map = + sta->vht_cap.vht_mcs.rx_mcs_map; + sta_vht->vht_tx_mcs_map = + sta->vht_cap.vht_mcs.tx_mcs_map; + stlv++; + } + } } else { req.basic.conn_state = CONN_STATE_DISCONNECT; req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - - /* wtbl reset */ - wtbl_hdr = (struct wtbl_req_hdr *)buf; - buf += sizeof(*wtbl_hdr); - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_RESET_AND_SET; - - __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, req.buf - (u8 *)&req, true); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - req.buf, buf - req.buf, true); - } - - /* sta_rec ht */ - if (sta->ht_cap.ht_supported) { - struct sta_rec_ht *sta_ht; - - sta_ht = (struct sta_rec_ht *)buf; - buf += sizeof(*sta_ht); - sta_ht->tag = cpu_to_le16(STA_REC_HT); - sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); - sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - stlv++; - - /* sta_rec vht */ - if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_vht; - - sta_vht = (struct sta_rec_vht *)buf; - buf += sizeof(*sta_vht); - sta_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); - sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = - sta->vht_cap.vht_mcs.rx_mcs_map; - sta_vht->vht_tx_mcs_map = - sta->vht_cap.vht_mcs.tx_mcs_map; - stlv++; - } } /* wtbl */ @@ -1295,6 +1302,9 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtbl_hdr->wlan_idx = msta->wcid.idx; wtbl_hdr->operation = WTBL_RESET_AND_SET; + if (!en) + goto out; + wtbl_g = (struct wtbl_generic *)buf; buf += sizeof(*wtbl_g); wtbl_g->tag = cpu_to_le16(WTBL_GENERIC); @@ -1381,14 +1391,12 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, wtlv++; } +out: wtbl_hdr->tlv_num = cpu_to_le16(wtlv); req.hdr.tlv_num = cpu_to_le16(stlv); - __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, (u8 *)wtbl_hdr, - buf - (u8 *)wtbl_hdr, true); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &req, (u8 *)wtbl_hdr - (u8 *)&req, true); + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, en); } int mt7615_mcu_set_bcn(struct ieee80211_hw *hw, struct ieee80211_vif *vif, From 6849e29ed92ebd0d8c6909fb04b78bd1f869eac2 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:49 +0800 Subject: [PATCH 152/168] mt76: mt7615: add starec operating flow for firmware v2 Add fw_ver in mt7615_dev to check firmware version, and adjust mt7615_mcu_send_sta_rec() to adapt firmware v2 changes. Signed-off-by: Ryder Lee Signed-off-by: Shayne Chen Tested-by: Sean Wang Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 20 +++++++++++++------ .../wireless/mediatek/mt76/mt7615/mt7615.h | 5 +++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 90ff69610c41..9cebf5797fcf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -551,6 +551,11 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) sizeof(dev->mt76.hw->wiphy->fw_version), "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) + dev->fw_ver = MT7615_FIRMWARE_V2; + else + dev->fw_ver = MT7615_FIRMWARE_V1; + out: release_firmware(fw); return ret; @@ -1121,10 +1126,11 @@ static int mt7615_mcu_send_sta_rec(struct mt7615_dev *dev, u8 *req, u8 *wreq, u8 wlen, bool enable) { - u32 slen = wreq - req; + bool is_v1 = (dev->fw_ver == MT7615_FIRMWARE_V1); + u32 slen = is_v1 ? wreq - req : wreq - req + wlen; int ret; - if (!enable) { + if (is_v1 && !enable) { ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, req, slen, true); @@ -1135,10 +1141,12 @@ mt7615_mcu_send_sta_rec(struct mt7615_dev *dev, u8 *req, u8 *wreq, wreq, wlen, true); } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, wreq, - wlen, true); - if (ret) - return ret; + if (is_v1) { + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, + wreq, wlen, true); + if (ret) + return ret; + } return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, req, slen, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 688d45261696..2ecfddbd5ad4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -36,6 +36,9 @@ #define MT7622_FIRMWARE_N9 "mediatek/mt7622_n9.bin" #define MT7622_ROM_PATCH "mediatek/mt7622_rom_patch.bin" +#define MT7615_FIRMWARE_V1 1 +#define MT7615_FIRMWARE_V2 2 + #define MT7615_EEPROM_SIZE 1024 #define MT7615_TOKEN_SIZE 4096 @@ -178,6 +181,8 @@ struct mt7615_dev { spinlock_t token_lock; struct idr token; + + u8 fw_ver; }; enum { From 184dd9a11d7d52ef42830ebfe6e2d979ba0d7006 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:50 +0800 Subject: [PATCH 153/168] mt76: mt7615: use new tag sta_rec_wtbl In order to reduce command/event times, newer firmware adds a tag sta_rec_wtbl to take care of WTBL operations. MCU_EXT_CMD_WTBL_UPDATE is deprecated. Signed-off-by: Ryder Lee Signed-off-by: Shayne Chen Tested-by: Sean Wang Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 22 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7615/mcu.h | 8 ++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 9cebf5797fcf..72a3f9db7d21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1174,6 +1174,7 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), }, }; + struct sta_rec_wtbl *wtbl = NULL; struct wtbl_req_hdr *wtbl_hdr; struct wtbl_generic *wtbl_g; struct wtbl_rx *wtbl_rx; @@ -1181,6 +1182,13 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, eth_broadcast_addr(req.basic.peer_addr); + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } + wtbl_hdr = (struct wtbl_req_hdr *)buf; buf += sizeof(*wtbl_hdr); wtbl_hdr->wlan_idx = mvif->sta.wcid.idx; @@ -1214,6 +1222,9 @@ int mt7615_mcu_set_bmc(struct mt7615_dev *dev, wtbl_hdr->tlv_num = cpu_to_le16(2); out: + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, buf - (u8 *)wtbl_hdr, en); } @@ -1242,6 +1253,7 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, .aid = cpu_to_le16(sta->aid), }, }; + struct sta_rec_wtbl *wtbl = NULL; struct wtbl_req_hdr *wtbl_hdr; struct wtbl_generic *wtbl_g; struct wtbl_rx *wtbl_rx; @@ -1305,6 +1317,13 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, } /* wtbl */ + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + stlv++; + } + wtbl_hdr = (struct wtbl_req_hdr *)buf; buf += sizeof(*wtbl_hdr); wtbl_hdr->wlan_idx = msta->wcid.idx; @@ -1400,6 +1419,9 @@ int mt7615_mcu_set_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, } out: + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + wtbl_hdr->tlv_num = cpu_to_le16(wtlv); req.hdr.tlv_num = cpu_to_le16(stlv); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 2fbfbdb2c53d..db0199e60cb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -565,9 +565,10 @@ struct sta_rec_ba { __le16 winsize; } __packed; -#define MT7615_STA_REC_UPDATE_MAX_SIZE (sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_vht)) +struct sta_rec_wtbl { + __le16 tag; + __le16 len; +} __packed; enum { STA_REC_BASIC, @@ -582,6 +583,7 @@ enum { STA_REC_HT, STA_REC_VHT, STA_REC_APPS, + STA_REC_WTBL = 13, STA_REC_MAX_NUM }; From 4690da34f1548df55773dde859f3c3bc8ff5cbee Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:51 +0800 Subject: [PATCH 154/168] mt76: mt7615: switch mt7615_mcu_set_tx_ba to v2 format To adapt new firmware version. Signed-off-by: Ryder Lee Tested-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 72a3f9db7d21..29d54e3f09dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1695,28 +1695,11 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, { struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_ORIGINATOR, - .sn = add ? cpu_to_le16(params->ssn) : 0, - .ba_en = add, - }, - }; struct { struct sta_req_hdr hdr; struct sta_rec_ba ba; - } sta_req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, @@ -1735,7 +1718,32 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, .winsize = cpu_to_le16(params->buf_size), }, }; - int ret; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_ba *wtbl_ba; + u8 *buf = req.buf; + + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } + + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + wtbl_hdr->tlv_num = cpu_to_le16(1); + + wtbl_ba = (struct wtbl_ba *)buf; + buf += sizeof(*wtbl_ba); + wtbl_ba->tag = cpu_to_le16(WTBL_BA); + wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); + wtbl_ba->tid = params->tid; + wtbl_ba->ba_type = MT_BA_TYPE_ORIGINATOR; + wtbl_ba->sn = add ? cpu_to_le16(params->ssn) : 0; + wtbl_ba->ba_en = add; if (add) { u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; @@ -1745,16 +1753,14 @@ int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, break; } - wtbl_req.ba.ba_winsize_idx = idx; + wtbl_ba->ba_winsize_idx = idx; } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); - if (ret) - return ret; + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, true); } int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, From e07880b24d088f8e5a31a4aac930fa71877706cb Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 1 Feb 2020 23:33:52 +0800 Subject: [PATCH 155/168] mt76: mt7615: switch mt7615_mcu_set_rx_ba to v2 format To adapt new firmware version. Signed-off-by: Ryder Lee Tested-by: Shayne Chen Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 29d54e3f09dc..f5b04afe9cf4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1769,29 +1769,11 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, { struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; struct mt7615_vif *mvif = msta->vif; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_RECIPIENT, - .rst_ba_tid = params->tid, - .rst_ba_sel = RST_BA_MAC_TID_MATCH, - .rst_ba_sb = 1, - }, - }; struct { struct sta_req_hdr hdr; struct sta_rec_ba ba; - } sta_req = { + u8 buf[MT7615_WTBL_UPDATE_MAX_SIZE]; + } __packed req = { .hdr = { .bss_idx = mvif->idx, .wlan_idx = msta->wcid.idx, @@ -1810,17 +1792,41 @@ int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, .winsize = cpu_to_le16(params->buf_size), }, }; - int ret; + struct sta_rec_wtbl *wtbl = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct wtbl_ba *wtbl_ba; + u8 *buf = req.buf; - memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); + if (dev->fw_ver > MT7615_FIRMWARE_V1) { + req.hdr.tlv_num = cpu_to_le16(2); + wtbl = (struct sta_rec_wtbl *)buf; + wtbl->tag = cpu_to_le16(STA_REC_WTBL); + buf += sizeof(*wtbl); + } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); - if (ret || !add) - return ret; + wtbl_hdr = (struct wtbl_req_hdr *)buf; + buf += sizeof(*wtbl_hdr); + wtbl_hdr->wlan_idx = msta->wcid.idx; + wtbl_hdr->operation = WTBL_SET; + wtbl_hdr->tlv_num = cpu_to_le16(1); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); + wtbl_ba = (struct wtbl_ba *)buf; + buf += sizeof(*wtbl_ba); + wtbl_ba->tag = cpu_to_le16(WTBL_BA); + wtbl_ba->len = cpu_to_le16(sizeof(*wtbl_ba)); + wtbl_ba->tid = params->tid; + wtbl_ba->ba_type = MT_BA_TYPE_RECIPIENT; + wtbl_ba->rst_ba_tid = params->tid; + wtbl_ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; + wtbl_ba->rst_ba_sb = 1; + + memcpy(wtbl_ba->peer_addr, params->sta->addr, ETH_ALEN); + + if (wtbl) + wtbl->len = cpu_to_le16(buf - (u8 *)wtbl_hdr); + + return mt7615_mcu_send_sta_rec(dev, (u8 *)&req, (u8 *)wtbl_hdr, + buf - (u8 *)wtbl_hdr, add); } int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) From c5502b89ee68da9992160cf2c5111d8b660e8698 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 2 Feb 2020 16:12:49 +0100 Subject: [PATCH 156/168] mt76: mt7615: fix adding active monitor interfaces Treat them the same as AP iftype internally for MCU commands Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 5df9521a654f..f1321fc2f362 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -97,6 +97,7 @@ static int get_omac_idx(enum nl80211_iftype type, u32 mask) int i; switch (type) { + case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: From 8e2ad48e2bac60d86a69b778a47c6390818f6589 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 2 Feb 2020 16:24:08 +0100 Subject: [PATCH 157/168] mt76: mt7615: fix monitor mode on second PHY The second PHY receives no packets unless there is an active vif present. Set the WANT_MONITOR_VIF flag to deal with that Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt7615/main.c | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index e7f251957fca..4c9f52e04bb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -415,6 +415,9 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) mphy->sband_2g.sband.n_channels = 0; mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + /* The second interface does not get any packets unless it has a vif */ + ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + ret = mt76_register_phy(mphy); if (ret) ieee80211_free_hw(mphy->hw); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index f1321fc2f362..8a62d7d0c104 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -177,9 +177,11 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); - mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; - mt76_txq_init(&dev->mt76, vif->txq); + if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + } out: mutex_unlock(&dev->mt76.mutex); @@ -201,7 +203,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_mcu_set_dev_info(dev, vif, 0); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - mt76_txq_remove(&dev->mt76, vif->txq); + if (vif->txq) + mt76_txq_remove(&dev->mt76, vif->txq); mutex_lock(&dev->mt76.mutex); dev->vif_mask &= ~BIT(mvif->idx); From 43ba19228cfacaa18363dfb9e88074f8322d22f3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 6 Feb 2020 18:30:08 +0100 Subject: [PATCH 158/168] mt76: avoid extra RCU synchronization on station removal Use sta_pre_rcu_remove callback to clear wcid pointer earlier Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 16 +++++++++++++--- drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt7603/main.c | 1 + drivers/net/wireless/mediatek/mt76/mt7615/main.c | 1 + drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 + drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 1 + .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 2 ++ .../net/wireless/mediatek/mt76/mt76x2/pci_main.c | 1 + .../net/wireless/mediatek/mt76/mt76x2/usb_main.c | 1 + 9 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index a9909debf9de..4b19ac91ab72 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -984,9 +984,6 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; int i, idx = wcid->idx; - rcu_assign_pointer(dev->wcid[idx], NULL); - synchronize_rcu(); - for (i = 0; i < ARRAY_SIZE(wcid->aggr); i++) mt76_rx_aggr_stop(dev, wcid, i); @@ -1036,6 +1033,19 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76_sta_state); +void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt76_phy *phy = hw->priv; + struct mt76_dev *dev = phy->dev; + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + mutex_lock(&dev->mutex); + rcu_assign_pointer(dev->wcid[wcid->idx], NULL); + mutex_unlock(&dev->mutex); +} +EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove); + int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 81f7df013073..ca9d8ae43fec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -806,6 +806,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_sta_state new_state); void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index e5776d936c0a..26cb711b465f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -680,6 +680,7 @@ const struct ieee80211_ops mt7603_ops = { .configure_filter = mt7603_configure_filter, .bss_info_changed = mt7603_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7603_set_key, .conf_tx = mt7603_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 8a62d7d0c104..001760709379 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -712,6 +712,7 @@ const struct ieee80211_ops mt7615_ops = { .bss_info_changed = mt7615_bss_info_changed, .sta_add = mt7615_sta_add, .sta_remove = mt7615_sta_remove, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7615_set_key, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 88ff51400f8f..0b520ae08d01 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -67,6 +67,7 @@ static const struct ieee80211_ops mt76x0e_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 747d21b3ee57..5535b9c0632f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -126,6 +126,7 @@ static const struct ieee80211_ops mt76x0u_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 93d56d7ce5db..3d8bd61c5b43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -427,6 +427,8 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) if (!wcid) continue; + rcu_assign_pointer(dev->mt76.wcid[i], NULL); + priv = msta = container_of(wcid, struct mt76x02_sta, wcid); sta = container_of(priv, struct ieee80211_sta, drv_priv); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index dd336f54b8ee..105e5b99b3f9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -145,6 +145,7 @@ const struct ieee80211_ops mt76x2_ops = { .configure_filter = mt76x02_configure_filter, .bss_info_changed = mt76x02_bss_info_changed, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .conf_tx = mt76x02_conf_tx, .sw_scan_start = mt76_sw_scan, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 746f1a8304a6..bab4e6e1904e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -105,6 +105,7 @@ const struct ieee80211_ops mt76x2u_ops = { .add_interface = mt76x02_add_interface, .remove_interface = mt76x02_remove_interface, .sta_state = mt76_sta_state, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt76x02_set_key, .ampdu_action = mt76x02_ampdu_action, .config = mt76x2u_config, From 049019c2a07d7b6c86fff9885cb96ab3095f6583 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 6 Feb 2020 18:31:08 +0100 Subject: [PATCH 159/168] mt76: mt76x2: avoid starting the MAC too early Do not set the tx/rx start bits in MT_MAC_SYS_CTRL from within initvals. The driver sets these later when the hardware is ready Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index 79e583eb066b..a92a479aebaa 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -82,7 +82,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) { MT_PBF_SYS_CTRL, 0x00080c00 }, { MT_PBF_CFG, 0x1efebcff }, { MT_FCE_PSE_CTRL, 0x00000001 }, - { MT_MAC_SYS_CTRL, 0x0000000c }, + { MT_MAC_SYS_CTRL, 0x00000000 }, { MT_MAX_LEN_CFG, 0x003e3f00 }, { MT_AMPDU_MAX_LEN_20M1S, 0xaaa99887 }, { MT_AMPDU_MAX_LEN_20M2S, 0x000000aa }, From 07cda406308b7d11cb77c406044b52752049e78d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 11 Feb 2020 21:00:56 +0100 Subject: [PATCH 160/168] mt76: fix rounding issues on converting per-chain and combined txpower Unify code converting between the different txpower values. Always add/remove the combined txpower delta before dividing half-dB values. Also fix the combined txpower delta values. The correct half-dB delta for 3 chains is 9, not 8. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 20 ++----------------- drivers/net/wireless/mediatek/mt76/mt76.h | 7 +++++++ .../net/wireless/mediatek/mt76/mt7615/init.c | 17 ++-------------- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 7 ++++--- 4 files changed, 15 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 4b19ac91ab72..f74fc7130ed2 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -1051,25 +1051,9 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct mt76_phy *phy = hw->priv; int n_chains = hweight8(phy->antenna_mask); + int delta = mt76_tx_power_nss_delta(n_chains); - *dbm = DIV_ROUND_UP(phy->txpower_cur, 2); - - /* convert from per-chain power to combined - * output power - */ - switch (n_chains) { - case 4: - *dbm += 6; - break; - case 3: - *dbm += 4; - break; - case 2: - *dbm += 3; - break; - default: - break; - } + *dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index ca9d8ae43fec..844e58f18a2a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -755,6 +755,13 @@ static inline bool mt76_is_skb_pktid(u8 pktid) return pktid >= MT_PACKET_ID_FIRST; } +static inline u8 mt76_tx_power_nss_delta(u8 nss) +{ + static const u8 nss_delta[4] = { 0, 6, 9, 12 }; + + return nss_delta[nss - 1]; +} + void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb); void mt76_tx(struct mt76_phy *dev, struct ieee80211_sta *sta, struct mt76_wcid *wcid, struct sk_buff *skb); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 4c9f52e04bb8..889eb72ad6bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -269,6 +269,7 @@ mt7615_init_txpower(struct mt7615_dev *dev, int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; + int delta = mt76_tx_power_nss_delta(n_chains); target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < sband->n_channels; i++) { @@ -283,21 +284,7 @@ mt7615_init_txpower(struct mt7615_dev *dev, target_power = max(target_power, eep[index]); } - target_power = DIV_ROUND_UP(target_power, 2); - switch (n_chains) { - case 4: - target_power += 6; - break; - case 3: - target_power += 4; - break; - case 2: - target_power += 3; - break; - default: - break; - } - + target_power = DIV_ROUND_UP(target_power + delta, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f5b04afe9cf4..68f35aa15c60 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1595,14 +1595,14 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) { - static const u8 nss_delta[4] = { 0, 6, 8, 12 }; struct mt76_phy *mphy = phy->mt76; struct ieee80211_hw *hw = mphy->hw; int n_chains = hweight8(mphy->antenna_mask); int tx_power; int i; - tx_power = hw->conf.power_level * 2 - nss_delta[n_chains - 1]; + tx_power = hw->conf.power_level * 2 - + mt76_tx_power_nss_delta(n_chains); mphy->txpower_cur = tx_power; for (i = 0; i < MT_SKU_1SS_DELTA; i++) @@ -1612,7 +1612,8 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) int delta = 0; if (i < n_chains - 1) - delta = nss_delta[n_chains - 1] - nss_delta[i]; + delta = mt76_tx_power_nss_delta(n_chains) - + mt76_tx_power_nss_delta(i + 1); sku[MT_SKU_1SS_DELTA + i] = delta; } } From 0e544cb59c9a67d91e5356b0294991948d5ebdbe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 12 Feb 2020 09:07:49 +0100 Subject: [PATCH 161/168] mt76: mt7615: rework rx phy index handling Overwriting the RMAC_CHFREQ register is not reliable enough, as the firmware could potentially write it again. Since there is no PHY index indication in the rx info, we need to use another way: If both PHYs are using different channels, find the PHY where chfreq matches the register value. The only corner case remaining is when both PHYs are using the same channel. In that case, the per-packet noise value on the primary PHY will have information belonging to the chains of the secondary PHY from the previous received packet of that PHY. The secondary PHY will set noise to 0 for extra chains. Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt7615/mac.c | 111 +++++++++++------- .../net/wireless/mediatek/mt76/mt7615/mac.h | 5 + .../net/wireless/mediatek/mt76/mt7615/main.c | 7 +- .../wireless/mediatek/mt76/mt7615/mt7615.h | 2 +- 4 files changed, 75 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index b0d41ec68b77..22ec28bf80b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -169,36 +169,32 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; struct mt76_phy *mphy = &dev->mt76.phy; struct mt7615_phy *phy = &dev->phy; + struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; __le32 *rxd = (__le32 *)skb->data; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); + __le32 rxd12 = rxd[12]; bool unicast, remove_pad, insert_ccmp_hdr = false; + int phy_idx; int i, idx; u8 chfreq; memset(status, 0, sizeof(*status)); chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); - if (!(chfreq & MT_CHFREQ_VALID)) - return -EINVAL; - - if (chfreq & MT_CHFREQ_DBDC_IDX) { - mphy = dev->mt76.phy2; - if (!mphy) - return -EINVAL; - - phy = mphy->priv; - status->ext_phy = true; - } - - if ((chfreq & MT_CHFREQ_SEQ) != phy->chfreq_seq) - return -EINVAL; - - if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) - return -EINVAL; + if (!phy2) + phy_idx = 0; + else if (phy2->chfreq == phy->chfreq) + phy_idx = -1; + else if (phy->chfreq == chfreq) + phy_idx = 0; + else if (phy2->chfreq == chfreq) + phy_idx = 1; + else + phy_idx = -1; unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); @@ -214,13 +210,6 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } - status->freq = mphy->chandef.chan->center_freq; - status->band = mphy->chandef.chan->band; - if (status->band == NL80211_BAND_5GHZ) - sband = &mphy->sband_5g.sband; - else - sband = &mphy->sband_2g.sband; - if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -234,28 +223,11 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | - MT_RXD2_NORMAL_NON_AMPDU))) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (phy->rx_ampdu_ts != rxd[12]) { - if (!++phy->ampdu_ref) - phy->ampdu_ref++; - } - phy->rx_ampdu_ts = rxd[12]; - - status->ampdu_ref = phy->ampdu_ref; - } - remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) return -EINVAL; - if (!sband->channels) - return -EINVAL; - rxd += 4; if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { rxd += 4; @@ -287,6 +259,59 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) return -EINVAL; } + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + u32 rxdg5 = le32_to_cpu(rxd[5]); + + /* + * If both PHYs are on the same channel and we don't have a WCID, + * we need to figure out which PHY this packet was received on. + * On the primary PHY, the noise value for the chains belonging to the + * second PHY will be set to the noise value of the last packet from + * that PHY. + */ + if (phy_idx < 0) { + int first_chain = ffs(phy2->chainmask) - 1; + + phy_idx = ((rxdg5 >> (first_chain * 8)) & 0xff) == 0; + } + } + + if (phy_idx == 1 && phy2) { + mphy = dev->mt76.phy2; + phy = phy2; + status->ext_phy = true; + } + + if (chfreq != phy->chfreq) + return -EINVAL; + + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; + if (status->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + + if (!sband->channels) + return -EINVAL; + + if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | + MT_RXD2_NORMAL_NON_AMPDU))) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != rxd12) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = rxd12; + + status->ampdu_ref = phy->ampdu_ref; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { u32 rxdg0 = le32_to_cpu(rxd[0]); u32 rxdg1 = le32_to_cpu(rxd[1]); @@ -340,14 +365,14 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - status->chains = dev->mphy.antenna_mask; + status->chains = mphy->antenna_mask; status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); status->signal = status->chain_signal[0]; - for (i = 1; i < hweight8(dev->mphy.antenna_mask); i++) { + for (i = 1; i < hweight8(mphy->antenna_mask); i++) { if (!(status->chains & BIT(i))) continue; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index bf12eba549f7..6fa7e3dd6a3a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -103,6 +103,11 @@ enum rx_pkt_type { #define MT_RXV4_RCPI1 GENMASK(15, 8) #define MT_RXV4_RCPI0 GENMASK(7, 0) +#define MT_RXV6_NF3 GENMASK(31, 24) +#define MT_RXV6_NF2 GENMASK(23, 16) +#define MT_RXV6_NF1 GENMASK(15, 8) +#define MT_RXV6_NF0 GENMASK(7, 0) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 001760709379..01194ed79869 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -229,7 +229,6 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mutex_lock(&dev->mt76.mutex); set_bit(MT76_RESET, &phy->mt76->state); - phy->chfreq_seq = (phy->chfreq_seq + 1) & MT_CHFREQ_SEQ; phy->dfs_state = -1; mt76_set_channel(phy->mt76); @@ -237,11 +236,6 @@ static int mt7615_set_channel(struct mt7615_phy *phy) if (ret) goto out; - mt76_wr(dev, MT_CHFREQ(ext_phy), - MT_CHFREQ_VALID | - (ext_phy * MT_CHFREQ_DBDC_IDX) | - phy->chfreq_seq); - mt7615_mac_set_timing(phy); ret = mt7615_dfs_init_radar_detector(phy); mt7615_mac_cca_stats_reset(phy); @@ -249,6 +243,7 @@ static int mt7615_set_channel(struct mt7615_phy *phy) mt7615_mac_reset_counters(dev); phy->noise = 0; + phy->chfreq = mt76_rr(dev, MT_CHFREQ(ext_phy)); out: clear_bit(MT76_RESET, &phy->mt76->state); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 2ecfddbd5ad4..a84a9b4cbf4e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -134,7 +134,7 @@ struct mt7615_phy { s16 coverage_class; u8 slottime; - u8 chfreq_seq; + u8 chfreq; u8 rdd_state; int dfs_state; From e22d0b89647c2e14a21c046af4ea5fed7c2b2acc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 13 Feb 2020 22:56:33 +0100 Subject: [PATCH 162/168] mt76: do not set HOST_BROADCAST_PS_BUFFERING for mt7615 mt7615 handles powersave buffering in firmware Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 - drivers/net/wireless/mediatek/mt76/mt7603/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index f74fc7130ed2..bcba1fefd723 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -295,7 +295,6 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, PS_NULLFUNC_STACK); - ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); ieee80211_hw_set(hw, AMPDU_AGGREGATION); ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 182ce5a86f65..9e40e81bcc29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -557,6 +557,7 @@ int mt7603_register_device(struct mt7603_dev *dev) wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 48da4f3a17db..b7a120b0856d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -181,6 +181,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->vif_data_size = sizeof(struct mt76x02_vif); ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES); + ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); dev->mt76.global_wcid.idx = 255; dev->mt76.global_wcid.hw_key_idx = -1; From cf605a3bd9fb89ef8ab0f10d908bb556032424c5 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 9 Feb 2020 15:15:08 +0100 Subject: [PATCH 163/168] mt76: mt7615: rely on mt76_queues_read for mt7622 As previous devices, mt7622 relies on multiple hw queues while for mt7615 we have just on per band hw queue and the mcu demux the traffic according to the packet AC. In order to dump all configured hw queues, rely on mt76_queues_read for mt7622 in mt7615 debugfs Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/debugfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 2567c5d6945f..d2202acb8dc6 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -30,7 +30,7 @@ int mt76_queues_read(struct seq_file *s, void *data) struct mt76_dev *dev = dev_get_drvdata(s->private); int i; - for (i = 0; i < __MT_TXQ_MAX; i++) { + for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) { struct mt76_sw_queue *q = &dev->q_tx[i]; if (!q->q) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 7d8e53ac51ef..b4d0795154e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -264,8 +264,12 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) if (!dir) return -ENOMEM; - debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, - mt7615_queues_read); + if (is_mt7615(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt7615_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt76_queues_read); debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7615_queues_acq); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); From 972c598133d89d557479c70dfff2f52a9c62a472 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Mon, 10 Feb 2020 11:34:00 +0100 Subject: [PATCH 164/168] mt76: mt76u: extend RX scatter gather number Set RX scatter gather number to 4 in order to extend the maximum AMSDU size to 11,454. Signed-off-by: Sean Wang Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 844e58f18a2a..3809d9afdcee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -389,7 +389,7 @@ enum mt76u_out_ep { }; #define MT_TX_SG_MAX_SIZE 8 -#define MT_RX_SG_MAX_SIZE 1 +#define MT_RX_SG_MAX_SIZE 4 #define MT_NUM_TX_ENTRIES 256 #define MT_NUM_RX_ENTRIES 128 #define MCU_RESP_URB_SIZE 1024 From 5d5a99464abb00b51dd3b47e6c11793ef1d66ec2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 10 Feb 2020 11:36:48 +0100 Subject: [PATCH 165/168] mt76: mt76u: rename stat_wq in wq Rename usb stat_wq in wq in order to be reused not just for gathering hw tx statistics Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 3809d9afdcee..002e142ca893 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -400,7 +400,7 @@ struct mt76_usb { u16 data_len; struct tasklet_struct rx_tasklet; - struct workqueue_struct *stat_wq; + struct workqueue_struct *wq; struct work_struct stat_work; u8 out_ep[__MT_EP_OUT_MAX]; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 981d8a985557..3aa1425049d9 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -852,7 +852,7 @@ static void mt76u_tx_tasklet(unsigned long data) if (dev->drv->tx_status_data && !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) - queue_work(dev->usb.stat_wq, &dev->usb.stat_work); + queue_work(dev->usb.wq, &dev->usb.stat_work); if (wake) ieee80211_wake_queue(dev->hw, i); } @@ -878,7 +878,7 @@ static void mt76u_tx_status_data(struct work_struct *work) } if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state)) - queue_work(usb->stat_wq, &usb->stat_work); + queue_work(usb->wq, &usb->stat_work); else clear_bit(MT76_READING_STATS, &dev->phy.state); } @@ -1132,9 +1132,9 @@ static const struct mt76_queue_ops usb_queue_ops = { void mt76u_deinit(struct mt76_dev *dev) { - if (dev->usb.stat_wq) { - destroy_workqueue(dev->usb.stat_wq); - dev->usb.stat_wq = NULL; + if (dev->usb.wq) { + destroy_workqueue(dev->usb.wq); + dev->usb.wq = NULL; } } EXPORT_SYMBOL_GPL(mt76u_deinit); @@ -1160,8 +1160,8 @@ int mt76u_init(struct mt76_dev *dev, tasklet_init(&dev->tx_tasklet, mt76u_tx_tasklet, (unsigned long)dev); INIT_WORK(&usb->stat_work, mt76u_tx_status_data); - usb->stat_wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0); - if (!usb->stat_wq) + usb->wq = alloc_workqueue("mt76u", WQ_UNBOUND, 0); + if (!usb->wq) return -ENOMEM; usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); From a9fddf08ec666037c51546bc4e09a79998263944 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 11 Feb 2020 22:20:54 +0100 Subject: [PATCH 166/168] mt76: mt7615: remove rx_mask in mt7615_eeprom_parse_hw_cap Get rid of rx_mask in mt7615_eeprom_parse_hw_cap routine since it is not actually used Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index ecf0f4458575..5220c18e711f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -94,7 +94,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) { u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask, rx_mask, max_nss; + u8 tx_mask, max_nss; u32 val; val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, @@ -119,11 +119,6 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) val = mt76_rr(dev, MT_TOP_STRAP_STA); max_nss = val & MT_TOP_3NSS ? 3 : 4; - rx_mask = FIELD_GET(MT_EE_NIC_CONF_RX_MASK, - eeprom[MT_EE_NIC_CONF_0]); - if (!rx_mask || rx_mask > max_nss) - rx_mask = max_nss; - tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, eeprom[MT_EE_NIC_CONF_0]); if (!tx_mask || tx_mask > max_nss) From 0987295750574adc59999b8fb9890834574bc4e2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 8 Feb 2020 13:44:28 +0100 Subject: [PATCH 167/168] mt76: Introduce mt76_mcu data structure Introduce mt76_mcu data structure to contain common fields between mt76u_mcu and mt76e_mcu. Initialize mcu common fields in mt76_alloc_device(). Rely on mt76_mcu in mt76_mcu_rx_event and in mt76_mcu_get_response in order to reuse them in usb code Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 ++++ drivers/net/wireless/mediatek/mt76/mcu.c | 11 ++++----- drivers/net/wireless/mediatek/mt76/mmio.c | 3 --- drivers/net/wireless/mediatek/mt76/mt76.h | 21 ++++++++--------- .../net/wireless/mediatek/mt76/mt7603/mcu.c | 10 ++++---- .../net/wireless/mediatek/mt76/mt7615/mac.c | 2 +- .../net/wireless/mediatek/mt76/mt7615/mcu.c | 10 ++++---- .../net/wireless/mediatek/mt76/mt76x02_mcu.c | 10 ++++---- .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 4 ++-- .../net/wireless/mediatek/mt76/mt76x02_txrx.c | 1 - .../wireless/mediatek/mt76/mt76x02_usb_mcu.c | 23 ++++++++----------- drivers/net/wireless/mediatek/mt76/usb.c | 3 +-- 12 files changed, 48 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index bcba1fefd723..f44f99184c10 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -420,6 +420,10 @@ mt76_alloc_device(struct device *pdev, unsigned int size, init_waitqueue_head(&dev->tx_wait); skb_queue_head_init(&dev->status_list); + skb_queue_head_init(&dev->mcu.res_q); + init_waitqueue_head(&dev->mcu.wait); + mutex_init(&dev->mcu.mutex); + INIT_LIST_HEAD(&dev->txwi_cache); for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index b0fb0830c9e1..633ad948c21d 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -24,7 +24,6 @@ mt76_mcu_msg_alloc(const void *data, int head_len, } EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); -/* mmio */ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires) { @@ -34,17 +33,17 @@ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, return NULL; timeout = expires - jiffies; - wait_event_timeout(dev->mmio.mcu.wait, - (!skb_queue_empty(&dev->mmio.mcu.res_q) || + wait_event_timeout(dev->mcu.wait, + (!skb_queue_empty(&dev->mcu.res_q) || test_bit(MT76_MCU_RESET, &dev->phy.state)), timeout); - return skb_dequeue(&dev->mmio.mcu.res_q); + return skb_dequeue(&dev->mcu.res_q); } EXPORT_SYMBOL_GPL(mt76_mcu_get_response); void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) { - skb_queue_tail(&dev->mmio.mcu.res_q, skb); - wake_up(&dev->mmio.mcu.wait); + skb_queue_tail(&dev->mcu.res_q, skb); + wake_up(&dev->mcu.wait); } EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c index 1c974df1fe25..7ead6620bb8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mmio.c @@ -94,9 +94,6 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs) dev->bus = &mt76_mmio_ops; dev->mmio.regs = regs; - skb_queue_head_init(&dev->mmio.mcu.res_q); - init_waitqueue_head(&dev->mmio.mcu.wait); spin_lock_init(&dev->mmio.irq_lock); - mutex_init(&dev->mmio.mcu.mutex); } EXPORT_SYMBOL_GPL(mt76_mmio_init); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 002e142ca893..2e57e7c6bd29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -388,6 +388,14 @@ enum mt76u_out_ep { __MT_EP_OUT_MAX, }; +struct mt76_mcu { + struct mutex mutex; + u32 msg_seq; + + struct sk_buff_head res_q; + wait_queue_head_t wait; +}; + #define MT_TX_SG_MAX_SIZE 8 #define MT_RX_SG_MAX_SIZE 4 #define MT_NUM_TX_ENTRIES 256 @@ -408,10 +416,7 @@ struct mt76_usb { bool sg_en; struct mt76u_mcu { - struct mutex mutex; u8 *data; - u32 msg_seq; - /* multiple reads */ struct mt76_reg_pair *rp; int rp_len; @@ -421,14 +426,6 @@ struct mt76_usb { }; struct mt76_mmio { - struct mt76e_mcu { - struct mutex mutex; - - wait_queue_head_t wait; - struct sk_buff_head res_q; - - u32 msg_seq; - } mcu; void __iomem *regs; spinlock_t irq_lock; u32 irqmask; @@ -506,6 +503,8 @@ struct mt76_dev { const struct mt76_mcu_ops *mcu_ops; struct device *dev; + struct mt76_mcu mcu; + struct net_device napi_dev; spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c index bec58f567010..b466b3ab8a2c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -22,9 +22,9 @@ __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, struct mt7603_mcu_txd *txd; u8 seq; - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; if (!seq) - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen); memset(txd, 0, hdrlen); @@ -67,7 +67,7 @@ mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq); if (ret) @@ -97,7 +97,7 @@ mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -277,7 +277,7 @@ int mt7603_mcu_init(struct mt7603_dev *dev) void mt7603_mcu_exit(struct mt7603_dev *dev) { __mt76_mcu_restart(&dev->mt76); - skb_queue_purge(&dev->mt76.mmio.mcu.res_q); + skb_queue_purge(&dev->mt76.mcu.res_q); } int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 22ec28bf80b0..145366dbc39b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1878,7 +1878,7 @@ void mt7615_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &dev->mphy.state); set_bit(MT76_MCU_RESET, &dev->mphy.state); - wake_up(&dev->mt76.mmio.mcu.wait); + wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->mt76.mac_work); /* lock/unlock all queues to ensure that no tx is pending */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 68f35aa15c60..7218a3041ead 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -58,9 +58,9 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, u32 val; __le32 *txd; - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; mcu_txd = (struct mt7615_mcu_txd *)skb_push(skb, sizeof(struct mt7615_mcu_txd)); @@ -153,7 +153,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); if (ret) @@ -174,7 +174,7 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -719,7 +719,7 @@ void mt7615_mcu_exit(struct mt7615_dev *dev) { __mt76_mcu_restart(&dev->mt76); mt7615_firmware_own(dev); - skb_queue_purge(&dev->mt76.mmio.mcu.res_q); + skb_queue_purge(&dev->mt76.mcu.res_q); } int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 6274b6a24b07..5664749ad6c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -24,11 +24,11 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&mdev->mmio.mcu.mutex); + mutex_lock(&mdev->mcu.mutex); - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; if (!seq) - seq = ++mdev->mmio.mcu.msg_seq & 0xf; + seq = ++mdev->mcu.msg_seq & 0xf; tx_info = MT_MCU_MSG_TYPE_CMD | FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | @@ -65,7 +65,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, } out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } @@ -141,7 +141,7 @@ int mt76x02_mcu_cleanup(struct mt76x02_dev *dev) mt76_wr(dev, MT_MCU_INT_LEVEL, 1); usleep_range(20000, 30000); - while ((skb = skb_dequeue(&dev->mt76.mmio.mcu.res_q)) != NULL) + while ((skb = skb_dequeue(&dev->mt76.mcu.res_q)) != NULL) dev_kfree_skb(skb); return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 3d8bd61c5b43..c7f028e73b6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -544,9 +544,9 @@ static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) restart: mt76x02_watchdog_reset(dev); - mutex_lock(&dev->mt76.mmio.mcu.mutex); + mutex_lock(&dev->mt76.mcu.mutex); dev->mcu_timeout = 0; - mutex_unlock(&dev->mt76.mmio.mcu.mutex); + mutex_unlock(&dev->mt76.mcu.mutex); dev->tx_hang_reset++; dev->tx_hang_check = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 039f96877787..96fdf423a348 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -39,7 +39,6 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, void *rxwi = skb->data; if (q == MT_RXQ_MCU) { - /* this is used just by mmio code */ mt76_mcu_rx_event(&dev->mt76, skb); return; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index c58282baee46..843b86560ed4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -83,18 +83,17 @@ static int __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, bool wait_resp) { - struct mt76_usb *usb = &dev->usb; - int ret; u8 seq = 0; u32 info; + int ret; if (test_bit(MT76_REMOVED, &dev->phy.state)) return 0; if (wait_resp) { - seq = ++usb->mcu.msg_seq & 0xf; + seq = ++dev->mcu.msg_seq & 0xf; if (!seq) - seq = ++usb->mcu.msg_seq & 0xf; + seq = ++dev->mcu.msg_seq & 0xf; } info = FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | @@ -121,7 +120,6 @@ static int mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, int len, bool wait_resp) { - struct mt76_usb *usb = &dev->usb; struct sk_buff *skb; int err; @@ -129,9 +127,9 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, if (!skb) return -ENOMEM; - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); err = __mt76x02u_mcu_send_msg(dev, skb, cmd, wait_resp); - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); return err; } @@ -145,9 +143,8 @@ static int mt76x02u_mcu_wr_rp(struct mt76_dev *dev, u32 base, const struct mt76_reg_pair *data, int n) { - const int CMD_RANDOM_WRITE = 12; const int max_vals_per_cmd = MT_INBAND_PACKET_MAX_LEN / 8; - struct mt76_usb *usb = &dev->usb; + const int CMD_RANDOM_WRITE = 12; struct sk_buff *skb; int cnt, i, ret; @@ -166,9 +163,9 @@ mt76x02u_mcu_wr_rp(struct mt76_dev *dev, u32 base, skb_put_le32(skb, data[i].value); } - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); ret = __mt76x02u_mcu_send_msg(dev, skb, CMD_RANDOM_WRITE, cnt == n); - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); if (ret) return ret; @@ -202,7 +199,7 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, skb_put_le32(skb, data[i].value); } - mutex_lock(&usb->mcu.mutex); + mutex_lock(&dev->mcu.mutex); usb->mcu.rp = data; usb->mcu.rp_len = n; @@ -213,7 +210,7 @@ mt76x02u_mcu_rd_rp(struct mt76_dev *dev, u32 base, usb->mcu.rp = NULL; - mutex_unlock(&usb->mcu.mutex); + mutex_unlock(&dev->mcu.mutex); return ret; } diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 3aa1425049d9..36ba81d63f12 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -1167,14 +1167,13 @@ int mt76u_init(struct mt76_dev *dev, usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1); if (usb->data_len < 32) usb->data_len = 32; + usb->data = devm_kmalloc(dev->dev, usb->data_len, GFP_KERNEL); if (!usb->data) { mt76u_deinit(dev); return -ENOMEM; } - mutex_init(&usb->mcu.mutex); - mutex_init(&usb->usb_ctrl_mtx); dev->bus = &mt76u_ops; dev->queue_ops = &usb_queue_ops; From 932183aa35c62e9657585382de641716088a0023 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Wed, 12 Feb 2020 21:47:10 +0530 Subject: [PATCH 168/168] mwifiex: change license text from MARVELL to NXP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As of 6-DEC-2019, NXP has acquired Marvell’s Wireless business unit. This change is to update the license text accordingly. Signed-off-by: James Cao Signed-off-by: Cathy Luo Signed-off-by: Ganapathi Bhat Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/11ac.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11ac.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11h.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n_aggr.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n_aggr.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/cfg80211.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/cfp.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/cmdevt.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/debugfs.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/decl.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/ethtool.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/fw.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/ie.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/init.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/ioctl.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/join.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/main.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/main.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/pcie.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/pcie.h | 6 +++--- drivers/net/wireless/marvell/mwifiex/scan.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sdio.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sdio.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_event.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_rx.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/sta_tx.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/tdls.c | 9 +++++---- drivers/net/wireless/marvell/mwifiex/txrx.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/uap_cmd.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/uap_event.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/uap_txrx.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/usb.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/usb.h | 6 +++--- drivers/net/wireless/marvell/mwifiex/util.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/util.h | 8 ++++---- drivers/net/wireless/marvell/mwifiex/wmm.c | 8 ++++---- drivers/net/wireless/marvell/mwifiex/wmm.h | 8 ++++---- 45 files changed, 179 insertions(+), 178 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.c b/drivers/net/wireless/marvell/mwifiex/11ac.c index 59d23fb2365f..756f019ef28a 100644 --- a/drivers/net/wireless/marvell/mwifiex/11ac.c +++ b/drivers/net/wireless/marvell/mwifiex/11ac.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11ac + * NXP Wireless LAN device driver: 802.11ac * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11ac.h b/drivers/net/wireless/marvell/mwifiex/11ac.h index 1ca92c7a8a4a..29e83468cf3f 100644 --- a/drivers/net/wireless/marvell/mwifiex/11ac.h +++ b/drivers/net/wireless/marvell/mwifiex/11ac.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11ac + * NXP Wireless LAN device driver: 802.11ac * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c index 238accfe4f41..d2ee6469e67b 100644 --- a/drivers/net/wireless/marvell/mwifiex/11h.c +++ b/drivers/net/wireless/marvell/mwifiex/11h.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11h + * NXP Wireless LAN device driver: 802.11h * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c index e435f801bc91..6696bce56178 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.c +++ b/drivers/net/wireless/marvell/mwifiex/11n.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n + * NXP Wireless LAN device driver: 802.11n * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n.h b/drivers/net/wireless/marvell/mwifiex/11n.h index 33268ce2cd82..83a88eecbda6 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.h +++ b/drivers/net/wireless/marvell/mwifiex/11n.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n + * NXP Wireless LAN device driver: 802.11n * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c index 088612438530..46f41dbcf30d 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n Aggregation + * NXP Wireless LAN device driver: 802.11n Aggregation * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.h b/drivers/net/wireless/marvell/mwifiex/11n_aggr.h index 8279b159da7c..382c1265c441 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.h +++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n Aggregation + * NXP Wireless LAN device driver: 802.11n Aggregation * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 05a3c61ac603..0bdafe9f66db 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * NXP Wireless LAN device driver: 802.11n RX Re-ordering * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h index 22d991f514c8..465f244b3636 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering + * NXP Wireless LAN device driver: 802.11n RX Re-ordering * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index d89684168500..0a6da6fe2f89 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: CFG80211 + * NXP Wireless LAN device driver: CFG80211 * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.h b/drivers/net/wireless/marvell/mwifiex/cfg80211.h index 908367857d58..530a63f13f14 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.h +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: CFG80211 + * NXP Wireless LAN device driver: CFG80211 * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c index f1522fb1c1e8..fb91ecfc5546 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfp.c +++ b/drivers/net/wireless/marvell/mwifiex/cfp.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: Channel, Frequence and Power + * NXP Wireless LAN device driver: Channel, Frequence and Power * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index e8788c35a453..7e4b8cd52605 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: commands and events + * NXP Wireless LAN device driver: commands and events * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 8ab114cf3467..dded92db1f37 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: debugfs + * NXP Wireless LAN device driver: debugfs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index 46696ea0b23e..6bd23c9b1eed 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: generic data structures and APIs + * NXP Wireless LAN device driver: generic data structures and APIs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ethtool.c b/drivers/net/wireless/marvell/mwifiex/ethtool.c index 58400c69ab26..9bdad3f59039 100644 --- a/drivers/net/wireless/marvell/mwifiex/ethtool.c +++ b/drivers/net/wireless/marvell/mwifiex/ethtool.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: ethtool + * NXP Wireless LAN device driver: ethtool * - * Copyright (C) 2013-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 1fb76d2f5d3f..4dfdf928f705 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: Firmware specific macros & structures + * NXP Wireless LAN device driver: Firmware specific macros & structures * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c index 580387f9f12a..811abe963af2 100644 --- a/drivers/net/wireless/marvell/mwifiex/ie.c +++ b/drivers/net/wireless/marvell/mwifiex/ie.c @@ -1,11 +1,11 @@ /* - * Marvell Wireless LAN device driver: management IE handling- setting and + * NXP Wireless LAN device driver: management IE handling- setting and * deleting IE. * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 1aa93e7e9835..82d69bc3aaaf 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: HW/FW Initialization + * NXP Wireless LAN device driver: HW/FW Initialization * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 0dd592ea6e83..3db449efa167 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: ioctl data structures & APIs + * NXP Wireless LAN device driver: ioctl data structures & APIs * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index d87aeff70cef..5934f7147547 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: association and ad-hoc start/join + * NXP Wireless LAN device driver: association and ad-hoc start/join * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 7d94695e7961..529099137644 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: major functions + * NXP Wireless LAN device driver: major functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index fa5634af40f7..afaffc325452 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: major data structures and prototypes + * NXP Wireless LAN device driver: major data structures and prototypes * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index fc1706d0647d..87b4ccca4b9a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: PCIE specific handling + * NXP Wireless LAN device driver: PCIE specific handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index f7ce9b6db6b4..fc59b522f670 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -3,10 +3,10 @@ * @brief This file contains definitions for PCI-E interface. * driver. * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index a7968a84aaf8..ff932627a46c 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: scan ioctl and command handling + * NXP Wireless LAN device driver: scan ioctl and command handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index fec38b6e86ff..6a2dcb01caf4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: SDIO specific handling + * NXP Wireless LAN device driver: SDIO specific handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index f672bdf52cc1..71cd8629b28e 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: SDIO specific definitions + * NXP Wireless LAN device driver: SDIO specific definitions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 4ed10cf82f9a..0bd93f26bd7f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station command handling + * NXP Wireless LAN device driver: station command handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 20c206da0631..f21660149f58 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station command response handling + * NXP Wireless LAN device driver: station command response handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 5fdffb114913..bc79ca4cb803 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station event handling + * NXP Wireless LAN device driver: station event handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index fbfa0b15d0c8..653f9e094256 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: functions for station ioctl + * NXP Wireless LAN device driver: functions for station ioctl * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index 52a2ce2e78b0..0d2adf887900 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station RX data handling + * NXP Wireless LAN device driver: station RX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/sta_tx.c b/drivers/net/wireless/marvell/mwifiex/sta_tx.c index 37c24b95e642..241305377e20 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_tx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_tx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: station TX data handling + * NXP Wireless LAN device driver: station TX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index f8f282ce39bd..97bb87c3676b 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -1,9 +1,10 @@ -/* Marvell Wireless LAN device driver: TDLS handling +/* + * NXP Wireless LAN device driver: TDLS handling * - * Copyright (C) 2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available on the worldwide web at diff --git a/drivers/net/wireless/marvell/mwifiex/txrx.c b/drivers/net/wireless/marvell/mwifiex/txrx.c index e3c1446dd847..a8479b879382 100644 --- a/drivers/net/wireless/marvell/mwifiex/txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/txrx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: generic TX/RX data handling + * NXP Wireless LAN device driver: generic TX/RX data handling * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c index 0939a8c8f3ab..b48a85d791f6 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP specific command handling + * NXP Wireless LAN device driver: AP specific command handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index 86bfa1b9ef9d..9121447e2701 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP event handling + * NXP Wireless LAN device driver: AP event handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index 354b09c5e8dc..77c8595f84f8 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: AP TX and RX data handling + * NXP Wireless LAN device driver: AP TX and RX data handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c index c2365eeb7016..6f3cfde4654c 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.c +++ b/drivers/net/wireless/marvell/mwifiex/usb.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: USB specific handling + * NXP Wireless LAN device driver: USB specific handling * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/usb.h b/drivers/net/wireless/marvell/mwifiex/usb.h index 37abd228a84f..d822ec15b7e6 100644 --- a/drivers/net/wireless/marvell/mwifiex/usb.h +++ b/drivers/net/wireless/marvell/mwifiex/usb.h @@ -1,10 +1,10 @@ /* * This file contains definitions for mwifiex USB interface driver. * - * Copyright (C) 2012-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 3b0d31827681..de89a1e710b1 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: utility functions + * NXP Wireless LAN device driver: utility functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/util.h b/drivers/net/wireless/marvell/mwifiex/util.h index 7cafcecd7b85..44aa80eb7827 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.h +++ b/drivers/net/wireless/marvell/mwifiex/util.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: utility functions + * NXP Wireless LAN device driver: utility functions * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 132f9e8ed68c..a06fff199ea3 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: WMM + * NXP Wireless LAN device driver: WMM * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.h b/drivers/net/wireless/marvell/mwifiex/wmm.h index 38f09762bd2f..04d7da95e307 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.h +++ b/drivers/net/wireless/marvell/mwifiex/wmm.h @@ -1,10 +1,10 @@ /* - * Marvell Wireless LAN device driver: WMM + * NXP Wireless LAN device driver: WMM * - * Copyright (C) 2011-2014, Marvell International Ltd. + * Copyright 2011-2020 NXP * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * This software file (the "File") is distributed by NXP + * under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc.,