diff options
261 files changed, 6916 insertions, 28251 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml index e564f20d8f41..a3607d55ef36 100644 --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml @@ -53,6 +53,7 @@ properties: - pci14e4,4488 # BCM4377 - pci14e4,4425 # BCM4378 - pci14e4,4433 # BCM4387 + - pci14e4,449d # BCM43752 reg: description: SDIO function number for the device (for most cases @@ -121,6 +122,14 @@ properties: NVRAM. This would normally be filled in by the bootloader from platform configuration data. + clocks: + items: + - description: External Low Power Clock input (32.768KHz) + + clock-names: + items: + - const: lpo + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml index 2460ccc08237..5d40f22765bb 100644 --- a/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml +++ b/Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml @@ -16,7 +16,11 @@ description: properties: compatible: - const: microchip,wilc1000 + oneOf: + - items: + - const: microchip,wilc3000 + - const: microchip,wilc1000 + - const: microchip,wilc1000 reg: true diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst index db6192b2bb50..ade50d4e67cf 100644 --- a/Documentation/networking/net_cachelines/net_device.rst +++ b/Documentation/networking/net_cachelines/net_device.rst @@ -52,7 +52,6 @@ struct net_device_core_stats* core_stats atomic_t carrier_up_count atomic_t carrier_down_count struct iw_handler_def* wireless_handlers -struct iw_public_data* wireless_data struct ethtool_ops* ethtool_ops struct l3mdev_ops* l3mdev_ops struct ndisc_ops* ndisc_ops diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index 44488c153ea2..4fbe4b7cd12a 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -2566,7 +2566,6 @@ static void gelic_wl_setup_netdev_ops(struct net_device *netdev) netdev->ethtool_ops = &gelic_wl_ethtool_ops; netdev->netdev_ops = &gelic_wl_netdevice_ops; - netdev->wireless_data = &wl->wireless_data; netdev->wireless_handlers = &gelic_wl_wext_handler_def; } diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h index 1f203d1ae8db..dbabf538e10a 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h @@ -276,7 +276,6 @@ struct gelic_wl_info { u8 active_bssid[ETH_ALEN]; /* associated bssid */ unsigned int essid_len; - struct iw_public_data wireless_data; struct iw_statistics iwstat; }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 646e1737d4c4..41ab83c3d3f7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -8507,9 +8507,10 @@ exit: static void ath10k_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct ath10k *ar = hw->priv; struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; @@ -9450,7 +9451,7 @@ static const struct ieee80211_ops ath10k_ops = { .reconfig_complete = ath10k_reconfig_complete, .get_survey = ath10k_get_survey, .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask, - .sta_rc_update = ath10k_sta_rc_update, + .link_sta_rc_update = ath10k_sta_rc_update, .offset_tsf = ath10k_offset_tsf, .ampdu_action = ath10k_ampdu_action, .get_et_sset_count = ath10k_debug_get_et_sset_count, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index f8068d2e848c..e6acbff06749 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5079,9 +5079,10 @@ static void ath11k_mac_op_sta_set_4addr(struct ieee80211_hw *hw, static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct ath11k *ar = hw->priv; struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta); struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); @@ -9708,7 +9709,7 @@ static const struct ieee80211_ops ath11k_ops = { .sta_state = ath11k_mac_op_sta_state, .sta_set_4addr = ath11k_mac_op_sta_set_4addr, .sta_set_txpwr = ath11k_mac_op_sta_set_txpwr, - .sta_rc_update = ath11k_mac_op_sta_rc_update, + .link_sta_rc_update = ath11k_mac_op_sta_rc_update, .conf_tx = ath11k_mac_op_conf_tx, .set_antenna = ath11k_mac_op_set_antenna, .get_antenna = ath11k_mac_op_get_antenna, diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 137394c36460..acf5628adda5 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4737,9 +4737,10 @@ out: static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct ath12k *ar; struct ath12k_sta *arsta = ath12k_sta_to_arsta(sta); struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif); @@ -8681,7 +8682,7 @@ static const struct ieee80211_ops ath12k_ops = { .set_rekey_data = ath12k_mac_op_set_rekey_data, .sta_state = ath12k_mac_op_sta_state, .sta_set_txpwr = ath12k_mac_op_sta_set_txpwr, - .sta_rc_update = ath12k_mac_op_sta_rc_update, + .link_sta_rc_update = ath12k_mac_op_sta_rc_update, .conf_tx = ath12k_mac_op_conf_tx, .set_antenna = ath12k_mac_op_set_antenna, .get_antenna = ath12k_mac_op_get_antenna, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 8a03bcc2789e..57094bd45d98 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1357,8 +1357,10 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u32 changed) + struct ieee80211_link_sta *link_sta, + u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) @@ -1883,7 +1885,7 @@ struct ieee80211_ops ath9k_htc_ops = { .sta_add = ath9k_htc_sta_add, .sta_remove = ath9k_htc_sta_remove, .conf_tx = ath9k_htc_conf_tx, - .sta_rc_update = ath9k_htc_sta_rc_update, + .link_sta_rc_update = ath9k_htc_sta_rc_update, .bss_info_changed = ath9k_htc_bss_info_changed, .set_key = ath9k_htc_set_key, .get_tsf = ath9k_htc_get_tsf, diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index e8f1d30a8d73..a1a0a9223e74 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1493,6 +1493,7 @@ out: } static int wil_cfg80211_set_channel(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_chan_def *chandef) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index d35262335eaf..17f6b33beabd 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -947,8 +947,8 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) /* try to attach to the target device */ sdiodev->bus = brcmf_sdio_probe(sdiodev); - if (!sdiodev->bus) { - ret = -ENODEV; + if (IS_ERR(sdiodev->bus)) { + ret = PTR_ERR(sdiodev->bus); goto out; } brcmf_sdiod_host_fixup(sdiodev->func2->card->host); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 349aa3439502..297a7c738c01 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -7820,13 +7820,6 @@ s32 brcmf_cfg80211_down(struct net_device *ndev) return err; } -enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp) -{ - struct wireless_dev *wdev = &ifp->vif->wdev; - - return wdev->iftype; -} - bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index dc3a6a537507..2abae8894614 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -443,7 +443,6 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings); -enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp); struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, enum nl80211_iftype type); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index b24faae35873..58d50918dd17 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -561,7 +561,8 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, if (!found) { /* No platform data for this device, try OF and DMI data */ brcmf_dmi_probe(settings, chip, chiprev); - brcmf_of_probe(dev, bus_type, settings); + if (brcmf_of_probe(dev, bus_type, settings) == -EPROBE_DEFER) + return ERR_PTR(-EPROBE_DEFER); brcmf_acpi_probe(dev, bus_type, settings); } return settings; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index fe4f65756105..ae98e371dbfd 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -6,6 +6,7 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_net.h> +#include <linux/clk.h> #include <defs.h> #include "debug.h" @@ -65,12 +66,13 @@ static int brcmf_of_get_country_codes(struct device *dev, return 0; } -void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings) +int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) { struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; struct device_node *root, *np = dev->of_node; struct of_phandle_args oirq; + struct clk *clk; const char *prop; int irq; int err; @@ -106,7 +108,7 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, board_type = devm_kstrdup(dev, tmp, GFP_KERNEL); if (!board_type) { of_node_put(root); - return; + return 0; } strreplace(board_type, '/', '-'); settings->board_type = board_type; @@ -114,8 +116,14 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, of_node_put(root); } + clk = devm_clk_get_optional_enabled_with_rate(dev, "lpo", 32768); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + brcmf_dbg(INFO, "%s LPO clock\n", clk ? "enable" : "no"); + if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac")) - return; + return 0; err = brcmf_of_get_country_codes(dev, settings); if (err) @@ -124,23 +132,25 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, of_get_mac_address(np, settings->mac); if (bus_type != BRCMF_BUSTYPE_SDIO) - return; + return 0; if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) sdio->drive_strength = val; /* make sure there are interrupts defined in the node */ if (of_irq_parse_one(np, 0, &oirq)) - return; + return 0; irq = irq_create_of_mapping(&oirq); if (!irq) { brcmf_err("interrupt could not be mapped\n"); - return; + return 0; } - irqf = irqd_get_trigger_type(irq_get_irq_data(irq)); + irqf = irq_get_trigger_type(irq); sdio->oob_irq_supported = true; sdio->oob_irq_nr = irq; sdio->oob_irq_flags = irqf; + + return 0; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h index 10bf52253337..ae124c73fc3b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h @@ -3,11 +3,12 @@ * Copyright (c) 2014 Broadcom Corporation */ #ifdef CONFIG_OF -void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings); +int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings); #else -static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, - struct brcmf_mp_device *settings) +static int brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, + struct brcmf_mp_device *settings) { + return 0; } #endif /* CONFIG_OF */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 5dee54819fbd..e4395b1f8c11 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -66,6 +66,7 @@ BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); +BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie"); BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie"); BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie"); @@ -104,6 +105,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C), BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C), BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), + BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752), BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */ @@ -353,6 +355,7 @@ struct brcmf_pciedev_info { u16 value); struct brcmf_mp_device *settings; struct brcmf_otp_params otp; + bool fwseed; #ifdef DEBUG u32 console_interval; bool console_active; @@ -1715,14 +1718,14 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, memcpy_toio(devinfo->tcm + address, nvram, nvram_len); brcmf_fw_nvram_free(nvram); - if (devinfo->otp.valid) { + if (devinfo->fwseed) { size_t rand_len = BRCMF_RANDOM_SEED_LENGTH; struct brcmf_random_seed_footer footer = { .length = cpu_to_le32(rand_len), .magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC), }; - /* Some Apple chips/firmwares expect a buffer of random + /* Some chips/firmwares expect a buffer of random * data to be present before NVRAM */ brcmf_dbg(PCIE, "Download random seed\n"); @@ -2394,6 +2397,37 @@ static void brcmf_pcie_debugfs_create(struct device *dev) } #endif +struct brcmf_pcie_drvdata { + enum brcmf_fwvendor vendor; + bool fw_seed; +}; + +enum { + BRCMF_DRVDATA_CYW, + BRCMF_DRVDATA_BCA, + BRCMF_DRVDATA_WCC, + BRCMF_DRVDATA_WCC_SEED, +}; + +static const struct brcmf_pcie_drvdata drvdata[] = { + [BRCMF_DRVDATA_CYW] = { + .vendor = BRCMF_FWVENDOR_CYW, + .fw_seed = false, + }, + [BRCMF_DRVDATA_BCA] = { + .vendor = BRCMF_FWVENDOR_BCA, + .fw_seed = false, + }, + [BRCMF_DRVDATA_WCC] = { + .vendor = BRCMF_FWVENDOR_WCC, + .fw_seed = false, + }, + [BRCMF_DRVDATA_WCC_SEED] = { + .vendor = BRCMF_FWVENDOR_WCC, + .fw_seed = true, + }, +}; + /* Forward declaration for pci_match_id() call */ static const struct pci_device_id brcmf_pcie_devid_table[]; @@ -2452,6 +2486,9 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = -ENOMEM; goto fail; } + ret = PTR_ERR_OR_ZERO(devinfo->settings); + if (ret < 0) + goto fail; bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) { @@ -2472,9 +2509,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) bus->bus_priv.pcie = pcie_bus_dev; bus->ops = &brcmf_pcie_bus_ops; bus->proto_type = BRCMF_PROTO_MSGBUF; - bus->fwvid = id->driver_data; bus->chip = devinfo->coreid; bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot); + bus->fwvid = drvdata[id->driver_data].vendor; + devinfo->fwseed = drvdata[id->driver_data].fw_seed; dev_set_drvdata(&pdev->dev, bus); ret = brcmf_alloc(&devinfo->pdev->dev, devinfo->settings); @@ -2660,14 +2698,14 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = { BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \ PCI_ANY_ID, PCI_ANY_ID, \ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \ - BRCMF_FWVENDOR_ ## fw_vend \ + BRCMF_DRVDATA_ ## fw_vend \ } #define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev, fw_vend) \ { \ BRCM_PCIE_VENDOR_ID_BROADCOM, (dev_id), \ (subvend), (subdev), \ PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, \ - BRCMF_FWVENDOR_ ## fw_vend \ + BRCMF_DRVDATA_ ## fw_vend \ } static const struct pci_device_id brcmf_pcie_devid_table[] = { @@ -2695,9 +2733,10 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA), BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC), BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW), - BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC), - BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC), - BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC_SEED), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC_SEED), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC_SEED), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC_SEED), { /* end: all zeroes */ } }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 7b936668c1b6..b1727f35217b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3943,7 +3943,7 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { .write32 = brcmf_sdio_buscore_write32, }; -static bool +static int brcmf_sdio_probe_attach(struct brcmf_sdio *bus) { struct brcmf_sdio_dev *sdiodev; @@ -3953,6 +3953,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) u32 reg_val; u32 drivestrength; u32 enum_base; + int ret = -EBADE; sdiodev = bus->sdiodev; sdio_claim_host(sdiodev->func1); @@ -4001,8 +4002,9 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) BRCMF_BUSTYPE_SDIO, bus->ci->chip, bus->ci->chiprev); - if (!sdiodev->settings) { + if (IS_ERR_OR_NULL(sdiodev->settings)) { brcmf_err("Failed to get device parameters\n"); + ret = PTR_ERR_OR_ZERO(sdiodev->settings); goto fail; } /* platform specific configuration: @@ -4071,7 +4073,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) /* allocate header buffer */ bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL); if (!bus->hdrbuf) - return false; + return -ENOMEM; /* Locate an appropriately-aligned portion of hdrbuf */ bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], bus->head_align); @@ -4082,11 +4084,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) if (bus->poll) bus->pollrate = 1; - return true; + return 0; fail: sdio_release_host(sdiodev->func1); - return false; + return ret; } static int @@ -4451,8 +4453,10 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) /* Allocate private bus interface state */ bus = kzalloc(sizeof(*bus), GFP_ATOMIC); - if (!bus) + if (!bus) { + ret = -ENOMEM; goto fail; + } bus->sdiodev = sdiodev; sdiodev->bus = bus; @@ -4467,6 +4471,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) dev_name(&sdiodev->func1->dev)); if (!wq) { brcmf_err("insufficient memory to create txworkqueue\n"); + ret = -ENOMEM; goto fail; } brcmf_sdiod_freezer_count(sdiodev); @@ -4474,7 +4479,8 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) bus->brcmf_wq = wq; /* attempt to attach to the dongle */ - if (!(brcmf_sdio_probe_attach(bus))) { + ret = brcmf_sdio_probe_attach(bus); + if (ret < 0) { brcmf_err("brcmf_sdio_probe_attach failed\n"); goto fail; } @@ -4546,7 +4552,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) fail: brcmf_sdio_remove(bus); - return NULL; + return ERR_PTR(ret); } /* Detach and free everything */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 8afbf529c745..2821c27f317e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -1272,6 +1272,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, ret = -ENOMEM; goto fail; } + ret = PTR_ERR_OR_ZERO(devinfo->settings); + if (ret < 0) + goto fail; if (!brcmf_usb_dlneeded(devinfo)) { ret = brcmf_alloc(devinfo->dev, devinfo->settings); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c index 6d776ef6ff54..81df41c7fbb5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c @@ -56,11 +56,6 @@ void brcms_debugfs_detach(struct brcms_pub *drvr) debugfs_remove_recursive(drvr->dbgfs_dir); } -struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr) -{ - return drvr->dbgfs_dir; -} - static int brcms_debugfs_hardware_read(struct seq_file *s, void *data) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h index 56898e6d789d..d30a9fa30f1b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h @@ -70,7 +70,6 @@ void brcms_debugfs_init(void); void brcms_debugfs_exit(void); void brcms_debugfs_attach(struct brcms_pub *drvr); void brcms_debugfs_detach(struct brcms_pub *drvr); -struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr); void brcms_debugfs_create_files(struct brcms_pub *drvr); #endif /* _BRCMS_DEBUG_H_ */ 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 44684bf1b9ac..c1e22c589d85 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h @@ -52,6 +52,7 @@ #define BRCM_CC_43664_CHIP_ID 43664 #define BRCM_CC_43666_CHIP_ID 43666 #define BRCM_CC_4371_CHIP_ID 0x4371 +#define BRCM_CC_43752_CHIP_ID 43752 #define BRCM_CC_4377_CHIP_ID 0x4377 #define BRCM_CC_4378_CHIP_ID 0x4378 #define BRCM_CC_4387_CHIP_ID 0x4387 @@ -94,6 +95,7 @@ #define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 #define BRCM_PCIE_4371_DEVICE_ID 0x440d #define BRCM_PCIE_43596_DEVICE_ID 0x4415 +#define BRCM_PCIE_43752_DEVICE_ID 0x449d #define BRCM_PCIE_4377_DEVICE_ID 0x4488 #define BRCM_PCIE_4378_DEVICE_ID 0x4425 #define BRCM_PCIE_4387_DEVICE_ID 0x4433 diff --git a/drivers/net/wireless/intel/ipw2x00/Kconfig b/drivers/net/wireless/intel/ipw2x00/Kconfig index 1650d5865aa0..b92df91adb3a 100644 --- a/drivers/net/wireless/intel/ipw2x00/Kconfig +++ b/drivers/net/wireless/intel/ipw2x00/Kconfig @@ -7,10 +7,8 @@ config IPW2100 tristate "Intel PRO/Wireless 2100 Network Connection" depends on PCI && CFG80211 select WIRELESS_EXT - select WEXT_SPY select WEXT_PRIV select FW_LOADER - select LIB80211 select LIBIPW help A driver for the Intel PRO/Wireless 2100 Network @@ -67,12 +65,9 @@ config IPW2100_DEBUG config IPW2200 tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" depends on PCI && CFG80211 - select CFG80211_WEXT_EXPORT select WIRELESS_EXT - select WEXT_SPY select WEXT_PRIV select FW_LOADER - select LIB80211 select LIBIPW help A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network @@ -158,14 +153,10 @@ config LIBIPW tristate depends on PCI && CFG80211 select WIRELESS_EXT - select WEXT_SPY select CRYPTO select CRYPTO_MICHAEL_MIC + select CRYPTO_LIB_ARC4 select CRC32 - select LIB80211 - select LIB80211_CRYPT_WEP - select LIB80211_CRYPT_TKIP - select LIB80211_CRYPT_CCMP help This option enables the hardware independent IEEE 802.11 networking stack. This component is deprecated in favor of the diff --git a/drivers/net/wireless/intel/ipw2x00/Makefile b/drivers/net/wireless/intel/ipw2x00/Makefile index e1ec50359dff..91e6091c4ebf 100644 --- a/drivers/net/wireless/intel/ipw2x00/Makefile +++ b/drivers/net/wireless/intel/ipw2x00/Makefile @@ -12,4 +12,9 @@ libipw-objs := \ libipw_tx.o \ libipw_rx.o \ libipw_wx.o \ - libipw_geo.o + libipw_geo.o \ + libipw_spy.o \ + libipw_crypto.o \ + libipw_crypto_ccmp.o \ + libipw_crypto_tkip.o \ + libipw_crypto_wep.o diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index b6636002c7d2..15bf35f2de2a 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -148,9 +148,6 @@ that only one external action is invoked at a time. #include <linux/acpi.h> #include <linux/ctype.h> #include <linux/pm_qos.h> - -#include <net/lib80211.h> - #include "ipw2100.h" #include "ipw.h" @@ -6025,8 +6022,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, dev->netdev_ops = &ipw2100_netdev_ops; dev->ethtool_ops = &ipw2100_ethtool_ops; dev->wireless_handlers = &ipw2100_wx_handler_def; - priv->wireless_data.libipw = priv->ieee; - dev->wireless_data = &priv->wireless_data; dev->watchdog_timeo = 3 * HZ; dev->irq = 0; dev->min_mtu = 68; @@ -7571,7 +7566,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev, struct ipw2100_priv *priv = libipw_priv(dev); struct libipw_device *ieee = priv->ieee; struct iw_param *param = &wrqu->param; - struct lib80211_crypt_data *crypt; + struct libipw_crypt_data *crypt; unsigned long flags; int ret = 0; @@ -7663,7 +7658,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev, { struct ipw2100_priv *priv = libipw_priv(dev); struct libipw_device *ieee = priv->ieee; - struct lib80211_crypt_data *crypt; + struct libipw_crypt_data *crypt; struct iw_param *param = &wrqu->param; switch (param->flags & IW_AUTH_INDEX) { diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.h b/drivers/net/wireless/intel/ipw2x00/ipw2100.h index b34085ade3aa..6f81f509b9cb 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.h @@ -554,8 +554,6 @@ struct ipw2100_priv { struct net_device *net_dev; struct iw_statistics wstats; - struct iw_public_data wireless_data; - struct tasklet_struct irq_tasklet; struct delayed_work reset_work; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c index eed9ef17bc29..be1d971b3d32 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c @@ -6463,6 +6463,14 @@ static int ipw_set_rsn_capa(struct ipw_priv *priv, * WE-18 support */ +static int ipw_wx_get_name(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + strcpy(wrqu->name, "IEEE 802.11"); + return 0; +} + /* SIOCSIWGENIE */ static int ipw_wx_set_genie(struct net_device *dev, struct iw_request_info *info, @@ -6549,7 +6557,7 @@ static int ipw_wx_set_auth(struct net_device *dev, struct ipw_priv *priv = libipw_priv(dev); struct libipw_device *ieee = priv->ieee; struct iw_param *param = &wrqu->param; - struct lib80211_crypt_data *crypt; + struct libipw_crypt_data *crypt; unsigned long flags; int ret = 0; @@ -6648,7 +6656,7 @@ static int ipw_wx_get_auth(struct net_device *dev, { struct ipw_priv *priv = libipw_priv(dev); struct libipw_device *ieee = priv->ieee; - struct lib80211_crypt_data *crypt; + struct libipw_crypt_data *crypt; struct iw_param *param = &wrqu->param; switch (param->flags & IW_AUTH_INDEX) { @@ -9826,7 +9834,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, /* Rebase the WE IOCTLs to zero for the handler array */ static iw_handler ipw_wx_handlers[] = { - IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), + IW_HANDLER(SIOCGIWNAME, ipw_wx_get_name), IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq), IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq), IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode), @@ -9856,10 +9864,10 @@ static iw_handler ipw_wx_handlers[] = { IW_HANDLER(SIOCGIWENCODE, ipw_wx_get_encode), IW_HANDLER(SIOCSIWPOWER, ipw_wx_set_power), IW_HANDLER(SIOCGIWPOWER, ipw_wx_get_power), - IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), - IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), - IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), - IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), + IW_HANDLER(SIOCSIWSPY, ipw_wx_set_spy), + IW_HANDLER(SIOCGIWSPY, ipw_wx_get_spy), + IW_HANDLER(SIOCSIWTHRSPY, ipw_wx_set_thrspy), + IW_HANDLER(SIOCGIWTHRSPY, ipw_wx_get_thrspy), IW_HANDLER(SIOCSIWGENIE, ipw_wx_set_genie), IW_HANDLER(SIOCGIWGENIE, ipw_wx_get_genie), IW_HANDLER(SIOCSIWMLME, ipw_wx_set_mlme), @@ -11636,8 +11644,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, priv->ieee->worst_rssi = -85; net_dev->netdev_ops = &ipw_netdev_ops; - priv->wireless_data.spy_data = &priv->ieee->spy_data; - net_dev->wireless_data = &priv->wireless_data; + priv->ieee->spy_enabled = true; net_dev->wireless_handlers = &ipw_wx_handler_def; net_dev->ethtool_ops = &ipw_ethtool_ops; diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h index 8ebf09121e17..d3db54e6d37c 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h @@ -31,8 +31,6 @@ #include <linux/wireless.h> #include <linux/jiffies.h> #include <asm/io.h> - -#include <net/lib80211.h> #include <net/ieee80211_radiotap.h> #define DRV_NAME "ipw2200" @@ -1276,8 +1274,6 @@ struct ipw_priv { struct iw_statistics wstats; - struct iw_public_data wireless_data; - int user_requested_scan; u8 direct_scan_ssid[IW_ESSID_MAX_SIZE]; u8 direct_scan_ssid_len; diff --git a/drivers/net/wireless/intel/ipw2x00/libipw.h b/drivers/net/wireless/intel/ipw2x00/libipw.h index bad080d33c07..3c20353e5a41 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw.h +++ b/drivers/net/wireless/intel/ipw2x00/libipw.h @@ -25,8 +25,6 @@ #include <linux/kernel.h> /* ARRAY_SIZE */ #include <linux/wireless.h> #include <linux/ieee80211.h> - -#include <net/lib80211.h> #include <net/cfg80211.h> #define LIBIPW_VERSION "git-1.1.13" @@ -699,6 +697,76 @@ struct libipw_geo { struct libipw_channel a[LIBIPW_52GHZ_CHANNELS]; }; +#define NUM_WEP_KEYS 4 + +enum { + IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0), +}; + +struct module; + +struct libipw_crypto_ops { + const char *name; + struct list_head list; + + /* init new crypto context (e.g., allocate private data space, + * select IV, etc.); returns NULL on failure or pointer to allocated + * private data on success */ + void *(*init) (int keyidx); + + /* deinitialize crypto context and free allocated private data */ + void (*deinit) (void *priv); + + /* encrypt/decrypt return < 0 on error or >= 0 on success. The return + * value from decrypt_mpdu is passed as the keyidx value for + * decrypt_msdu. skb must have enough head and tail room for the + * encryption; if not, error will be returned; these functions are + * called for all MPDUs (i.e., fragments). + */ + int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv); + int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv); + + /* These functions are called for full MSDUs, i.e. full frames. + * These can be NULL if full MSDU operations are not needed. */ + int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv); + int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len, + void *priv); + + int (*set_key) (void *key, int len, u8 * seq, void *priv); + int (*get_key) (void *key, int len, u8 * seq, void *priv); + + /* procfs handler for printing out key information and possible + * statistics */ + void (*print_stats) (struct seq_file *m, void *priv); + + /* Crypto specific flag get/set for configuration settings */ + unsigned long (*get_flags) (void *priv); + unsigned long (*set_flags) (unsigned long flags, void *priv); + + /* maximum number of bytes added by encryption; encrypt buf is + * allocated with extra_prefix_len bytes, copy of in_buf, and + * extra_postfix_len; encrypt need not use all this space, but + * the result must start at the beginning of the buffer and correct + * length must be returned */ + int extra_mpdu_prefix_len, extra_mpdu_postfix_len; + int extra_msdu_prefix_len, extra_msdu_postfix_len; + + struct module *owner; +}; + +struct libipw_crypt_info { + char *name; + /* Most clients will already have a lock, + so just point to that. */ + spinlock_t *lock; + + struct libipw_crypt_data *crypt[NUM_WEP_KEYS]; + int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ + struct list_head crypt_deinit_list; + struct timer_list crypt_deinit_timer; + int crypt_quiesced; +}; + struct libipw_device { struct net_device *dev; struct wireless_dev wdev; @@ -720,6 +788,7 @@ struct libipw_device { int iw_mode; /* operating mode (IW_MODE_*) */ struct iw_spy_data spy_data; /* iwspy support */ + bool spy_enabled; spinlock_t lock; @@ -751,7 +820,7 @@ struct libipw_device { size_t wpa_ie_len; u8 *wpa_ie; - struct lib80211_crypt_info crypt_info; + struct libipw_crypt_info crypt_info; int bcrx_sta_key; /* use individual keys to override default keys even * with RX of broad/multicast frames */ @@ -988,4 +1057,43 @@ static inline int libipw_get_scans(struct libipw_device *ieee) return ieee->scans; } +struct libipw_crypt_data { + struct list_head list; /* delayed deletion list */ + const struct libipw_crypto_ops *ops; + void *priv; + atomic_t refcnt; +}; + +int libipw_crypt_info_init(struct libipw_crypt_info *info, char *name, + spinlock_t *lock); +void libipw_crypt_info_free(struct libipw_crypt_info *info); +int libipw_register_crypto_ops(const struct libipw_crypto_ops *ops); +int libipw_unregister_crypto_ops(const struct libipw_crypto_ops *ops); +const struct libipw_crypto_ops *libipw_get_crypto_ops(const char *name); +void libipw_crypt_delayed_deinit(struct libipw_crypt_info *info, + struct libipw_crypt_data **crypt); + +/* must be called in the listed order */ +int libipw_crypto_init(void); +int libipw_crypto_ccmp_init(void); +int libipw_crypto_tkip_init(void); +int libipw_crypto_wep_init(void); + +void libipw_crypto_wep_exit(void); +void libipw_crypto_tkip_exit(void); +void libipw_crypto_ccmp_exit(void); +void libipw_crypto_exit(void); + + +int ipw_wx_set_spy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int ipw_wx_get_spy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int ipw_wx_set_thrspy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int ipw_wx_get_thrspy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +void libipw_spy_update(struct net_device *dev, unsigned char *address, + struct iw_quality *wstats); + #endif /* LIBIPW_H */ diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c new file mode 100644 index 000000000000..32639e0e8430 --- /dev/null +++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * libipw -- common bits for IPW drivers + * + * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> + * + * Portions copied from old ieee80211 component, w/ original copyright + * notices below: + * + * Host AP crypto routines + * + * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> + * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com> + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/ctype.h> +#include <linux/ieee80211.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/string.h> +#include "libipw.h" + +struct libipw_crypto_alg { + struct list_head list; + const struct libipw_crypto_ops *ops; +}; + +static LIST_HEAD(libipw_crypto_algs); +static DEFINE_SPINLOCK(libipw_crypto_lock); + +static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info, + int force); +static void libipw_crypt_quiescing(struct libipw_crypt_info *info); +static void libipw_crypt_deinit_handler(struct timer_list *t); + +int libipw_crypt_info_init(struct libipw_crypt_info *info, char *name, + spinlock_t *lock) +{ + memset(info, 0, sizeof(*info)); + + info->name = name; + info->lock = lock; + + INIT_LIST_HEAD(&info->crypt_deinit_list); + timer_setup(&info->crypt_deinit_timer, libipw_crypt_deinit_handler, + 0); + + return 0; +} +EXPORT_SYMBOL(libipw_crypt_info_init); + +void libipw_crypt_info_free(struct libipw_crypt_info *info) +{ + int i; + + libipw_crypt_quiescing(info); + del_timer_sync(&info->crypt_deinit_timer); + libipw_crypt_deinit_entries(info, 1); + + for (i = 0; i < NUM_WEP_KEYS; i++) { + struct libipw_crypt_data *crypt = info->crypt[i]; + if (crypt) { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); + module_put(crypt->ops->owner); + } + kfree(crypt); + info->crypt[i] = NULL; + } + } +} +EXPORT_SYMBOL(libipw_crypt_info_free); + +static void libipw_crypt_deinit_entries(struct libipw_crypt_info *info, + int force) +{ + struct libipw_crypt_data *entry, *next; + unsigned long flags; + + spin_lock_irqsave(info->lock, flags); + list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) { + if (atomic_read(&entry->refcnt) != 0 && !force) + continue; + + list_del(&entry->list); + + if (entry->ops) { + entry->ops->deinit(entry->priv); + module_put(entry->ops->owner); + } + kfree(entry); + } + spin_unlock_irqrestore(info->lock, flags); +} + +/* After this, crypt_deinit_list won't accept new members */ +static void libipw_crypt_quiescing(struct libipw_crypt_info *info) +{ + unsigned long flags; + + spin_lock_irqsave(info->lock, flags); + info->crypt_quiesced = 1; + spin_unlock_irqrestore(info->lock, flags); +} + +static void libipw_crypt_deinit_handler(struct timer_list *t) +{ + struct libipw_crypt_info *info = from_timer(info, t, + crypt_deinit_timer); + unsigned long flags; + + libipw_crypt_deinit_entries(info, 0); + + spin_lock_irqsave(info->lock, flags); + if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) { + printk(KERN_DEBUG "%s: entries remaining in delayed crypt " + "deletion list\n", info->name); + info->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&info->crypt_deinit_timer); + } + spin_unlock_irqrestore(info->lock, flags); +} + +void libipw_crypt_delayed_deinit(struct libipw_crypt_info *info, + struct libipw_crypt_data **crypt) +{ + struct libipw_crypt_data *tmp; + unsigned long flags; + + if (*crypt == NULL) + return; + + tmp = *crypt; + *crypt = NULL; + + /* must not run ops->deinit() while there may be pending encrypt or + * decrypt operations. Use a list of delayed deinits to avoid needing + * locking. */ + + spin_lock_irqsave(info->lock, flags); + if (!info->crypt_quiesced) { + list_add(&tmp->list, &info->crypt_deinit_list); + if (!timer_pending(&info->crypt_deinit_timer)) { + info->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&info->crypt_deinit_timer); + } + } + spin_unlock_irqrestore(info->lock, flags); +} +EXPORT_SYMBOL(libipw_crypt_delayed_deinit); + +int libipw_register_crypto_ops(const struct libipw_crypto_ops *ops) +{ + unsigned long flags; + struct libipw_crypto_alg *alg; + + alg = kzalloc(sizeof(*alg), GFP_KERNEL); + if (alg == NULL) + return -ENOMEM; + + alg->ops = ops; + + spin_lock_irqsave(&libipw_crypto_lock, flags); + list_add(&alg->list, &libipw_crypto_algs); + spin_unlock_irqrestore(&libipw_crypto_lock, flags); + + printk(KERN_DEBUG "libipw_crypt: registered algorithm '%s'\n", + ops->name); + + return 0; +} +EXPORT_SYMBOL(libipw_register_crypto_ops); + +int libipw_unregister_crypto_ops(const struct libipw_crypto_ops *ops) +{ + struct libipw_crypto_alg *alg; + unsigned long flags; + + spin_lock_irqsave(&libipw_crypto_lock, flags); + list_for_each_entry(alg, &libipw_crypto_algs, list) { + if (alg->ops == ops) + goto found; + } + spin_unlock_irqrestore(&libipw_crypto_lock, flags); + return -EINVAL; + + found: + printk(KERN_DEBUG "libipw_crypt: unregistered algorithm '%s'\n", + ops->name); + list_del(&alg->list); + spin_unlock_irqrestore(&libipw_crypto_lock, flags); + kfree(alg); + return 0; +} +EXPORT_SYMBOL(libipw_unregister_crypto_ops); + +const struct libipw_crypto_ops *libipw_get_crypto_ops(const char *name) +{ + struct libipw_crypto_alg *alg; + unsigned long flags; + + spin_lock_irqsave(&libipw_crypto_lock, flags); + list_for_each_entry(alg, &libipw_crypto_algs, list) { + if (strcmp(alg->ops->name, name) == 0) + goto found; + } + spin_unlock_irqrestore(&libipw_crypto_lock, flags); + return NULL; + + found: + spin_unlock_irqrestore(&libipw_crypto_lock, flags); + return alg->ops; +} +EXPORT_SYMBOL(libipw_get_crypto_ops); + +static void *libipw_crypt_null_init(int keyidx) +{ + return (void *)1; +} + +static void libipw_crypt_null_deinit(void *priv) +{ +} + +static const struct libipw_crypto_ops libipw_crypt_null = { + .name = "NULL", + .init = libipw_crypt_null_init, + .deinit = libipw_crypt_null_deinit, + .owner = THIS_MODULE, +}; + +int __init libipw_crypto_init(void) +{ + return libipw_register_crypto_ops(&libipw_crypt_null); +} + +void libipw_crypto_exit(void) +{ + libipw_unregister_crypto_ops(&libipw_crypt_null); + BUG_ON(!list_empty(&libipw_crypto_algs)); +} diff --git a/net/wireless/lib80211_crypt_ccmp.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c index 5aad139130e1..bf900d8c8ad3 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * lib80211 crypt: host-based CCMP encryption implementation for lib80211 + * libipw crypt: host-based CCMP encryption implementation for libipw * * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> @@ -18,17 +18,10 @@ #include <linux/if_arp.h> #include <asm/string.h> #include <linux/wireless.h> - #include <linux/ieee80211.h> - #include <linux/crypto.h> #include <crypto/aead.h> - -#include <net/lib80211.h> - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: CCMP"); -MODULE_LICENSE("GPL"); +#include "libipw.h" #define AES_BLOCK_LEN 16 #define CCMP_HDR_LEN 8 @@ -36,7 +29,7 @@ MODULE_LICENSE("GPL"); #define CCMP_TK_LEN 16 #define CCMP_PN_LEN 6 -struct lib80211_ccmp_data { +struct libipw_ccmp_data { u8 key[CCMP_TK_LEN]; int key_set; @@ -56,9 +49,9 @@ struct lib80211_ccmp_data { u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static void *lib80211_ccmp_init(int key_idx) +static void *libipw_ccmp_init(int key_idx) { - struct lib80211_ccmp_data *priv; + struct libipw_ccmp_data *priv; priv = kzalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) @@ -83,9 +76,9 @@ static void *lib80211_ccmp_init(int key_idx) return NULL; } -static void lib80211_ccmp_deinit(void *priv) +static void libipw_ccmp_deinit(void *priv) { - struct lib80211_ccmp_data *_priv = priv; + struct libipw_ccmp_data *_priv = priv; if (_priv && _priv->tfm) crypto_free_aead(_priv->tfm); kfree(priv); @@ -150,10 +143,10 @@ static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr, return aad_len; } -static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, +static int libipw_ccmp_hdr(struct sk_buff *skb, int hdr_len, u8 *aeskey, int keylen, void *priv) { - struct lib80211_ccmp_data *key = priv; + struct libipw_ccmp_data *key = priv; int i; u8 *pos; @@ -187,9 +180,9 @@ static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len, return CCMP_HDR_LEN; } -static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_ccmp_data *key = priv; + struct libipw_ccmp_data *key = priv; struct ieee80211_hdr *hdr; struct aead_request *req; struct scatterlist sg[2]; @@ -202,7 +195,7 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) return -1; data_len = skb->len - hdr_len; - len = lib80211_ccmp_hdr(skb, hdr_len, NULL, 0, priv); + len = libipw_ccmp_hdr(skb, hdr_len, NULL, 0, priv); if (len < 0) return -1; @@ -251,9 +244,9 @@ static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o) return 0; } -static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_ccmp_data *key = priv; + struct libipw_ccmp_data *key = priv; u8 keyidx, *pos; struct ieee80211_hdr *hdr; struct aead_request *req; @@ -299,7 +292,7 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (ccmp_replay_check(pn, key->rx_pn)) { -#ifdef CONFIG_LIB80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG net_dbg_ratelimited("CCMP: replay detected: STA=%pM previous PN %02x%02x%02x%02x%02x%02x received PN %02x%02x%02x%02x%02x%02x\n", hdr->addr2, key->rx_pn[0], key->rx_pn[1], key->rx_pn[2], @@ -344,9 +337,9 @@ static int lib80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return keyidx; } -static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) +static int libipw_ccmp_set_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_ccmp_data *data = priv; + struct libipw_ccmp_data *data = priv; int keyidx; struct crypto_aead *tfm = data->tfm; @@ -376,9 +369,9 @@ static int lib80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) return 0; } -static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) +static int libipw_ccmp_get_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_ccmp_data *data = priv; + struct libipw_ccmp_data *data = priv; if (len < CCMP_TK_LEN) return -1; @@ -399,9 +392,9 @@ static int lib80211_ccmp_get_key(void *key, int len, u8 * seq, void *priv) return CCMP_TK_LEN; } -static void lib80211_ccmp_print_stats(struct seq_file *m, void *priv) +static void libipw_ccmp_print_stats(struct seq_file *m, void *priv) { - struct lib80211_ccmp_data *ccmp = priv; + struct libipw_ccmp_data *ccmp = priv; seq_printf(m, "key[%d] alg=CCMP key_set=%d " @@ -418,31 +411,28 @@ static void lib80211_ccmp_print_stats(struct seq_file *m, void *priv) ccmp->dot11RSNAStatsCCMPDecryptErrors); } -static const struct lib80211_crypto_ops lib80211_crypt_ccmp = { +static const struct libipw_crypto_ops libipw_crypt_ccmp = { .name = "CCMP", - .init = lib80211_ccmp_init, - .deinit = lib80211_ccmp_deinit, - .encrypt_mpdu = lib80211_ccmp_encrypt, - .decrypt_mpdu = lib80211_ccmp_decrypt, + .init = libipw_ccmp_init, + .deinit = libipw_ccmp_deinit, + .encrypt_mpdu = libipw_ccmp_encrypt, + .decrypt_mpdu = libipw_ccmp_decrypt, .encrypt_msdu = NULL, .decrypt_msdu = NULL, - .set_key = lib80211_ccmp_set_key, - .get_key = lib80211_ccmp_get_key, - .print_stats = lib80211_ccmp_print_stats, + .set_key = libipw_ccmp_set_key, + .get_key = libipw_ccmp_get_key, + .print_stats = libipw_ccmp_print_stats, .extra_mpdu_prefix_len = CCMP_HDR_LEN, .extra_mpdu_postfix_len = CCMP_MIC_LEN, .owner = THIS_MODULE, }; -static int __init lib80211_crypto_ccmp_init(void) +int __init libipw_crypto_ccmp_init(void) { - return lib80211_register_crypto_ops(&lib80211_crypt_ccmp); + return libipw_register_crypto_ops(&libipw_crypt_ccmp); } -static void __exit lib80211_crypto_ccmp_exit(void) +void libipw_crypto_ccmp_exit(void) { - lib80211_unregister_crypto_ops(&lib80211_crypt_ccmp); + libipw_unregister_crypto_ops(&libipw_crypt_ccmp); } - -module_init(lib80211_crypto_ccmp_init); -module_exit(lib80211_crypto_ccmp_exit); diff --git a/net/wireless/lib80211_crypt_tkip.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c index 63e68e5e121e..32288697da4f 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_tkip.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * lib80211 crypt: host-based TKIP encryption implementation for lib80211 + * libipw crypt: host-based TKIP encryption implementation for libipw * * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi> * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> @@ -21,25 +21,18 @@ #include <linux/if_ether.h> #include <linux/if_arp.h> #include <asm/string.h> - #include <linux/wireless.h> #include <linux/ieee80211.h> #include <net/iw_handler.h> - #include <crypto/arc4.h> #include <crypto/hash.h> #include <linux/crypto.h> #include <linux/crc32.h> - -#include <net/lib80211.h> - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("lib80211 crypt: TKIP"); -MODULE_LICENSE("GPL"); +#include "libipw.h" #define TKIP_HDR_LEN 8 -struct lib80211_tkip_data { +struct libipw_tkip_data { #define TKIP_KEY_LEN 32 u8 key[TKIP_KEY_LEN]; int key_set; @@ -73,23 +66,23 @@ struct lib80211_tkip_data { unsigned long flags; }; -static unsigned long lib80211_tkip_set_flags(unsigned long flags, void *priv) +static unsigned long libipw_tkip_set_flags(unsigned long flags, void *priv) { - struct lib80211_tkip_data *_priv = priv; + struct libipw_tkip_data *_priv = priv; unsigned long old_flags = _priv->flags; _priv->flags = flags; return old_flags; } -static unsigned long lib80211_tkip_get_flags(void *priv) +static unsigned long libipw_tkip_get_flags(void *priv) { - struct lib80211_tkip_data *_priv = priv; + struct libipw_tkip_data *_priv = priv; return _priv->flags; } -static void *lib80211_tkip_init(int key_idx) +static void *libipw_tkip_init(int key_idx) { - struct lib80211_tkip_data *priv; + struct libipw_tkip_data *priv; if (fips_enabled) return NULL; @@ -124,9 +117,9 @@ static void *lib80211_tkip_init(int key_idx) return NULL; } -static void lib80211_tkip_deinit(void *priv) +static void libipw_tkip_deinit(void *priv) { - struct lib80211_tkip_data *_priv = priv; + struct libipw_tkip_data *_priv = priv; if (_priv) { crypto_free_shash(_priv->tx_tfm_michael); crypto_free_shash(_priv->rx_tfm_michael); @@ -280,10 +273,10 @@ static void tkip_mixing_phase2(u8 * WEPSeed, const u8 * TK, const u16 * TTAK, #endif } -static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, +static int libipw_tkip_hdr(struct sk_buff *skb, int hdr_len, u8 * rc4key, int keylen, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; u8 *pos; struct ieee80211_hdr *hdr; @@ -324,9 +317,9 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, return TKIP_HDR_LEN; } -static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; int len; u8 rc4key[16], *pos, *icv; u32 crc; @@ -344,7 +337,7 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) len = skb->len - hdr_len; pos = skb->data + hdr_len; - if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) + if ((libipw_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) return -1; crc = ~crc32_le(~0, pos, len); @@ -373,9 +366,9 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, return 0; } -static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; u8 rc4key[16]; u8 keyidx, *pos; u32 iv32; @@ -419,7 +412,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += TKIP_HDR_LEN; if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { -#ifdef CONFIG_LIB80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG net_dbg_ratelimited("TKIP: replay detected: STA=%pM previous TSC %08x%04x received TSC %08x%04x\n", hdr->addr2, tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); @@ -450,7 +443,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) * it needs to be recalculated for the next packet. */ tkey->rx_phase1_done = 0; } -#ifdef CONFIG_LIB80211_DEBUG +#ifdef CONFIG_LIBIPW_DEBUG net_dbg_ratelimited("TKIP: ICV error detected: STA=%pM\n", hdr->addr2); #endif @@ -538,10 +531,10 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ } -static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len, +static int libipw_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; u8 *pos; if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { @@ -560,7 +553,7 @@ static int lib80211_michael_mic_add(struct sk_buff *skb, int hdr_len, return 0; } -static void lib80211_michael_mic_failure(struct net_device *dev, +static void libipw_michael_mic_failure(struct net_device *dev, struct ieee80211_hdr *hdr, int keyidx) { @@ -581,10 +574,10 @@ static void lib80211_michael_mic_failure(struct net_device *dev, wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); } -static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx, +static int libipw_michael_mic_verify(struct sk_buff *skb, int keyidx, int hdr_len, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; u8 mic[8]; if (!tkey->key_set) @@ -602,7 +595,7 @@ static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx, skb->dev ? skb->dev->name : "N/A", hdr->addr2, keyidx); if (skb->dev) - lib80211_michael_mic_failure(skb->dev, hdr, keyidx); + libipw_michael_mic_failure(skb->dev, hdr, keyidx); tkey->dot11RSNAStatsTKIPLocalMICFailures++; return -1; } @@ -617,9 +610,9 @@ static int lib80211_michael_mic_verify(struct sk_buff *skb, int keyidx, return 0; } -static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) +static int libipw_tkip_set_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; int keyidx; struct crypto_shash *tfm = tkey->tx_tfm_michael; struct arc4_ctx *tfm2 = &tkey->tx_ctx_arc4; @@ -650,9 +643,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) return 0; } -static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) +static int libipw_tkip_get_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_tkip_data *tkey = priv; + struct libipw_tkip_data *tkey = priv; if (len < TKIP_KEY_LEN) return -1; @@ -679,9 +672,9 @@ static int lib80211_tkip_get_key(void *key, int len, u8 * seq, void *priv) return TKIP_KEY_LEN; } -static void lib80211_tkip_print_stats(struct seq_file *m, void *priv) +static void libipw_tkip_print_stats(struct seq_file *m, void *priv) { - struct lib80211_tkip_data *tkip = priv; + struct libipw_tkip_data *tkip = priv; seq_printf(m, "key[%d] alg=TKIP key_set=%d " "tx_pn=%02x%02x%02x%02x%02x%02x " @@ -705,34 +698,31 @@ static void lib80211_tkip_print_stats(struct seq_file *m, void *priv) tkip->dot11RSNAStatsTKIPLocalMICFailures); } -static const struct lib80211_crypto_ops lib80211_crypt_tkip = { +static const struct libipw_crypto_ops libipw_crypt_tkip = { .name = "TKIP", - .init = lib80211_tkip_init, - .deinit = lib80211_tkip_deinit, - .encrypt_mpdu = lib80211_tkip_encrypt, - .decrypt_mpdu = lib80211_tkip_decrypt, - .encrypt_msdu = lib80211_michael_mic_add, - .decrypt_msdu = lib80211_michael_mic_verify, - .set_key = lib80211_tkip_set_key, - .get_key = lib80211_tkip_get_key, - .print_stats = lib80211_tkip_print_stats, + .init = libipw_tkip_init, + .deinit = libipw_tkip_deinit, + .encrypt_mpdu = libipw_tkip_encrypt, + .decrypt_mpdu = libipw_tkip_decrypt, + .encrypt_msdu = libipw_michael_mic_add, + .decrypt_msdu = libipw_michael_mic_verify, + .set_key = libipw_tkip_set_key, + .get_key = libipw_tkip_get_key, + .print_stats = libipw_tkip_print_stats, .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ .extra_mpdu_postfix_len = 4, /* ICV */ .extra_msdu_postfix_len = 8, /* MIC */ - .get_flags = lib80211_tkip_get_flags, - .set_flags = lib80211_tkip_set_flags, + .get_flags = libipw_tkip_get_flags, + .set_flags = libipw_tkip_set_flags, .owner = THIS_MODULE, }; -static int __init lib80211_crypto_tkip_init(void) +int __init libipw_crypto_tkip_init(void) { - return lib80211_register_crypto_ops(&lib80211_crypt_tkip); + return libipw_register_crypto_ops(&libipw_crypt_tkip); } -static void __exit lib80211_crypto_tkip_exit(void) +void libipw_crypto_tkip_exit(void) { - lib80211_unregister_crypto_ops(&lib80211_crypt_tkip); + libipw_unregister_crypto_ops(&libipw_crypt_tkip); } - -module_init(lib80211_crypto_tkip_init); -module_exit(lib80211_crypto_tkip_exit); diff --git a/net/wireless/lib80211_crypt_wep.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_wep.c index 3b148c7bef85..c3a4ccb9de17 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_wep.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * lib80211 crypt: host-based WEP encryption implementation for lib80211 + * libipw crypt: host-based WEP encryption implementation for libipw * * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> @@ -16,17 +16,11 @@ #include <linux/skbuff.h> #include <linux/mm.h> #include <asm/string.h> - -#include <net/lib80211.h> - #include <crypto/arc4.h> #include <linux/crc32.h> +#include "libipw.h" -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("lib80211 crypt: WEP"); -MODULE_LICENSE("GPL"); - -struct lib80211_wep_data { +struct libipw_wep_data { u32 iv; #define WEP_KEY_LEN 13 u8 key[WEP_KEY_LEN + 1]; @@ -36,9 +30,9 @@ struct lib80211_wep_data { struct arc4_ctx rx_ctx; }; -static void *lib80211_wep_init(int keyidx) +static void *libipw_wep_init(int keyidx) { - struct lib80211_wep_data *priv; + struct libipw_wep_data *priv; if (fips_enabled) return NULL; @@ -54,16 +48,16 @@ static void *lib80211_wep_init(int keyidx) return priv; } -static void lib80211_wep_deinit(void *priv) +static void libipw_wep_deinit(void *priv) { kfree_sensitive(priv); } /* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */ -static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, +static int libipw_wep_build_iv(struct sk_buff *skb, int hdr_len, u8 *key, int keylen, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; u32 klen; u8 *pos; @@ -102,19 +96,19 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, * * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) */ -static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; u32 crc, klen, len; u8 *pos, *icv; u8 key[WEP_KEY_LEN + 3]; - /* other checks are in lib80211_wep_build_iv */ + /* other checks are in libipw_wep_build_iv */ if (skb_tailroom(skb) < 4) return -1; /* add the IV to the frame */ - if (lib80211_wep_build_iv(skb, hdr_len, NULL, 0, priv)) + if (libipw_wep_build_iv(skb, hdr_len, NULL, 0, priv)) return -1; /* Copy the IV into the first 3 bytes of the key */ @@ -148,9 +142,9 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on * failure. If frame is OK, IV and ICV will be removed. */ -static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +static int libipw_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; u32 crc, klen, plen; u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos, icv[4]; @@ -195,9 +189,9 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return 0; } -static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv) +static int libipw_wep_set_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; if (len < 0 || len > WEP_KEY_LEN) return -1; @@ -208,9 +202,9 @@ static int lib80211_wep_set_key(void *key, int len, u8 * seq, void *priv) return 0; } -static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv) +static int libipw_wep_get_key(void *key, int len, u8 * seq, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; if (len < wep->key_len) return -1; @@ -220,37 +214,34 @@ static int lib80211_wep_get_key(void *key, int len, u8 * seq, void *priv) return wep->key_len; } -static void lib80211_wep_print_stats(struct seq_file *m, void *priv) +static void libipw_wep_print_stats(struct seq_file *m, void *priv) { - struct lib80211_wep_data *wep = priv; + struct libipw_wep_data *wep = priv; seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len); } -static const struct lib80211_crypto_ops lib80211_crypt_wep = { +static const struct libipw_crypto_ops libipw_crypt_wep = { .name = "WEP", - .init = lib80211_wep_init, - .deinit = lib80211_wep_deinit, - .encrypt_mpdu = lib80211_wep_encrypt, - .decrypt_mpdu = lib80211_wep_decrypt, + .init = libipw_wep_init, + .deinit = libipw_wep_deinit, + .encrypt_mpdu = libipw_wep_encrypt, + .decrypt_mpdu = libipw_wep_decrypt, .encrypt_msdu = NULL, .decrypt_msdu = NULL, - .set_key = lib80211_wep_set_key, - .get_key = lib80211_wep_get_key, - .print_stats = lib80211_wep_print_stats, + .set_key = libipw_wep_set_key, + .get_key = libipw_wep_get_key, + .print_stats = libipw_wep_print_stats, .extra_mpdu_prefix_len = 4, /* IV */ .extra_mpdu_postfix_len = 4, /* ICV */ .owner = THIS_MODULE, }; -static int __init lib80211_crypto_wep_init(void) +int __init libipw_crypto_wep_init(void) { - return lib80211_register_crypto_ops(&lib80211_crypt_wep); + return libipw_register_crypto_ops(&libipw_crypt_wep); } -static void __exit lib80211_crypto_wep_exit(void) +void __exit libipw_crypto_wep_exit(void) { - lib80211_unregister_crypto_ops(&lib80211_crypt_wep); + libipw_unregister_crypto_ops(&libipw_crypt_wep); } - -module_init(lib80211_crypto_wep_init); -module_exit(lib80211_crypto_wep_exit); diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_module.c b/drivers/net/wireless/intel/ipw2x00/libipw_module.c index 43bab92a4148..0a16127bfd68 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_module.c @@ -169,7 +169,7 @@ struct net_device *alloc_libipw(int sizeof_priv, int monitor) spin_lock_init(&ieee->lock); - lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); + libipw_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); ieee->wpa_enabled = 0; ieee->drop_unencrypted = 0; @@ -191,7 +191,7 @@ void free_libipw(struct net_device *dev, int monitor) { struct libipw_device *ieee = netdev_priv(dev); - lib80211_crypt_info_free(&ieee->crypt_info); + libipw_crypt_info_free(&ieee->crypt_info); libipw_networks_free(ieee); @@ -251,6 +251,7 @@ static const struct proc_ops debug_level_proc_ops = { static int __init libipw_init(void) { + int err; #ifdef CONFIG_LIBIPW_DEBUG struct proc_dir_entry *e; @@ -273,7 +274,33 @@ static int __init libipw_init(void) printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + err = libipw_crypto_init(); + if (err) + goto remove_debugfs; + err = libipw_crypto_ccmp_init(); + if (err) + goto uninit_crypto; + err = libipw_crypto_tkip_init(); + if (err) + goto uninit_crypto_ccmp; + err = libipw_crypto_wep_init(); + if (err) + goto uninit_crypto_tkip; + return 0; +uninit_crypto_tkip: + libipw_crypto_tkip_exit(); +uninit_crypto_ccmp: + libipw_crypto_ccmp_exit(); +uninit_crypto: + libipw_crypto_exit(); +remove_debugfs: +#ifdef CONFIG_LIBIPW_DEBUG + remove_proc_entry("debug_level", libipw_proc); + remove_proc_entry(DRV_PROCNAME, init_net.proc_net); + libipw_proc = NULL; +#endif + return err; } static void __exit libipw_exit(void) @@ -285,6 +312,11 @@ static void __exit libipw_exit(void) libipw_proc = NULL; } #endif /* CONFIG_LIBIPW_DEBUG */ + + libipw_crypto_ccmp_exit(); + libipw_crypto_tkip_exit(); + libipw_crypto_wep_exit(); + libipw_crypto_exit(); } #ifdef CONFIG_LIBIPW_DEBUG diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c index 48d6870bbf4e..7e41cb7bbfe0 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_rx.c @@ -27,9 +27,6 @@ #include <linux/etherdevice.h> #include <linux/uaccess.h> #include <linux/ctype.h> - -#include <net/lib80211.h> - #include "libipw.h" static void libipw_monitor_rx(struct libipw_device *ieee, @@ -266,7 +263,7 @@ static int libipw_is_eapol_frame(struct libipw_device *ieee, /* Called only as a tasklet (software IRQ), by libipw_rx */ static int libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb, - struct lib80211_crypt_data *crypt) + struct libipw_crypt_data *crypt) { struct libipw_hdr_3addr *hdr; int res, hdrlen; @@ -298,7 +295,7 @@ libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb, static int libipw_rx_frame_decrypt_msdu(struct libipw_device *ieee, struct sk_buff *skb, int keyidx, - struct lib80211_crypt_data *crypt) + struct libipw_crypt_data *crypt) { struct libipw_hdr_3addr *hdr; int res, hdrlen; @@ -345,7 +342,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, #endif u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; - struct lib80211_crypt_data *crypt = NULL; + struct libipw_crypt_data *crypt = NULL; int keyidx = 0; int can_be_decrypted = 0; @@ -396,7 +393,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, wstats.updated |= IW_QUAL_QUAL_INVALID; /* Update spy records */ - wireless_spy_update(ieee->dev, hdr->addr2, &wstats); + libipw_spy_update(ieee->dev, hdr->addr2, &wstats); } #endif /* IW_WIRELESS_SPY */ #endif /* CONFIG_WIRELESS_EXT */ diff --git a/net/wireless/wext-spy.c b/drivers/net/wireless/intel/ipw2x00/libipw_spy.c index b379a0371653..ba876e92f7f6 100644 --- a/net/wireless/wext-spy.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_spy.c @@ -14,19 +14,21 @@ #include <net/iw_handler.h> #include <net/arp.h> #include <net/wext.h> +#include "libipw.h" -static inline struct iw_spy_data *get_spydata(struct net_device *dev) +static struct iw_spy_data *get_spydata(struct net_device *dev) { - /* This is the new way */ - if (dev->wireless_data) - return dev->wireless_data->spy_data; + struct libipw_device *ieee = netdev_priv(dev); + + if (ieee->spy_enabled) + return &ieee->spy_data; return NULL; } -int iw_handler_set_spy(struct net_device * dev, - struct iw_request_info * info, - union iwreq_data * wrqu, - char * extra) +int ipw_wx_set_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) { struct iw_spy_data * spydata = get_spydata(dev); struct sockaddr * address = (struct sockaddr *) extra; @@ -36,15 +38,15 @@ int iw_handler_set_spy(struct net_device * dev, return -EOPNOTSUPP; /* Disable spy collection while we copy the addresses. - * While we copy addresses, any call to wireless_spy_update() + * While we copy addresses, any call to libipw_spy_update() * will NOP. This is OK, as anyway the addresses are changing. */ spydata->spy_number = 0; - /* We want to operate without locking, because wireless_spy_update() + /* We want to operate without locking, because libipw_spy_update() * most likely will happen in the interrupt handler, and therefore * have its own locking constraints and needs performance. * The rtnl_lock() make sure we don't race with the other iw_handlers. - * This make sure wireless_spy_update() "see" that the spy list + * This make sure libipw_spy_update() "see" that the spy list * is temporarily disabled. */ smp_wmb(); @@ -69,12 +71,12 @@ int iw_handler_set_spy(struct net_device * dev, return 0; } -EXPORT_SYMBOL(iw_handler_set_spy); +EXPORT_SYMBOL(ipw_wx_set_spy); -int iw_handler_get_spy(struct net_device * dev, - struct iw_request_info * info, - union iwreq_data * wrqu, - char * extra) +int ipw_wx_get_spy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) { struct iw_spy_data * spydata = get_spydata(dev); struct sockaddr * address = (struct sockaddr *) extra; @@ -101,16 +103,16 @@ int iw_handler_get_spy(struct net_device * dev, spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED; return 0; } -EXPORT_SYMBOL(iw_handler_get_spy); +EXPORT_SYMBOL(ipw_wx_get_spy); /*------------------------------------------------------------------*/ /* * Standard Wireless Handler : set spy threshold */ -int iw_handler_set_thrspy(struct net_device * dev, - struct iw_request_info *info, - union iwreq_data * wrqu, - char * extra) +int ipw_wx_set_thrspy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) { struct iw_spy_data * spydata = get_spydata(dev); struct iw_thrspy * threshold = (struct iw_thrspy *) extra; @@ -128,16 +130,16 @@ int iw_handler_set_thrspy(struct net_device * dev, return 0; } -EXPORT_SYMBOL(iw_handler_set_thrspy); +EXPORT_SYMBOL(ipw_wx_set_thrspy); /*------------------------------------------------------------------*/ /* * Standard Wireless Handler : get spy threshold */ -int iw_handler_get_thrspy(struct net_device * dev, - struct iw_request_info *info, - union iwreq_data * wrqu, - char * extra) +int ipw_wx_get_thrspy(struct net_device * dev, + struct iw_request_info * info, + union iwreq_data * wrqu, + char * extra) { struct iw_spy_data * spydata = get_spydata(dev); struct iw_thrspy * threshold = (struct iw_thrspy *) extra; @@ -152,7 +154,7 @@ int iw_handler_get_thrspy(struct net_device * dev, return 0; } -EXPORT_SYMBOL(iw_handler_get_thrspy); +EXPORT_SYMBOL(ipw_wx_get_thrspy); /*------------------------------------------------------------------*/ /* @@ -189,9 +191,9 @@ static void iw_send_thrspy_event(struct net_device * dev, * small, this is good enough. If we wanted to support larger number of * spy addresses, we should use something more efficient... */ -void wireless_spy_update(struct net_device * dev, - unsigned char * address, - struct iw_quality * wstats) +void libipw_spy_update(struct net_device * dev, + unsigned char * address, + struct iw_quality * wstats) { struct iw_spy_data * spydata = get_spydata(dev); int i; @@ -229,4 +231,3 @@ void wireless_spy_update(struct net_device * dev, } } } -EXPORT_SYMBOL(wireless_spy_update); diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c index e22a6732a4c3..80edaa3dea9c 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_tx.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_tx.c @@ -138,7 +138,7 @@ static int libipw_copy_snap(u8 * data, __be16 h_proto) static int libipw_encrypt_fragment(struct libipw_device *ieee, struct sk_buff *frag, int hdr_len) { - struct lib80211_crypt_data *crypt = + struct libipw_crypt_data *crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; int res; @@ -255,7 +255,7 @@ netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; - struct lib80211_crypt_data *crypt; + struct libipw_crypt_data *crypt; int priority = skb->priority; int snapped = 0; diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c index dbc7153d0a3d..db71d81b0d4f 100644 --- a/drivers/net/wireless/intel/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/intel/ipw2x00/libipw_wx.c @@ -21,10 +21,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/jiffies.h> - -#include <net/lib80211.h> #include <linux/wireless.h> - #include "libipw.h" static const char *libipw_modes[] = { @@ -303,7 +300,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee, .flags = 0 }; int i, key, key_provided, len; - struct lib80211_crypt_data **crypt; + struct libipw_crypt_data **crypt; int host_crypto = ieee->host_encrypt || ieee->host_decrypt; LIBIPW_DEBUG_WX("SET_ENCODE\n"); @@ -328,7 +325,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee, if (key_provided && *crypt) { LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n", key); - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); + libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt); } else LIBIPW_DEBUG_WX("Disabling encryption.\n"); @@ -338,7 +335,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee, if (ieee->crypt_info.crypt[i] != NULL) { if (key_provided) break; - lib80211_crypt_delayed_deinit(&ieee->crypt_info, + libipw_crypt_delayed_deinit(&ieee->crypt_info, &ieee->crypt_info.crypt[i]); } } @@ -361,21 +358,21 @@ int libipw_wx_set_encode(struct libipw_device *ieee, strcmp((*crypt)->ops->name, "WEP") != 0) { /* changing to use WEP; deinit previously used algorithm * on this key */ - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); + libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt); } if (*crypt == NULL && host_crypto) { - struct lib80211_crypt_data *new_crypt; + struct libipw_crypt_data *new_crypt; /* take WEP into use */ - new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), + new_crypt = kzalloc(sizeof(struct libipw_crypt_data), GFP_KERNEL); if (new_crypt == NULL) return -ENOMEM; - new_crypt->ops = lib80211_get_crypto_ops("WEP"); + new_crypt->ops = libipw_get_crypto_ops("WEP"); if (!new_crypt->ops) { - request_module("lib80211_crypt_wep"); - new_crypt->ops = lib80211_get_crypto_ops("WEP"); + request_module("libipw_crypt_wep"); + new_crypt->ops = libipw_get_crypto_ops("WEP"); } if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) @@ -386,7 +383,7 @@ int libipw_wx_set_encode(struct libipw_device *ieee, new_crypt = NULL; printk(KERN_WARNING "%s: could not initialize WEP: " - "load module lib80211_crypt_wep\n", dev->name); + "load module libipw_crypt_wep\n", dev->name); return -EOPNOTSUPP; } *crypt = new_crypt; @@ -509,8 +506,8 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, int i, idx, ret = 0; int group_key = 0; const char *alg, *module; - const struct lib80211_crypto_ops *ops; - struct lib80211_crypt_data **crypt; + const struct libipw_crypto_ops *ops; + struct libipw_crypt_data **crypt; struct libipw_security sec = { .flags = 0, @@ -541,7 +538,7 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE) { if (*crypt) - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); + libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt); for (i = 0; i < WEP_KEYS; i++) if (ieee->crypt_info.crypt[i] != NULL) @@ -567,15 +564,15 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, switch (ext->alg) { case IW_ENCODE_ALG_WEP: alg = "WEP"; - module = "lib80211_crypt_wep"; + module = "libipw_crypt_wep"; break; case IW_ENCODE_ALG_TKIP: alg = "TKIP"; - module = "lib80211_crypt_tkip"; + module = "libipw_crypt_tkip"; break; case IW_ENCODE_ALG_CCMP: alg = "CCMP"; - module = "lib80211_crypt_ccmp"; + module = "libipw_crypt_ccmp"; break; default: LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n", @@ -584,10 +581,10 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, goto done; } - ops = lib80211_get_crypto_ops(alg); + ops = libipw_get_crypto_ops(alg); if (ops == NULL) { request_module(module); - ops = lib80211_get_crypto_ops(alg); + ops = libipw_get_crypto_ops(alg); } if (ops == NULL) { LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n", @@ -597,9 +594,9 @@ int libipw_wx_set_encodeext(struct libipw_device *ieee, } if (*crypt == NULL || (*crypt)->ops != ops) { - struct lib80211_crypt_data *new_crypt; + struct libipw_crypt_data *new_crypt; - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); + libipw_crypt_delayed_deinit(&ieee->crypt_info, crypt); new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); if (new_crypt == NULL) { diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index fa1be8c54d3c..ea40d402681d 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware API version supported */ -#define IWL_BZ_UCODE_API_MAX 93 +#define IWL_BZ_UCODE_API_MAX 94 /* Lowest firmware API version supported */ #define IWL_BZ_UCODE_API_MIN 90 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index f1dd1c29f305..635fed641c19 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware API version supported */ -#define IWL_SC_UCODE_API_MAX 93 +#define IWL_SC_UCODE_API_MAX 94 /* Lowest firmware API version supported */ #define IWL_SC_UCODE_API_MIN 90 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index c46e24fc6a1e..b23d5fc4bbe6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -382,6 +382,8 @@ struct iwl_mac_config_cmd { * @LINK_CONTEXT_MODIFY_EHT_PARAMS: covers iwl_link_ctx_cfg_cmd::puncture_mask. * This flag can be set only if the MAC that this link relates to has * eht_support set to true. No longer used since _VER_3 of this command. + * @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth. + * Request RX OMI to the AP to modify bandwidth of this link. * @LINK_CONTEXT_MODIFY_ALL: set all above flags */ enum iwl_link_ctx_modify_flags { @@ -393,6 +395,7 @@ enum iwl_link_ctx_modify_flags { LINK_CONTEXT_MODIFY_HE_PARAMS = BIT(5), LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6), LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7), + LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8), LINK_CONTEXT_MODIFY_ALL = 0xff, }; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */ @@ -434,6 +437,22 @@ enum iwl_link_ctx_flags { }; /* LINK_CONTEXT_FLAG_E_VER_1 */ /** + * enum iwl_link_modify_bandwidth - link modify (RX OMI) bandwidth + * @IWL_LINK_MODIFY_BW_20: request 20 MHz + * @IWL_LINK_MODIFY_BW_40: request 40 MHz + * @IWL_LINK_MODIFY_BW_80: request 80 MHz + * @IWL_LINK_MODIFY_BW_160: request 160 MHz + * @IWL_LINK_MODIFY_BW_320: request 320 MHz + */ +enum iwl_link_modify_bandwidth { + IWL_LINK_MODIFY_BW_20, + IWL_LINK_MODIFY_BW_40, + IWL_LINK_MODIFY_BW_80, + IWL_LINK_MODIFY_BW_160, + IWL_LINK_MODIFY_BW_320, +}; + +/** * struct iwl_link_config_cmd - command structure to configure the LINK context * in MLD API * ( LINK_CONFIG_CMD =0x9 ) @@ -457,6 +476,8 @@ enum iwl_link_ctx_flags { * @block_tx: tell the firmware that this link can't Tx. This should be used * only when a link is de-activated because of CSA with mode = 1. * Available since version 5. + * @modify_bandwidth: bandwidth request value for RX OMI (see also + * %LINK_CONTEXT_MODIFY_BANDWIDTH), from &enum iwl_link_modify_bandwidth. * @reserved1: in version 2, listen_lmac became reserved * @cck_rates: basic rates available for CCK * @ofdm_rates: basic rates available for OFDM @@ -500,10 +521,11 @@ struct iwl_link_config_cmd { __le32 modify_mask; __le32 active; union { - __le32 listen_lmac; + __le32 listen_lmac; /* only _VER_1 */ struct { - u8 block_tx; - u8 reserved1[3]; + u8 block_tx; /* since _VER_5 */ + u8 modify_bandwidth; /* since _VER_6 */ + u8 reserved1[2]; }; }; __le32 cck_rates; @@ -524,7 +546,7 @@ struct iwl_link_config_cmd { __le16 puncture_mask; /* removed in _VER_3 */ __le16 frame_time_rts_th; __le32 flags; - __le32 flags_mask; + __le32 flags_mask; /* removed in _VER_6 */ /* The below fields are for multi-bssid */ u8 ref_bssid_addr[6]; __le16 reserved_for_ref_bssid_addr; @@ -535,7 +557,7 @@ struct iwl_link_config_cmd { u8 ibss_bssid_addr[6]; __le16 reserved_for_ibss_bssid_addr; __le32 reserved3[8]; -} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5 */ +} __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, _VER_5, _VER_6 */ /* Currently FW supports link ids in the range 0-3 and can have * at most two active links for each vif. diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 98d56e778d99..f4803b55adb9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018-2019, 2021-2023 Intel Corporation + * Copyright (C) 2005-2014, 2018-2019, 2021-2024 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -327,18 +327,19 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt); void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt, u32 timepoint, u32 timepoint_data); +bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id); void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt); void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt); -#define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \ - IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__) +#define IWL_FW_CHECK_FAILED(_obj, ...) \ + IWL_ERR_LIMIT(_obj, __VA_ARGS__) #define IWL_FW_CHECK(_obj, _cond, _fmt, ...) \ ({ \ bool __cond = (_cond); \ \ if (unlikely(__cond)) \ - IWL_FW_CHECK_FAILED(_obj, _fmt, __VA_ARGS__); \ + IWL_FW_CHECK_FAILED(_obj, _fmt, ##__VA_ARGS__); \ \ unlikely(__cond); \ }) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 8f107ceec407..3cabdeb53e99 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2023 Intel Corporation + * Copyright (C) 2012-2014, 2018-2024 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -530,3 +530,23 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) } } IWL_EXPORT_SYMBOL(iwl_fwrt_dump_error_logs); + +bool iwl_fwrt_read_err_table(struct iwl_trans *trans, u32 base, u32 *err_id) +{ + struct error_table_start { + /* cf. struct iwl_error_event_table */ + u32 valid; + __le32 err_id; + } err_info; + + if (!base) + return false; + + iwl_trans_read_mem_bytes(trans, base, + &err_info, sizeof(err_info)); + if (err_info.valid && err_id) + *err_id = le32_to_cpu(err_info.err_id); + + return !!err_info.valid; +} +IWL_EXPORT_SYMBOL(iwl_fwrt_read_err_table); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index ddf484027d4f..795a166ed63a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -17,7 +17,8 @@ #define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30 #define IWL_MVM_TPT_COUNT_WINDOW_SEC 5 #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5 -#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 11 +#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15 +#define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11 #define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC) #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) @@ -57,7 +58,6 @@ #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 -#define IWL_MVM_HW_CSUM_DISABLE 0 #define IWL_MVM_ADWELL_ENABLE 1 #define IWL_MVM_ADWELL_MAX_BUDGET 0 #define IWL_MVM_TCM_LOAD_MEDIUM_THRESH 10 /* percentage */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 49a6aff42376..9f41b9af5269 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -3024,24 +3024,6 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, ieee80211_resume_disconnect(vif); } -static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id) -{ - struct error_table_start { - /* cf. struct iwl_error_event_table */ - u32 valid; - __le32 err_id; - } err_info; - - if (!base) - return false; - - iwl_trans_read_mem_bytes(trans, base, - &err_info, sizeof(err_info)); - if (err_info.valid && err_id) - *err_id = le32_to_cpu(err_info.err_id); - - return !!err_info.valid; -} static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -3049,9 +3031,9 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm, u32 err_id; /* check for lmac1 error */ - if (iwl_mvm_rt_status(mvm->trans, - mvm->trans->dbg.lmac_error_event_table[0], - &err_id)) { + if (iwl_fwrt_read_err_table(mvm->trans, + mvm->trans->dbg.lmac_error_event_table[0], + &err_id)) { if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) { struct cfg80211_wowlan_wakeup wakeup = { .rfkill_release = true, @@ -3063,13 +3045,15 @@ static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm, } /* check if we have lmac2 set and check for error */ - if (iwl_mvm_rt_status(mvm->trans, - mvm->trans->dbg.lmac_error_event_table[1], NULL)) + if (iwl_fwrt_read_err_table(mvm->trans, + mvm->trans->dbg.lmac_error_event_table[1], + NULL)) return true; /* check for umac error */ - if (iwl_mvm_rt_status(mvm->trans, - mvm->trans->dbg.umac_error_event_table, NULL)) + if (iwl_fwrt_read_err_table(mvm->trans, + mvm->trans->dbg.umac_error_event_table, + NULL)) return true; return false; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 2b0652168002..628baf67b208 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -12,6 +12,7 @@ HOW(BLOCKED_FW) \ HOW(BLOCKED_NON_BSS) \ HOW(BLOCKED_ROC) \ + HOW(BLOCKED_TMP_NON_BSS) \ HOW(EXIT_MISSED_BEACON) \ HOW(EXIT_LOW_RSSI) \ HOW(EXIT_COEX) \ @@ -360,7 +361,8 @@ int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, send_cmd: cmd.modify_mask = cpu_to_le32(changes); cmd.flags = cpu_to_le32(flags); - cmd.flags_mask = cpu_to_le32(flags_mask); + if (cmd_ver < 6) + cmd.flags_mask = cpu_to_le32(flags_mask); cmd.spec_link_id = link_conf->link_id; if (cmd_ver < 2) cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index a7a10e716e65..9a43df49493f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1605,6 +1605,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, 0); u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, MISSED_BEACONS_NOTIF, 0); + struct ieee80211_bss_conf *bss_conf; /* If the firmware uses the new notification (from MAC_CONF_GROUP), * refer to that notification's version. @@ -1617,9 +1618,9 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, /* before version four the ID in the notification refers to mac ID */ if (notif_ver < 4) { vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); + bss_conf = &vif->bss_conf; } else { - struct ieee80211_bss_conf *bss_conf = - iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false); + bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false); if (!bss_conf) return; @@ -1664,6 +1665,8 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, rx_missed_bcon, rx_missed_bcon_since_rx); } } else if (link_id >= 0 && hweight16(vif->active_links) > 1) { + u32 bss_param_ch_cnt_link_id = + bss_conf->bss_param_ch_cnt_link_id; u32 scnd_lnk_bcn_lost = 0; if (notif_ver >= 5 && @@ -1677,10 +1680,14 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, /* Exit EMLSR if we lost more than * IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link. + * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED + * and the link's bss_param_ch_count has changed. */ if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS && scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) || - rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH) + rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH || + (bss_param_ch_cnt_link_id != link_id && + rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED)) iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_MISSED_BEACON, iwl_mvm_get_primary_link(vif)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a327893c6dce..4db7c3ee6bf5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1336,6 +1336,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) * of packets the FW sent out, so we must reconnect. */ iwl_mvm_teardown_tdls_peers(mvm); + + IWL_INFO(mvm, "restart completed\n"); } void iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, @@ -1466,15 +1468,16 @@ struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) return NULL; } -int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, + struct ieee80211_bss_conf *link_conf, s16 tx_power) { u32 cmd_id = REDUCE_TX_POWER_CMD; + u32 mac_id = iwl_mvm_vif_from_mac80211(link_conf->vif)->id; int len; struct iwl_dev_tx_power_cmd_v3_v8 cmd = { .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC), - .common.mac_context_id = - cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id), + .common.mac_context_id = cpu_to_le32(mac_id), }; struct iwl_dev_tx_power_cmd cmd_v9_v10; u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3); @@ -1487,8 +1490,7 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (cmd_ver > 8) { /* Those fields sit on the same place for v9 and v10 */ cmd_v9_v10.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC); - cmd_v9_v10.common.mac_context_id = - cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id); + cmd_v9_v10.common.mac_context_id = cpu_to_le32(mac_id); cmd_v9_v10.common.pwr_restriction = cpu_to_le16(u_tx_power); cmd_data = &cmd_v9_v10; } @@ -1731,6 +1733,21 @@ static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk) iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT); } +static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy, + struct wiphy_work *wk) +{ + struct iwl_mvm_vif *mvmvif = + container_of(wk, struct iwl_mvm_vif, + unblock_esr_tmp_non_bss_wk.work); + struct iwl_mvm *mvm = mvmvif->mvm; + struct ieee80211_vif *vif = + container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); + + mutex_lock(&mvm->mutex); + iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); + mutex_unlock(&mvm->mutex); +} + void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) { lockdep_assert_held(&mvm->mutex); @@ -1749,6 +1766,9 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) wiphy_work_init(&mvmvif->unblock_esr_tpt_wk, iwl_mvm_unblock_esr_tpt); + + wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk, + iwl_mvm_unblock_esr_tmp_non_bss); } static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, @@ -1899,6 +1919,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, &mvmvif->mlo_int_scan_wk); wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); + wiphy_delayed_work_cancel(mvm->hw->wiphy, + &mvmvif->unblock_esr_tmp_non_bss_wk); cancel_delayed_work_sync(&mvmvif->csa_work); } @@ -3303,7 +3325,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_TXPOWER) { IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n", bss_conf->txpower); - iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); + iwl_mvm_set_tx_power(mvm, bss_conf, bss_conf->txpower); } } @@ -4075,6 +4097,8 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, &mvmvif->mlo_int_scan_wk); wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); + wiphy_delayed_work_cancel(mvm->hw->wiphy, + &mvmvif->unblock_esr_tmp_non_bss_wk); /* No need for the periodic statistics anymore */ if (ieee80211_vif_is_mld(vif) && mvmvif->esr_active) @@ -4236,8 +4260,9 @@ int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value) } void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u32 changed) + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); if (changed & (IEEE80211_RC_BW_CHANGED | @@ -5067,7 +5092,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | IEEE80211_CHANCTX_CHANGE_RX_CHAINS | IEEE80211_CHANCTX_CHANGE_RADAR | - IEEE80211_CHANCTX_CHANGE_MIN_WIDTH)), + IEEE80211_CHANCTX_CHANGE_MIN_DEF)), "Cannot change PHY. Ref=%d, changed=0x%X\n", phy_ctxt->ref, changed)) return; @@ -5075,7 +5100,7 @@ void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, guard(mvm)(mvm); /* we are only changing the min_width, may be a noop */ - if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) { + if (changed == IEEE80211_CHANCTX_CHANGE_MIN_DEF) { if (phy_ctxt->width == def->width) return; @@ -6562,7 +6587,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, .release_buffered_frames = iwl_mvm_mac_release_buffered_frames, .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, - .sta_rc_update = iwl_mvm_sta_rc_update, + .link_sta_rc_update = iwl_mvm_sta_rc_update, .conf_tx = iwl_mvm_mac_conf_tx, .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index f2378e0fb2fb..a5c38f389c69 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -331,23 +331,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, if (ret) goto out; - /* Initialize rate control for the AP station, since we might be - * doing a link switch here - we cannot initialize it before since - * this needs the phy context assigned (and in FW?), and we cannot - * do it later because it needs to be initialized as soon as we're - * able to TX on the link, i.e. when active. + /* + * if link switching (link not active yet) we'll activate it in + * firmware later on link-info change, which mac80211 guarantees + * for link switch after the stations are set up */ - if (mvmvif->ap_sta) { - struct ieee80211_link_sta *link_sta; - - rcu_read_lock(); - link_sta = rcu_dereference(mvmvif->ap_sta->link[link_id]); - - if (!WARN_ON_ONCE(!link_sta)) - iwl_mvm_rs_rate_init(mvm, vif, mvmvif->ap_sta, - link_conf, link_sta, - phy_ctxt->channel->band); - rcu_read_unlock(); + if (ieee80211_vif_link_active(vif, link_conf->link_id)) { + ret = iwl_mvm_link_changed(mvm, vif, link_conf, + LINK_CONTEXT_MODIFY_ACTIVE | + LINK_CONTEXT_MODIFY_RATES_INFO, + true); + if (ret) + goto out; } if (vif->type == NL80211_IFTYPE_STATION) @@ -355,14 +350,6 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, link_conf, false); - /* then activate */ - ret = iwl_mvm_link_changed(mvm, vif, link_conf, - LINK_CONTEXT_MODIFY_ACTIVE | - LINK_CONTEXT_MODIFY_RATES_INFO, - true); - if (ret) - goto out; - /* * Power state must be updated before quotas, * otherwise fw will complain. @@ -775,6 +762,11 @@ iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!mvmvif->link[link_conf->link_id])) return; + /* not yet marked active in vif means during link switch */ + if (!ieee80211_vif_link_active(vif, link_conf->link_id) && + vif->cfg.assoc && mvmvif->link[link_conf->link_id]->phy_ctxt) + link_changes |= LINK_CONTEXT_MODIFY_ACTIVE; + has_he = link_conf->he_support && !iwlwifi_mod_params.disable_11ax; has_eht = link_conf->eht_support && !iwlwifi_mod_params.disable_11be; @@ -1038,7 +1030,7 @@ static void iwl_mvm_mld_link_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_TXPOWER) { IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d dBm\n", link_conf->txpower); - iwl_mvm_set_tx_power(mvm, vif, link_conf->txpower); + iwl_mvm_set_tx_power(mvm, link_conf, link_conf->txpower); } } @@ -1376,6 +1368,36 @@ iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw, return ret; } +#define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ) + +static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); + struct iwl_mvm_vif *mvmvif; + int ret; + + IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n", + type); + + if (IS_ERR_OR_NULL(bss_vif) || + !(type == NL80211_IFTYPE_AP || + type == NL80211_IFTYPE_P2P_GO || + type == NL80211_IFTYPE_P2P_CLIENT)) + return; + + mvmvif = iwl_mvm_vif_from_mac80211(bss_vif); + ret = iwl_mvm_block_esr_sync(mvm, bss_vif, + IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); + if (ret) + return; + + wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy, + &mvmvif->unblock_esr_tmp_non_bss_wk, + IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT); +} + const struct ieee80211_ops iwl_mvm_mld_hw_ops = { .tx = iwl_mvm_mac_tx, .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, @@ -1401,7 +1423,7 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = { .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, .release_buffered_frames = iwl_mvm_mac_release_buffered_frames, .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, - .sta_rc_update = iwl_mvm_sta_rc_update, + .link_sta_rc_update = iwl_mvm_sta_rc_update, .conf_tx = iwl_mvm_mld_mac_conf_tx, .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx, @@ -1472,4 +1494,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = { .change_sta_links = iwl_mvm_mld_change_sta_links, .can_activate_links = iwl_mvm_mld_can_activate_links, .can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm, + .prep_add_interface = iwl_mvm_mld_prep_add_interface, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c index 28a9d90ad1cd..99eb1e1db1bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c @@ -1182,6 +1182,9 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm, link_sta_added_to_fw |= BIT(link_id); iwl_mvm_rs_add_sta_link(mvm, mvm_sta_link); + + iwl_mvm_rs_rate_init(mvm, vif, sta, link_conf, link_sta, + link_conf->chanreq.oper.chan->band); } if (sta_mask_added) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index ef07cff203b0..5aa48c77b054 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -361,6 +361,9 @@ struct iwl_mvm_vif_link_info { * @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is * preventing EMLSR * @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR + * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link + * is preventing EMLSR. This is a temporary blocking that is set when there + * is an indication that a non-BSS interface is to be added. * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR * due to low RSSI. @@ -379,6 +382,7 @@ enum iwl_mvm_esr_state { IWL_MVM_ESR_BLOCKED_FW = 0x8, IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10, IWL_MVM_ESR_BLOCKED_ROC = 0x20, + IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40, IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000, IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000, IWL_MVM_ESR_EXIT_COEX = 0x40000, @@ -452,6 +456,8 @@ struct iwl_mvm_esr_exit { * @prevent_esr_done_wk: work that should be done when esr prevention ends. * @mlo_int_scan_wk: work for the internal MLO scan. * @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough. + * @unblock_esr_tmp_non_bss_wk: work for removing the + * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR. * @roc_activity: currently running ROC activity for this vif (or * ROC_NUM_ACTIVITIES if no activity is running). * @session_prot_connection_loss: the connection was lost due to session @@ -588,6 +594,7 @@ struct iwl_mvm_vif { struct wiphy_delayed_work prevent_esr_done_wk; struct wiphy_delayed_work mlo_int_scan_wk; struct wiphy_work unblock_esr_tpt_wk; + struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk; struct iwl_mvm_vif_link_info deflink; struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS]; @@ -773,7 +780,6 @@ struct iwl_mvm_tcm { * @head_sn: reorder window head sn * @num_stored: number of mpdus stored in the buffer * @queue: queue of this reorder buffer - * @last_amsdu: track last ASMDU SN for duplication detection * @valid: reordering is valid for this queue * @lock: protect reorder buffer internal state */ @@ -781,7 +787,6 @@ struct iwl_mvm_reorder_buffer { u16 head_sn; u16 num_stored; int queue; - u16 last_amsdu; bool valid; spinlock_t lock; } ____cacheline_aligned_in_smp; @@ -1584,8 +1589,7 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_CSUM_SUPPORT) && - !IWL_MVM_HW_CSUM_DISABLE; + IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); } static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm) @@ -2914,7 +2918,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw, bool more_data); int iwl_mvm_mac_set_rts_threshold(struct ieee80211_hw *hw, u32 value); void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u32 changed); + struct ieee80211_link_sta *link_sta, u32 changed); void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info); @@ -2982,7 +2986,8 @@ void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool iwl_mvm_have_links_same_channel(struct iwl_mvm_vif *vif1, struct iwl_mvm_vif *vif2); bool iwl_mvm_vif_is_active(struct iwl_mvm_vif *mvmvif); -int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, +int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, + struct ieee80211_bss_conf *bss_conf, s16 tx_power); int iwl_mvm_set_hw_timestamp(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 05715e5af6ab..de5ac000272e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -440,12 +440,6 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, mvmsta = iwl_mvm_sta_from_mac80211(sta); - if (!mvmsta) { - IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n", - notif->sta_id); - goto out; - } - flags = le32_to_cpu(notif->flags); mvm_link_sta = rcu_dereference(mvmsta->link[link_sta->link_id]); @@ -615,11 +609,8 @@ void iwl_mvm_rs_fw_rate_init(struct iwl_mvm *mvm, int cmd_ver; int ret; - /* Enable external EHT LTF only for GL device and if there's - * mutual support by AP and client - */ - if (CSR_HW_REV_TYPE(mvm->trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && - sband_eht_cap && + /* Enable extra EHT LTF if there's mutual support by AP and client */ + if (sband_eht_cap && sband_eht_cap->eht_cap_elem.phy_cap_info[5] & IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF && link_sta->eht_cap.has_eht && diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 65f8933c34b4..a2f16bfaec44 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -773,9 +773,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, return false; } - rcu_read_lock(); sta_mask = iwl_mvm_sta_fw_id_mask(mvm, sta, -1); - rcu_read_unlock(); if (IWL_FW_CHECK(mvm, tid != baid_data->tid || @@ -814,7 +812,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, if (!buffer->num_stored && ieee80211_sn_less(sn, nssn)) { if (!amsdu || last_subframe) buffer->head_sn = nssn; - /* No need to update AMSDU last SN - we are moving the head */ + spin_unlock_bh(&buffer->lock); return false; } @@ -831,7 +829,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, if (!amsdu || last_subframe) buffer->head_sn = ieee80211_sn_inc(buffer->head_sn); - /* No need to update AMSDU last SN - we are moving the head */ spin_unlock_bh(&buffer->lock); return false; } @@ -841,9 +838,6 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, __skb_queue_tail(&entries[index].frames, skb); buffer->num_stored++; - if (amsdu) - buffer->last_amsdu = sn; - /* * We cannot trust NSSN for AMSDU sub-frames that are not the last. * The reason is that NSSN advances on the first sub-frame, and may diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index b6c99cd6d9e5..9d05c344d967 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -4328,7 +4328,10 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, unsigned int wdg_timeout = iwl_mvm_get_wd_timeout(mvm, vif); bool mld = iwl_mvm_has_mld_api(mvm->fw); - u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK; + u32 type = IWL_STA_LINK; + + if (mld) + type = STATION_TYPE_PEER; ret = iwl_mvm_allocate_int_sta(mvm, sta, 0, NL80211_IFTYPE_UNSPECIFIED, type); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 9fe050f0ddc1..1ef14340953c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -2351,6 +2351,10 @@ void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, txq_write_ptr = txq->write_ptr; spin_unlock(&txq->lock); + /* There is nothing to do if we are flushing an empty queue */ + if (is_flush && txq_write_ptr == txq_read_ptr) + goto out; + read_ptr = iwl_txq_get_cmd_index(txq, txq_read_ptr); if (!test_bit(txq_id, trans_pcie->txqs.queue_used)) { diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c index d33a994906a7..27f44a9f0bc1 100644 --- a/drivers/net/wireless/intersil/p54/p54spi.c +++ b/drivers/net/wireless/intersil/p54/p54spi.c @@ -624,7 +624,7 @@ static int p54spi_probe(struct spi_device *spi) gpio_direction_input(p54spi_gpio_irq); ret = request_irq(gpio_to_irq(p54spi_gpio_irq), - p54spi_interrupt, 0, "p54spi", + p54spi_interrupt, IRQF_NO_AUTOEN, "p54spi", priv->spi); if (ret < 0) { dev_err(&priv->spi->dev, "request_irq() failed"); @@ -633,8 +633,6 @@ static int p54spi_probe(struct spi_device *spi) irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); - disable_irq(gpio_to_irq(p54spi_gpio_irq)); - INIT_WORK(&priv->work, p54spi_work); init_completion(&priv->fw_comp); INIT_LIST_HEAD(&priv->tx_pending); diff --git a/drivers/net/wireless/marvell/libertas/Kconfig b/drivers/net/wireless/marvell/libertas/Kconfig index 36b234bc5be8..caf8bc231b2e 100644 --- a/drivers/net/wireless/marvell/libertas/Kconfig +++ b/drivers/net/wireless/marvell/libertas/Kconfig @@ -3,7 +3,6 @@ config LIBERTAS tristate "Marvell 8xxx Libertas WLAN driver support" depends on USB || MMC || SPI depends on CFG80211 - select LIB80211 select FW_LOADER help A library for Marvell Libertas 8xxx devices. diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index afe9bcd3ad46..2e2c193716d9 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len) */ static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_chan_def *chandef) { struct lbs_private *priv = wiphy_priv(wiphy); diff --git a/drivers/net/wireless/marvell/libertas/mesh.h b/drivers/net/wireless/marvell/libertas/mesh.h index 44c4cd0230a8..e37db10e82a9 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.h +++ b/drivers/net/wireless/marvell/libertas/mesh.h @@ -7,7 +7,6 @@ #include <net/iw_handler.h> -#include <net/lib80211.h> #include "host.h" #include "dev.h" diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 1cff001bdc51..b30ed321c625 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -938,8 +938,10 @@ void mwifiex_process_assoc_resp(struct mwifiex_adapter *adapter) assoc_resp.links[0].bss = priv->req_bss; assoc_resp.buf = priv->assoc_rsp_buf; assoc_resp.len = priv->assoc_rsp_size; + wiphy_lock(priv->wdev.wiphy); cfg80211_rx_assoc_resp(priv->netdev, &assoc_resp); + wiphy_unlock(priv->wdev.wiphy); priv->assoc_rsp_size = 0; } } diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index d03129d5d24e..4a96281792cc 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -875,7 +875,7 @@ struct mwifiex_ietypes_chanstats { struct mwifiex_ie_types_wildcard_ssid_params { struct mwifiex_ie_types_header header; u8 max_ssid_length; - u8 ssid[1]; + u8 ssid[]; } __packed; #define TSF_DATA_SIZE 8 diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 516159b721d3..74747d3a379a 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -8,7 +8,7 @@ #ifndef _MWIFIEX_IOCTL_H_ #define _MWIFIEX_IOCTL_H_ -#include <net/lib80211.h> +#define NUM_WEP_KEYS 4 enum { MWIFIEX_SCAN_TYPE_UNCHANGED = 0, diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index 6d8f1d1d7ca4..5a1a0287c1d5 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -663,7 +663,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, bool enable_data = true; u16 cap_info, status_code, aid; const u8 *ie_ptr; - struct ieee80211_ht_operation *assoc_resp_ht_oper; if (!priv->attempted_bss_desc) { mwifiex_dbg(priv->adapter, ERROR, @@ -779,14 +778,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer, priv->assoc_rsp_size - sizeof(struct ieee_types_assoc_rsp)); - if (ie_ptr) { - assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr - + sizeof(struct ieee_types_header)); - priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param; - priv->ht_param_present = true; - } else { - priv->ht_param_present = false; - } + + priv->ht_param_present = ie_ptr ? true : false; mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 96d1f6039fbc..855019fe5485 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1679,7 +1679,8 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter) } ret = devm_request_irq(dev, adapter->irq_wakeup, - mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW, + mwifiex_irq_wakeup_handler, + IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN, "wifi_wake", adapter); if (ret) { dev_err(dev, "Failed to request irq_wakeup %d (%d)\n", @@ -1687,7 +1688,6 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter) goto err_exit; } - disable_irq(adapter->irq_wakeup); if (device_init_wakeup(dev, true)) { dev_err(dev, "fail to init wakeup for mwifiex\n"); goto err_exit; diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 566adce3413c..0674dcf7a537 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -19,7 +19,6 @@ #include <linux/if_arp.h> #include <linux/etherdevice.h> #include <net/sock.h> -#include <net/lib80211.h> #include <linux/vmalloc.h> #include <linux/firmware.h> #include <linux/ctype.h> @@ -574,7 +573,6 @@ struct mwifiex_private { u16 listen_interval; u16 atim_window; u8 adhoc_channel; - u8 adhoc_is_link_sensed; u8 adhoc_state; struct mwifiex_802_11_security sec_info; struct mwifiex_wep_key wep_key[NUM_WEP_KEYS]; @@ -683,7 +681,6 @@ struct mwifiex_private { struct mwifiex_ds_mem_rw mem_rw; struct sk_buff_head bypass_txq; struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX]; - u8 assoc_resp_ht_param; bool ht_param_present; }; @@ -802,7 +799,6 @@ struct mwifiex_auto_tdls_peer { unsigned long rssi_jiffies; u8 failure_count; u8 do_discover; - u8 do_setup; }; #define MWIFIEX_TYPE_AGGR_DATA_V2 11 diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index b5f3821a6a8f..400348abeee5 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -177,17 +177,14 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code, priv->is_data_rate_auto = true; priv->data_rate = 0; - priv->assoc_resp_ht_param = 0; priv->ht_param_present = false; if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) mwifiex_hist_data_reset(priv); - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { + if (priv->bss_mode == NL80211_IFTYPE_ADHOC) priv->adhoc_state = ADHOC_IDLE; - priv->adhoc_is_link_sensed = false; - } /* * Memorize the previous SSID and BSSID so @@ -843,7 +840,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_ADHOC_BCN_LOST: mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n"); - priv->adhoc_is_link_sensed = false; mwifiex_clean_txrx(priv); mwifiex_stop_net_dev_queue(priv->netdev, adapter); if (netif_carrier_ok(priv->netdev)) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index d3cba6895f8c..e06a0622973e 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -351,8 +351,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, goto done; } - priv->adhoc_is_link_sensed = false; - ret = mwifiex_check_network_compatibility(priv, bss_desc); mwifiex_stop_net_dev_queue(priv->netdev, adapter); diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 7823e67694e8..0a5f340876c3 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -1306,7 +1306,6 @@ int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb) peer->mac_addr, NL80211_TDLS_SETUP, 0, GFP_ATOMIC); - peer->do_setup = false; priv->check_tdls_tx = false; } else if (peer->failure_count < MWIFIEX_TDLS_MAX_FAIL_COUNT && @@ -1465,7 +1464,6 @@ void mwifiex_check_auto_tdls(struct timer_list *t) tdls_peer->failure_count < MWIFIEX_TDLS_MAX_FAIL_COUNT) { priv->check_tdls_tx = true; - tdls_peer->do_setup = true; mwifiex_dbg(priv->adapter, INFO, "check TDLS with peer=%pM\t" "rssi=%d\n", tdls_peer->mac_addr, diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 42c04bf858da..1f1f6280a0f2 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -494,7 +494,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, } } + wiphy_lock(priv->wdev.wiphy); cfg80211_rx_mlme_mgmt(priv->netdev, skb->data, pkt_len); + wiphy_unlock(priv->wdev.wiphy); } if (priv->adapter->host_mlme_enabled && diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index d75e8dea1fbd..c6f498fc81ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -1163,9 +1163,10 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) static void mt7915_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = phy->dev; struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; @@ -1709,7 +1710,7 @@ const struct ieee80211_ops mt7915_ops = { .stop_ap = mt7915_stop_ap, .sta_state = mt76_sta_state, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, - .sta_rc_update = mt7915_sta_rc_update, + .link_sta_rc_update = mt7915_sta_rc_update, .set_key = mt7915_set_key, .ampdu_action = mt7915_ampdu_action, .set_rts_threshold = mt7915_set_rts_threshold, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index 39f071ece35e..2b34ae5e0cb5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -1060,9 +1060,10 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta) static void mt7996_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = phy->dev; @@ -1472,7 +1473,7 @@ const struct ieee80211_ops mt7996_ops = { .sta_add = mt7996_sta_add, .sta_remove = mt7996_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, - .sta_rc_update = mt7996_sta_rc_update, + .link_sta_rc_update = mt7996_sta_rc_update, .set_key = mt7996_set_key, .ampdu_action = mt7996_ampdu_action, .set_rts_threshold = mt7996_set_rts_threshold, diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index eb37b228d54e..e96736cc7259 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl) } static int set_channel(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_chan_def *chandef) { struct wilc *wl = wiphy_priv(wiphy); @@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, struct wilc_vif *vif = netdev_priv(dev); int ret; - ret = set_channel(wiphy, &settings->chandef); + ret = set_channel(wiphy, dev, &settings->chandef); if (ret != 0) netdev_err(dev, "Error in setting channel\n"); @@ -1757,57 +1758,10 @@ void wlan_deinit_locks(struct wilc *wilc) cleanup_srcu_struct(&wilc->srcu); } -int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, - const struct wilc_hif_func *ops) -{ - struct wilc *wl; - int ret, i; - - wl = wilc_create_wiphy(dev); - if (!wl) - return -EINVAL; - - wlan_init_locks(wl); - - ret = wilc_wlan_cfg_init(wl); - if (ret) - goto free_wl; - - *wilc = wl; - wl->io_type = io_type; - wl->hif_func = ops; - - for (i = 0; i < NQUEUES; i++) - INIT_LIST_HEAD(&wl->txq[i].txq_head.list); - - INIT_LIST_HEAD(&wl->rxq_head.list); - INIT_LIST_HEAD(&wl->vif_list); - - wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, - wiphy_name(wl->wiphy)); - if (!wl->hif_workqueue) { - ret = -ENOMEM; - goto free_cfg; - } - - return 0; - -free_cfg: - wilc_wlan_cfg_deinit(wl); - -free_wl: - wlan_deinit_locks(wl); - wiphy_unregister(wl->wiphy); - wiphy_free(wl->wiphy); - return ret; -} -EXPORT_SYMBOL_GPL(wilc_cfg80211_init); - -struct wilc *wilc_create_wiphy(struct device *dev) +static struct wilc *wilc_create_wiphy(struct device *dev) { struct wiphy *wiphy; struct wilc *wl; - int ret; wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl)); if (!wiphy) @@ -1850,17 +1804,66 @@ struct wilc *wilc_create_wiphy(struct device *dev) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT); wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->features |= NL80211_FEATURE_SAE; set_wiphy_dev(wiphy, dev); wl->wiphy = wiphy; - ret = wiphy_register(wiphy); - if (ret) { - wiphy_free(wiphy); - return NULL; - } return wl; } +int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, + const struct wilc_hif_func *ops) +{ + struct wilc *wl; + int ret, i; + + wl = wilc_create_wiphy(dev); + if (!wl) + return -EINVAL; + + wlan_init_locks(wl); + + ret = wilc_wlan_cfg_init(wl); + if (ret) + goto free_wl; + + *wilc = wl; + wl->io_type = io_type; + wl->hif_func = ops; + + for (i = 0; i < NQUEUES; i++) + INIT_LIST_HEAD(&wl->txq[i].txq_head.list); + + INIT_LIST_HEAD(&wl->rxq_head.list); + INIT_LIST_HEAD(&wl->vif_list); + + wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, + wiphy_name(wl->wiphy)); + if (!wl->hif_workqueue) { + ret = -ENOMEM; + goto free_cfg; + } + + return 0; + +free_cfg: + wilc_wlan_cfg_deinit(wl); + +free_wl: + wlan_deinit_locks(wl); + wiphy_free(wl->wiphy); + return ret; +} +EXPORT_SYMBOL_GPL(wilc_cfg80211_init); + +int wilc_cfg80211_register(struct wilc *wilc) +{ + /* WPA3/SAE supported only on WILC1000 */ + if (is_wilc1000(wilc->chipid)) + wilc->wiphy->features |= NL80211_FEATURE_SAE; + + return wiphy_register(wilc->wiphy); +} +EXPORT_SYMBOL_GPL(wilc_cfg80211_register); + int wilc_init_host_int(struct net_device *net) { int ret; diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.h b/drivers/net/wireless/microchip/wilc1000/cfg80211.h index 8c65951cfaf9..2dc9c1c42d60 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.h +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.h @@ -10,7 +10,7 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, const struct wilc_hif_func *ops); -struct wilc *wilc_create_wiphy(struct device *dev); +int wilc_cfg80211_register(struct wilc *wilc); void wilc_deinit_host_int(struct net_device *net); int wilc_init_host_int(struct net_device *net); void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 9ecf3fb29b55..7e84fc0fd911 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -23,6 +23,12 @@ #define __WILC1000_FW(api) WILC1000_FW_PREFIX #api ".bin" #define WILC1000_FW(api) __WILC1000_FW(api) +#define WILC3000_API_VER 1 + +#define WILC3000_FW_PREFIX "atmel/wilc3000_wifi_firmware-" +#define __WILC3000_FW(api) WILC3000_FW_PREFIX #api ".bin" +#define WILC3000_FW(api) __WILC3000_FW(api) + static irqreturn_t isr_uh_routine(int irq, void *user_data) { struct wilc *wilc = user_data; @@ -195,20 +201,24 @@ static int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; - int chip_id; const struct firmware *wilc_fw; + char *firmware; int ret; - chip_id = wilc_get_chipid(wilc, false); + if (is_wilc1000(wilc->chipid)) + firmware = WILC1000_FW(WILC1000_API_VER); + else if (is_wilc3000(wilc->chipid)) + firmware = WILC3000_FW(WILC3000_API_VER); + else + return -EINVAL; - netdev_info(dev, "ChipID [%x] loading firmware [%s]\n", chip_id, - WILC1000_FW(WILC1000_API_VER)); + netdev_info(dev, "WILC%d loading firmware [%s]\n", + is_wilc1000(wilc->chipid) ? 1000 : 3000, + firmware); - ret = request_firmware(&wilc_fw, WILC1000_FW(WILC1000_API_VER), - wilc->dev); + ret = request_firmware(&wilc_fw, firmware, wilc->dev); if (ret != 0) { - netdev_err(dev, "%s - firmware not available\n", - WILC1000_FW(WILC1000_API_VER)); + netdev_err(dev, "%s - firmware not available\n", firmware); return -EINVAL; } wilc->firmware = wilc_fw; @@ -233,7 +243,7 @@ static int wilc_start_firmware(struct net_device *dev) return 0; } -static int wilc1000_firmware_download(struct net_device *dev) +static int wilc_firmware_download(struct net_device *dev) { struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -528,7 +538,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) if (ret) goto fail_irq_enable; - ret = wilc1000_firmware_download(dev); + ret = wilc_firmware_download(dev); if (ret) goto fail_irq_enable; @@ -608,6 +618,9 @@ static int wilc_mac_open(struct net_device *ndev) return ret; } + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, + vif->idx); + netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr); ret = wilc_set_mac_address(vif, ndev->dev_addr); if (ret) { @@ -618,9 +631,6 @@ static int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, - vif->idx); - mgmt_regs.interface_stypes = vif->mgmt_reg_stypes; /* so we detect a change */ vif->mgmt_reg_stypes = 0; @@ -1014,3 +1024,4 @@ EXPORT_SYMBOL_GPL(wilc_netdev_ifc_init); MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER)); +MODULE_FIRMWARE(WILC3000_FW(WILC3000_API_VER)); diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index b4da05d5a498..5262c8846c13 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -182,6 +182,14 @@ static int wilc_sdio_probe(struct sdio_func *func, wilc_sdio_init(wilc, false); + ret = wilc_get_chipid(wilc); + if (ret) + goto dispose_irq; + + ret = wilc_cfg80211_register(wilc); + if (ret) + goto dispose_irq; + ret = wilc_load_mac_from_nv(wilc); if (ret) { pr_err("Can not retrieve MAC address from chip\n"); @@ -667,7 +675,6 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) struct wilc_sdio *sdio_priv = wilc->bus_data; struct sdio_cmd52 cmd; int loop, ret; - u32 chipid; /** * function 0 csa enable @@ -756,18 +763,6 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) return ret; } - /** - * make sure can read back chip id correctly - **/ - if (!resume) { - ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid); - if (ret) { - dev_err(&func->dev, "Fail cmd read chip id...\n"); - return ret; - } - dev_err(&func->dev, "chipid (%08x)\n", chipid); - } - sdio_priv->isinit = true; return 0; } @@ -815,13 +810,19 @@ static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG; } else { cmd.function = 0; - cmd.address = WILC_SDIO_IRQ_FLAG_REG; + cmd.address = is_wilc1000(wilc->chipid) ? + WILC1000_SDIO_IRQ_FLAG_REG : + WILC3000_SDIO_IRQ_FLAG_REG; } cmd.raw = 0; cmd.read_write = 0; cmd.data = 0; wilc_sdio_cmd52(wilc, &cmd); irq_flags = cmd.data; + + if (sdio_priv->irq_gpio) + irq_flags &= is_wilc1000(wilc->chipid) ? 0x1f : 0x0f; + tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data); if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags)) @@ -843,22 +844,56 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) if (sdio_priv->irq_gpio) reg = val & (BIT(MAX_NUM_INT) - 1); - /* select VMM table 0 */ - if (val & SEL_VMM_TBL0) - reg |= BIT(5); - /* select VMM table 1 */ - if (val & SEL_VMM_TBL1) - reg |= BIT(6); - /* enable VMM */ - if (val & EN_VMM) - reg |= BIT(7); + if (is_wilc1000(wilc->chipid)) { + /* select VMM table 0 */ + if (val & SEL_VMM_TBL0) + reg |= BIT(5); + /* select VMM table 1 */ + if (val & SEL_VMM_TBL1) + reg |= BIT(6); + /* enable VMM */ + if (val & EN_VMM) + reg |= BIT(7); + } else { + if (sdio_priv->irq_gpio && reg) { + struct sdio_cmd52 cmd; + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = WILC3000_SDIO_IRQ_FLAG_REG; + cmd.data = reg; + + ret = wilc_sdio_cmd52(wilc, &cmd); + if (ret) { + dev_err(&func->dev, + "Failed cmd52, set 0xfe data (%d) ...\n", + __LINE__); + return ret; + } + } + + reg = 0; + /* select VMM table 0 */ + if (val & SEL_VMM_TBL0) + reg |= BIT(0); + /* select VMM table 1 */ + if (val & SEL_VMM_TBL1) + reg |= BIT(1); + /* enable VMM */ + if (val & EN_VMM) + reg |= BIT(2); + } + if (reg) { struct sdio_cmd52 cmd; cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; - cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; + cmd.address = is_wilc1000(wilc->chipid) ? + WILC1000_SDIO_IRQ_CLEAR_FLAG_REG : + WILC3000_SDIO_VMM_TBL_CTRL_REG; cmd.data = reg; ret = wilc_sdio_cmd52(wilc, &cmd); @@ -979,17 +1014,15 @@ static int wilc_sdio_suspend(struct device *dev) if (!IS_ERR(wilc->rtc_clk)) clk_disable_unprepare(wilc->rtc_clk); - host_sleep_notify(wilc); - - wilc_sdio_disable_interrupt(wilc); - - ret = wilc_sdio_reset(wilc); + ret = host_sleep_notify(wilc); if (ret) { - dev_err(&func->dev, "Fail reset sdio\n"); + clk_prepare_enable(wilc->rtc_clk); return ret; } - return 0; + wilc_sdio_disable_interrupt(wilc); + + return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); } static int wilc_sdio_resume(struct device *dev) @@ -1008,9 +1041,7 @@ static int wilc_sdio_resume(struct device *dev) wilc_sdio_init(wilc, true); wilc_sdio_enable_interrupt(wilc); - host_wakeup_notify(wilc); - - return 0; + return host_wakeup_notify(wilc); } static const struct of_device_id wilc_of_match[] = { diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 05b577b1068e..ce2a9cdd6aa7 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -245,7 +245,11 @@ static int wilc_bus_probe(struct spi_device *spi) if (ret) goto power_down; - ret = wilc_validate_chipid(wilc); + ret = wilc_get_chipid(wilc); + if (ret) + goto power_down; + + ret = wilc_cfg80211_register(wilc); if (ret) goto power_down; @@ -1229,7 +1233,7 @@ static int wilc_validate_chipid(struct wilc *wilc) dev_err(&spi->dev, "Fail cmd read chip id...\n"); return ret; } - if (!is_wilc1000(chipid)) { + if (!is_wilc1000(chipid) && !is_wilc3000(chipid)) { dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid); return -ENODEV; } diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index 533939e71534..9d80adc45d6b 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -12,20 +12,6 @@ #define WAKE_UP_TRIAL_RETRY 10000 -static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire) -{ - mutex_lock(&wilc->hif_cs); - if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) - chip_wakeup(wilc); -} - -static inline void release_bus(struct wilc *wilc, enum bus_release release) -{ - if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode) - chip_allow_sleep(wilc); - mutex_unlock(&wilc->hif_cs); -} - static void wilc_wlan_txq_remove(struct wilc *wilc, u8 q_num, struct txq_entry_t *tqe) { @@ -555,7 +541,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) return rqe; } -void chip_allow_sleep(struct wilc *wilc) +static int chip_allow_sleep_wilc1000(struct wilc *wilc) { u32 reg = 0; const struct wilc_hif_func *hif_func = wilc->hif_func; @@ -584,7 +570,7 @@ void chip_allow_sleep(struct wilc *wilc) while (--trials) { ret = hif_func->hif_read_reg(wilc, to_host_from_fw_reg, ®); if (ret) - return; + return ret; if ((reg & to_host_from_fw_bit) == 0) break; } @@ -594,28 +580,62 @@ void chip_allow_sleep(struct wilc *wilc) /* Clear bit 1 */ ret = hif_func->hif_read_reg(wilc, wakeup_reg, ®); if (ret) - return; + return ret; if (reg & wakeup_bit) { reg &= ~wakeup_bit; ret = hif_func->hif_write_reg(wilc, wakeup_reg, reg); if (ret) - return; + return ret; } ret = hif_func->hif_read_reg(wilc, from_host_to_fw_reg, ®); if (ret) - return; + return ret; if (reg & from_host_to_fw_bit) { reg &= ~from_host_to_fw_bit; ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, reg); if (ret) - return; + return ret; + } + return 0; +} + +static int chip_allow_sleep_wilc3000(struct wilc *wilc) +{ + u32 reg = 0; + int ret; + const struct wilc_hif_func *hif_func = wilc->hif_func; + + if (wilc->io_type == WILC_HIF_SDIO) { + ret = hif_func->hif_read_reg(wilc, WILC_SDIO_WAKEUP_REG, ®); + if (ret) + return ret; + ret = hif_func->hif_write_reg(wilc, WILC_SDIO_WAKEUP_REG, + reg & ~WILC_SDIO_WAKEUP_BIT); + if (ret) + return ret; + } else { + ret = hif_func->hif_read_reg(wilc, WILC_SPI_WAKEUP_REG, ®); + if (ret) + return ret; + ret = hif_func->hif_write_reg(wilc, WILC_SPI_WAKEUP_REG, + reg & ~WILC_SPI_WAKEUP_BIT); + if (ret) + return ret; } + return 0; +} + +static int chip_allow_sleep(struct wilc *wilc) +{ + if (is_wilc1000(wilc->chipid)) + return chip_allow_sleep_wilc1000(wilc); + else + return chip_allow_sleep_wilc3000(wilc); } -EXPORT_SYMBOL_GPL(chip_allow_sleep); -void chip_wakeup(struct wilc *wilc) +static int chip_wakeup_wilc1000(struct wilc *wilc) { u32 ret = 0; u32 clk_status_val = 0, trials = 0; @@ -627,15 +647,15 @@ void chip_wakeup(struct wilc *wilc) if (wilc->io_type == WILC_HIF_SDIO) { wakeup_reg = WILC_SDIO_WAKEUP_REG; wakeup_bit = WILC_SDIO_WAKEUP_BIT; - clk_status_reg = WILC_SDIO_CLK_STATUS_REG; - clk_status_bit = WILC_SDIO_CLK_STATUS_BIT; + clk_status_reg = WILC1000_SDIO_CLK_STATUS_REG; + clk_status_bit = WILC1000_SDIO_CLK_STATUS_BIT; from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG; from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT; } else { wakeup_reg = WILC_SPI_WAKEUP_REG; wakeup_bit = WILC_SPI_WAKEUP_BIT; - clk_status_reg = WILC_SPI_CLK_STATUS_REG; - clk_status_bit = WILC_SPI_CLK_STATUS_BIT; + clk_status_reg = WILC1000_SPI_CLK_STATUS_REG; + clk_status_bit = WILC1000_SPI_CLK_STATUS_BIT; from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG; from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT; } @@ -644,20 +664,20 @@ void chip_wakeup(struct wilc *wilc) ret = hif_func->hif_write_reg(wilc, from_host_to_fw_reg, from_host_to_fw_bit); if (ret) - return; + return ret; /* Set wake-up bit */ ret = hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_bit); if (ret) - return; + return ret; while (trials < WAKE_UP_TRIAL_RETRY) { ret = hif_func->hif_read_reg(wilc, clk_status_reg, &clk_status_val); if (ret) { pr_err("Bus error %d %x\n", ret, clk_status_val); - return; + return ret; } if (clk_status_val & clk_status_bit) break; @@ -666,29 +686,135 @@ void chip_wakeup(struct wilc *wilc) } if (trials >= WAKE_UP_TRIAL_RETRY) { pr_err("Failed to wake-up the chip\n"); - return; + return -ETIMEDOUT; } /* Sometimes spi fail to read clock regs after reading * writing clockless registers */ if (wilc->io_type == WILC_HIF_SPI) wilc->hif_func->hif_reset(wilc); + + return 0; } -EXPORT_SYMBOL_GPL(chip_wakeup); -void host_wakeup_notify(struct wilc *wilc) +static int chip_wakeup_wilc3000(struct wilc *wilc) { - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_2, 1); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + u32 wakeup_reg_val, clk_status_reg_val, trials = 0; + u32 wakeup_reg, wakeup_bit; + u32 clk_status_reg, clk_status_bit; + int wake_seq_trials = 5; + const struct wilc_hif_func *hif_func = wilc->hif_func; + + if (wilc->io_type == WILC_HIF_SDIO) { + wakeup_reg = WILC_SDIO_WAKEUP_REG; + wakeup_bit = WILC_SDIO_WAKEUP_BIT; + clk_status_reg = WILC3000_SDIO_CLK_STATUS_REG; + clk_status_bit = WILC3000_SDIO_CLK_STATUS_BIT; + } else { + wakeup_reg = WILC_SPI_WAKEUP_REG; + wakeup_bit = WILC_SPI_WAKEUP_BIT; + clk_status_reg = WILC3000_SPI_CLK_STATUS_REG; + clk_status_bit = WILC3000_SPI_CLK_STATUS_BIT; + } + + hif_func->hif_read_reg(wilc, wakeup_reg, &wakeup_reg_val); + do { + hif_func->hif_write_reg(wilc, wakeup_reg, wakeup_reg_val | + wakeup_bit); + /* Check the clock status */ + hif_func->hif_read_reg(wilc, clk_status_reg, + &clk_status_reg_val); + + /* In case of clocks off, wait 1ms, and check it again. + * if still off, wait for another 1ms, for a total wait of 3ms. + * If still off, redo the wake up sequence + */ + while ((clk_status_reg_val & clk_status_bit) == 0 && + (++trials % 4) != 0) { + /* Wait for the chip to stabilize*/ + usleep_range(1000, 1100); + + /* Make sure chip is awake. This is an extra step that + * can be removed later to avoid the bus access + * overhead + */ + hif_func->hif_read_reg(wilc, clk_status_reg, + &clk_status_reg_val); + } + /* in case of failure, Reset the wakeup bit to introduce a new + * edge on the next loop + */ + if ((clk_status_reg_val & clk_status_bit) == 0) { + hif_func->hif_write_reg(wilc, wakeup_reg, + wakeup_reg_val & (~wakeup_bit)); + /* added wait before wakeup sequence retry */ + usleep_range(200, 300); + } + } while ((clk_status_reg_val & clk_status_bit) == 0 && wake_seq_trials-- > 0); + if (!wake_seq_trials) + dev_err(wilc->dev, "clocks still OFF. Wake up failed\n"); + + return 0; +} + +static int chip_wakeup(struct wilc *wilc) +{ + if (is_wilc1000(wilc->chipid)) + return chip_wakeup_wilc1000(wilc); + else + return chip_wakeup_wilc3000(wilc); +} + +static inline int acquire_bus(struct wilc *wilc, enum bus_acquire acquire) +{ + int ret = 0; + + mutex_lock(&wilc->hif_cs); + if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) { + ret = chip_wakeup(wilc); + if (ret) + mutex_unlock(&wilc->hif_cs); + } + + return ret; +} + +static inline int release_bus(struct wilc *wilc, enum bus_release release) +{ + int ret = 0; + + if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode) + ret = chip_allow_sleep(wilc); + mutex_unlock(&wilc->hif_cs); + + return ret; +} + +int host_wakeup_notify(struct wilc *wilc) +{ + int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + + if (ret) + return ret; + + wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ? + WILC1000_CORTUS_INTERRUPT_2 : + WILC3000_CORTUS_INTERRUPT_2, 1); + return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); } EXPORT_SYMBOL_GPL(host_wakeup_notify); -void host_sleep_notify(struct wilc *wilc) +int host_sleep_notify(struct wilc *wilc) { - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - wilc->hif_func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_1, 1); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + int ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + + if (ret) + return ret; + + wilc->hif_func->hif_write_reg(wilc, is_wilc1000(wilc->chipid) ? + WILC1000_CORTUS_INTERRUPT_1 : + WILC3000_CORTUS_INTERRUPT_1, 1); + return release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); } EXPORT_SYMBOL_GPL(host_sleep_notify); @@ -715,6 +841,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) int srcu_idx; u8 *txb = wilc->tx_buffer; struct wilc_vif *vif; + int rv; if (wilc->quit) goto out_update_cnt; @@ -785,7 +912,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) goto out_unlock; vmm_table[i] = 0x0; - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + goto out_unlock; + counter = 0; func = wilc->hif_func; do { @@ -818,19 +948,45 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) if (ret) break; - ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); - if (ret) - break; + if (is_wilc1000(wilc->chipid)) { + ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); + if (ret) + break; - do { - ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); + do { + ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); + if (ret) + break; + if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) { + entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg); + break; + } + } while (--timeout); + } else { + ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0); if (ret) break; - if (FIELD_GET(WILC_VMM_ENTRY_AVAILABLE, reg)) { - entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg); + + /* interrupt firmware */ + ret = func->hif_write_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, 1); + if (ret) break; - } - } while (--timeout); + + do { + ret = func->hif_read_reg(wilc, WILC_CORTUS_INTERRUPT_BASE, ®); + if (ret) + break; + if (reg == 0) { + /* Get the entries */ + ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); + if (ret) + break; + + entries = FIELD_GET(WILC_VMM_ENTRY_COUNT, reg); + break; + } + } while (--timeout); + } if (timeout <= 0) { ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x0); break; @@ -860,7 +1016,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) goto out_release_bus; } - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + if (ret) + goto out_unlock; offset = 0; i = 0; @@ -922,7 +1080,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) for (i = 0; i < NQUEUES; i++) wilc->txq[i].fw.count += ac_pkt_num_to_chip[i]; - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + goto out_unlock; ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); if (ret) @@ -931,7 +1091,9 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) ret = func->hif_block_tx_ext(wilc, 0, txb, offset); out_release_bus: - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + if (!ret && rv) + ret = rv; out_unlock: mutex_unlock(&wilc->txq_add_to_head_cs); @@ -1060,8 +1222,14 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) void wilc_handle_isr(struct wilc *wilc) { u32 int_status; + int ret; + + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) { + dev_err_ratelimited(wilc->dev, "Cannot acquire bus\n"); + return; + } - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); wilc->hif_func->hif_read_int(wilc, &int_status); if (int_status & DATA_INT_EXT) @@ -1070,7 +1238,9 @@ void wilc_handle_isr(struct wilc *wilc) if (!(int_status & (ALL_INT_EXT))) wilc_unknown_isr_ext(wilc); - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + ret = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + if (ret) + dev_err_ratelimited(wilc->dev, "Cannot release bus\n"); } EXPORT_SYMBOL_GPL(wilc_handle_isr); @@ -1082,6 +1252,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u8 *dma_buffer; int ret = 0; u32 reg = 0; + int rv; blksz = BIT(12); @@ -1092,7 +1263,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, offset = 0; pr_debug("%s: Downloading firmware size = %d\n", __func__, buffer_size); - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + return ret; wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); reg &= ~BIT(10); @@ -1101,11 +1274,17 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, if (reg & BIT(10)) pr_err("%s: Failed to reset\n", __func__); - release_bus(wilc, WILC_BUS_RELEASE_ONLY); + ret = release_bus(wilc, WILC_BUS_RELEASE_ONLY); + if (ret) + goto fail; + do { addr = get_unaligned_le32(&buffer[offset]); size = get_unaligned_le32(&buffer[offset + 4]); - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + goto fail; + offset += 8; while (((int)size) && (offset < buffer_size)) { if (size <= blksz) @@ -1123,7 +1302,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, offset += size2; size -= size2; } - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + if (!ret && rv) + ret = rv; if (ret) { pr_err("%s Bus error\n", __func__); @@ -1142,7 +1323,7 @@ fail: int wilc_wlan_start(struct wilc *wilc) { u32 reg = 0; - int ret; + int ret, rv; u32 chipid; if (wilc->io_type == WILC_HIF_SDIO) { @@ -1151,7 +1332,10 @@ int wilc_wlan_start(struct wilc *wilc) } else if (wilc->io_type == WILC_HIF_SPI) { reg = 1; } - acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); + if (ret) + return ret; + ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); if (ret) goto release; @@ -1160,6 +1344,9 @@ int wilc_wlan_start(struct wilc *wilc) if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num) reg |= WILC_HAVE_SDIO_IRQ_GPIO; + if (is_wilc3000(wilc->chipid)) + reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC; + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (ret) goto release; @@ -1182,16 +1369,18 @@ int wilc_wlan_start(struct wilc *wilc) wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); release: - release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return ret; + rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY); + return ret ? ret : rv; } int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) { u32 reg = 0; - int ret; + int ret, rv; - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + return ret; ret = wilc->hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, ®); if (ret) @@ -1227,9 +1416,9 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = 0; release: /* host comm is disabled - we can't issue sleep command anymore: */ - release_bus(wilc, WILC_BUS_RELEASE_ONLY); + rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return ret; + return ret ? ret : rv; } void wilc_wlan_cleanup(struct net_device *dev) @@ -1402,19 +1591,56 @@ int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, return ret; } +int wilc_get_chipid(struct wilc *wilc) +{ + u32 chipid = 0; + u32 rfrevid = 0; + + if (wilc->chipid == 0) { + wilc->hif_func->hif_read_reg(wilc, WILC3000_CHIP_ID, &chipid); + if (!is_wilc3000(chipid)) { + wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid); + wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID, + &rfrevid); + + if (!is_wilc1000(chipid)) { + wilc->chipid = 0; + return -EINVAL; + } + if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */ + if (rfrevid != 0x1) + chipid = WILC_1000_BASE_ID_2A_REV1; + } else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */ + if (rfrevid == 0x4) + chipid = WILC_1000_BASE_ID_2B_REV1; + else if (rfrevid != 0x3) + chipid = WILC_1000_BASE_ID_2B_REV2; + } + } + + wilc->chipid = chipid; + } + + return 0; +} +EXPORT_SYMBOL_GPL(wilc_get_chipid); + static int init_chip(struct net_device *dev) { - u32 chipid; u32 reg; - int ret = 0; + int ret, rv; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + return ret; - chipid = wilc_get_chipid(wilc, true); + ret = wilc_get_chipid(wilc); + if (ret) + goto release; - if ((chipid & 0xfff) != 0xa0) { + if ((wilc->chipid & 0xfff) != 0xa0) { ret = wilc->hif_func->hif_read_reg(wilc, WILC_CORTUS_RESET_MUX_SEL, ®); @@ -1439,46 +1665,35 @@ static int init_chip(struct net_device *dev) } } -release: - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - - return ret; -} - -u32 wilc_get_chipid(struct wilc *wilc, bool update) -{ - u32 chipid = 0; - u32 rfrevid = 0; - - if (wilc->chipid == 0 || update) { - wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid); - wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID, - &rfrevid); - if (!is_wilc1000(chipid)) { - wilc->chipid = 0; - return wilc->chipid; - } - if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */ - if (rfrevid != 0x1) - chipid = WILC_1000_BASE_ID_2A_REV1; - } else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */ - if (rfrevid == 0x4) - chipid = WILC_1000_BASE_ID_2B_REV1; - else if (rfrevid != 0x3) - chipid = WILC_1000_BASE_ID_2B_REV2; + if (is_wilc3000(wilc->chipid)) { + ret = wilc->hif_func->hif_read_reg(wilc, WILC3000_BOOTROM_STATUS, ®); + if (ret) { + netdev_err(dev, "failed to read WILC3000 BootROM status register\n"); + goto release; } - wilc->chipid = chipid; + ret = wilc->hif_func->hif_write_reg(wilc, WILC3000_CORTUS_BOOT_REGISTER_2, + WILC_CORTUS_BOOT_FROM_IRAM); + if (ret) { + netdev_err(dev, "failed to write WILC3000 Boot register\n"); + goto release; + } } - return wilc->chipid; + +release: + rv = release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + + return ret ? ret : rv; } int wilc_load_mac_from_nv(struct wilc *wl) { - int ret = -EINVAL; + int ret, rv; unsigned int i; - acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP); + ret = acquire_bus(wl, WILC_BUS_ACQUIRE_AND_WAKEUP); + if (ret) + return ret; for (i = 0; i < WILC_NVMEM_MAX_NUM_BANK; i++) { int bank_offset = get_bank_offset_from_bank_index(i); @@ -1517,14 +1732,14 @@ int wilc_load_mac_from_nv(struct wilc *wl) break; } - release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + rv = release_bus(wl, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret ? ret : rv; } EXPORT_SYMBOL_GPL(wilc_load_mac_from_nv); int wilc_wlan_init(struct net_device *dev) { - int ret = 0; + int ret = 0, rv; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc; @@ -1533,11 +1748,26 @@ int wilc_wlan_init(struct net_device *dev) wilc->quit = 0; if (!wilc->hif_func->hif_is_init(wilc)) { - acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); + ret = acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); + if (ret) + return ret; + ret = wilc->hif_func->hif_init(wilc, false); - release_bus(wilc, WILC_BUS_RELEASE_ONLY); + if (!ret) + ret = wilc_get_chipid(wilc); + rv = release_bus(wilc, WILC_BUS_RELEASE_ONLY); + if (!ret && rv) + ret = rv; if (ret) goto fail; + + if (!is_wilc1000(wilc->chipid) && !is_wilc3000(wilc->chipid)) { + netdev_err(dev, "Unsupported chipid: %x\n", wilc->chipid); + ret = -EINVAL; + goto fail; + } + + netdev_dbg(dev, "chipid (%08x)\n", wilc->chipid); } if (!wilc->vmm_table) diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index dd2fb3c2f06a..b9e7f9222ead 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -96,8 +96,14 @@ #define WILC_SPI_WAKEUP_REG 0x1 #define WILC_SPI_WAKEUP_BIT BIT(1) -#define WILC_SPI_CLK_STATUS_REG 0x0f -#define WILC_SPI_CLK_STATUS_BIT BIT(2) +/* WILC1000 specific */ +#define WILC1000_SPI_CLK_STATUS_REG 0x0f +#define WILC1000_SPI_CLK_STATUS_BIT BIT(2) + +/* WILC3000 specific */ +#define WILC3000_SPI_CLK_STATUS_REG 0x13 +#define WILC3000_SPI_CLK_STATUS_BIT BIT(2) + #define WILC_SPI_HOST_TO_FW_REG 0x0b #define WILC_SPI_HOST_TO_FW_BIT BIT(0) @@ -123,14 +129,24 @@ #define WILC_SDIO_WAKEUP_REG 0xf0 #define WILC_SDIO_WAKEUP_BIT BIT(0) -#define WILC_SDIO_CLK_STATUS_REG 0xf1 -#define WILC_SDIO_CLK_STATUS_BIT BIT(0) +/* WILC1000 */ +#define WILC1000_SDIO_CLK_STATUS_REG 0xf1 +#define WILC1000_SDIO_CLK_STATUS_BIT BIT(0) + +#define WILC1000_SDIO_IRQ_FLAG_REG 0xf7 +#define WILC1000_SDIO_IRQ_CLEAR_FLAG_REG 0xf8 + +/* WILC3000 specific */ +#define WILC3000_SDIO_CLK_STATUS_REG 0xf0 /* clk & wakeup are on same reg */ +#define WILC3000_SDIO_CLK_STATUS_BIT BIT(4) + +#define WILC3000_SDIO_VMM_TBL_CTRL_REG 0xf1 +#define WILC3000_SDIO_IRQ_FLAG_REG 0xfe +/* Common vendor specific CCCR register */ #define WILC_SDIO_INTERRUPT_DATA_SZ_REG 0xf2 /* Read size (2 bytes) */ #define WILC_SDIO_VMM_TBL_CTRL_REG 0xf6 -#define WILC_SDIO_IRQ_FLAG_REG 0xf7 -#define WILC_SDIO_IRQ_CLEAR_FLAG_REG 0xf8 #define WILC_SDIO_HOST_TO_FW_REG 0xfa #define WILC_SDIO_HOST_TO_FW_BIT BIT(0) @@ -172,8 +188,11 @@ #define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8) #define WILC_CORTUS_INTERRUPT_BASE 0x10A8 -#define WILC_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4) -#define WILC_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8) +#define WILC1000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4) +#define WILC3000_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x14) + +#define WILC1000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8) +#define WILC3000_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x18) /* tx control register 1 to 4 for RX */ #define WILC_REG_4_TO_1_RX 0x1e1c @@ -183,6 +202,9 @@ #define WILC_CORTUS_RESET_MUX_SEL 0x1118 #define WILC_CORTUS_BOOT_REGISTER 0xc0000 +#define WILC3000_BOOTROM_STATUS 0x207ac +#define WILC3000_CORTUS_BOOT_REGISTER_2 0x4f0000 +#define WILC3000_CHIP_ID 0x3b0000 #define WILC_CORTUS_BOOT_FROM_IRAM 0x71 @@ -195,6 +217,8 @@ #define WILC_1000_BASE_ID_2B_REV1 (WILC_1000_BASE_ID_2B + 1) #define WILC_1000_BASE_ID_2B_REV2 (WILC_1000_BASE_ID_2B + 2) +#define WILC_3000_BASE_ID 0x300000 + #define WILC_CHIP_REV_FIELD GENMASK(11, 0) /******************************************** @@ -413,6 +437,11 @@ static inline bool is_wilc1000(u32 id) return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID; } +static inline bool is_wilc3000(u32 id) +{ + return (id & (~WILC_CHIP_REV_FIELD)) == WILC_3000_BASE_ID; +} + int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *wilc); @@ -436,13 +465,11 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size); bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size); -void host_wakeup_notify(struct wilc *wilc); -void host_sleep_notify(struct wilc *wilc); -void chip_allow_sleep(struct wilc *wilc); -void chip_wakeup(struct wilc *wilc); +int host_wakeup_notify(struct wilc *wilc); +int host_sleep_notify(struct wilc *wilc); int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count); int wilc_wlan_init(struct net_device *dev); -u32 wilc_get_chipid(struct wilc *wilc, bool update); +int wilc_get_chipid(struct wilc *wilc); int wilc_load_mac_from_nv(struct wilc *wilc); #endif diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 9540ad6196d7..956c5763662f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -257,7 +257,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, cmd->beacon_interval = cpu_to_le16(s->beacon_interval); cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid); cmd->inactivity_timeout = cpu_to_le16(s->inactivity_timeout); - cmd->smps_mode = s->smps_mode; + cmd->smps_mode = NL80211_SMPS_OFF; cmd->p2p_ctwindow = s->p2p_ctwindow; cmd->p2p_opp_ps = s->p2p_opp_ps; cmd->pbss = s->pbss; diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index b204a24074ab..b375a4751580 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -13,7 +13,6 @@ #include <linux/if_arp.h> #include <linux/etherdevice.h> #include <net/sock.h> -#include <net/lib80211.h> #include <net/cfg80211.h> #include <linux/vmalloc.h> #include <linux/firmware.h> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 3bb81bcff0ac..60c2a12e9d5e 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3607,7 +3607,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); if (rf->channel <= 50) { - rt2800_rfcsr_write(rt2x00dev, 55, 0x06), + rt2800_rfcsr_write(rt2x00dev, 55, 0x06); rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); } else if (rf->channel >= 52) { rt2800_rfcsr_write(rt2x00dev, 55, 0x04); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c index 7891c988dd5f..f95898f68d68 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -5058,10 +5058,12 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (bss_conf->enable_beacon) + if (bss_conf->enable_beacon) { rtl8xxxu_start_tx_beacon(priv); - else + schedule_delayed_work(&priv->update_beacon_work, 0); + } else { rtl8xxxu_stop_tx_beacon(priv); + } } if (changed & BSS_CHANGED_BEACON) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 0e77de1baaf8..bcfc53af4c1a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -2040,31 +2040,33 @@ static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int params[] = {RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID, - EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, - EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, - COUNTRY_CODE_WORLD_WIDE_13}; + static const int params[] = { + RTL8723BE_EEPROM_ID, EEPROM_VID, EEPROM_DID, + EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, + EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, + COUNTRY_CODE_WORLD_WIDE_13 + }; u8 *hwinfo; int i; bool is_toshiba_smid1 = false; bool is_toshiba_smid2 = false; bool is_samsung_smid = false; bool is_lenovo_smid = false; - u16 toshiba_smid1[] = { + static const u16 toshiba_smid1[] = { 0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180, 0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180, 0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185, 0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185 }; - u16 toshiba_smid2[] = { + static const u16 toshiba_smid2[] = { 0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181, 0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185 }; - u16 samsung_smid[] = { + static const u16 samsung_smid[] = { 0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192, 0x8193, 0x9191, 0x9192, 0x9193 }; - u16 lenovo_smid[] = { + static const u16 lenovo_smid[] = { 0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200 }; diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index b9b0114e253b..813c12148819 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -267,7 +267,7 @@ static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload, static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload, u8 length) { - struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload; rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 564f5988ee82..e5abcc20b63c 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -228,7 +228,7 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, } static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, - const struct rtw_pwr_seq_cmd **cmd_seq) + const struct rtw_pwr_seq_cmd * const *cmd_seq) { u8 cut_mask; u8 intf_mask; @@ -271,7 +271,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) { const struct rtw_chip_info *chip = rtwdev->chip; - const struct rtw_pwr_seq_cmd **pwr_seq; + const struct rtw_pwr_seq_cmd * const *pwr_seq; u32 imr = 0; u8 rpwm; bool cur_pwr; diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index b39e90fb66b4..026fbf4ad9cc 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -928,8 +928,10 @@ static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw, static void rtw_ops_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u32 changed) + struct ieee80211_link_sta *link_sta, + u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct rtw_dev *rtwdev = hw->priv; struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; @@ -973,7 +975,7 @@ const struct ieee80211_ops rtw_ops = { .reconfig_complete = rtw_reconfig_complete, .hw_scan = rtw_ops_hw_scan, .cancel_hw_scan = rtw_ops_cancel_hw_scan, - .sta_rc_update = rtw_ops_sta_rc_update, + .link_sta_rc_update = rtw_ops_sta_rc_update, .set_sar_specs = rtw_ops_set_sar_specs, #ifdef CONFIG_PM .suspend = rtw_ops_suspend, diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 945117afe143..05cfb235f272 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -848,9 +848,8 @@ struct rtw_chip_ops { void (*phy_set_param)(struct rtw_dev *rtwdev); void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, u8 bandwidth, u8 primary_chan_idx); - void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status); + void (*query_phy_status)(struct rtw_dev *rtwdev, u8 *phy_status, + struct rtw_rx_pkt_stat *pkt_stat); u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, u32 addr, u32 mask); bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, @@ -1167,7 +1166,7 @@ enum rtw_fwcd_item { /* hardware configuration for each IC */ struct rtw_chip_info { - struct rtw_chip_ops *ops; + const struct rtw_chip_ops *ops; u8 id; const char *fw_name; @@ -1209,8 +1208,8 @@ struct rtw_chip_info { /* init values */ u8 sys_func_en; - const struct rtw_pwr_seq_cmd **pwr_on_seq; - const struct rtw_pwr_seq_cmd **pwr_off_seq; + const struct rtw_pwr_seq_cmd * const *pwr_on_seq; + const struct rtw_pwr_seq_cmd * const *pwr_off_seq; const struct rtw_rqpn *rqpn_table; const struct rtw_prioq_addrs *prioq_addrs; const struct rtw_page_table *page_table; @@ -1242,7 +1241,7 @@ struct rtw_chip_info { u8 bfer_su_max_num; u8 bfer_mu_max_num; - struct rtw_hw_reg_offset *edcca_th; + const struct rtw_hw_reg_offset *edcca_th; s8 l2h_th_ini_cs; s8 l2h_th_ini_ad; diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index 0b9b8807af2c..f71e41d6f97c 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1065,7 +1065,7 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci, dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE, DMA_FROM_DEVICE); rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); /* offset from rx_desc to payload */ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 37ef80c9091d..d57a2aabd89b 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -123,7 +123,7 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) { - struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; + const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; rtw_write32_mask(rtwdev, edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c index 222608de33cd..77399b8dd8cd 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c @@ -29,9 +29,6 @@ #define TBTT_PROHIBIT_HOLD_TIME 0x80 #define TBTT_PROHIBIT_HOLD_TIME_STOP_BCN 0x64 -/* raw pkt_stat->drv_info_sz is in unit of 8-bytes */ -#define RX_DRV_INFO_SZ_UNIT_8703B 8 - #define TRANS_SEQ_END \ 0xFFFF, \ RTW_PWR_CUT_ALL_MSK, \ @@ -481,14 +478,14 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8703b[] = { {TRANS_SEQ_END}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8703b[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8703b[] = { trans_pre_enable_8703b, trans_carddis_to_cardemu_8703b, trans_cardemu_to_act_8703b, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = { trans_act_to_lps_8703b, trans_act_to_reset_mcu_8703b, trans_act_to_cardemu_8703b, @@ -1032,57 +1029,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, query_phy_status_ofdm(rtwdev, phy_status, pkt_stat); } -static void rtw8703b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = 0; - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - pkt_stat->drv_info_sz *= RX_DRV_INFO_SZ_UNIT_8703B; - - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - - pkt_stat->bw = GET_RX_DESC_BW(rx_desc); - - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); - - /* Rtl8723cs driver checks for size < 14 or size > 8192 and - * simply drops the packet. Maybe this should go into - * rtw_rx_fill_rx_status()? - */ - if (pkt_stat->pkt_len == 0) { - rx_status->flag |= RX_FLAG_NO_PSDU; - rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); - } -} - #define ADDA_ON_VAL_8703B 0x03c00014 static @@ -1941,14 +1887,14 @@ static const struct coex_tdma_para tdma_sant_8703b[] = { { {0x61, 0x08, 0x03, 0x11, 0x11} }, }; -static struct rtw_chip_ops rtw8703b_ops = { +static const struct rtw_chip_ops rtw8703b_ops = { .mac_init = rtw8723x_mac_init, .dump_fw_crash = NULL, .shutdown = NULL, .read_efuse = rtw8703b_read_efuse, .phy_set_param = rtw8703b_phy_set_param, .set_channel = rtw8703b_set_channel, - .query_rx_desc = rtw8703b_query_rx_desc, + .query_phy_status = query_phy_status, .read_rf = rtw_phy_read_rf_sipi, .write_rf = rtw_phy_write_rf_reg_sipi, .set_tx_power_index = rtw8723x_set_tx_power_index, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 3fba4054d45f..86a5e2497641 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -227,47 +227,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = 0; - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev, u8 channel, u32 thres) { @@ -1430,10 +1389,10 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) dm_info->pwr_trk_triggered = false; } -static struct rtw_chip_ops rtw8723d_ops = { +static const struct rtw_chip_ops rtw8723d_ops = { .phy_set_param = rtw8723d_phy_set_param, .read_efuse = rtw8723x_read_efuse, - .query_rx_desc = rtw8723d_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8723d_set_channel, .mac_init = rtw8723x_mac_init, .shutdown = rtw8723d_shutdown, @@ -1788,7 +1747,7 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8723d[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8723d[] = { trans_carddis_to_cardemu_8723d, trans_cardemu_to_act_8723d, NULL @@ -2004,7 +1963,7 @@ static const struct rtw_pwr_seq_cmd trans_act_to_post_carddis_8723d[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8723d[] = { trans_act_to_lps_8723d, trans_act_to_pre_carddis_8723d, trans_act_to_cardemu_8723d, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index 526e8de77b3e..66c79956e8e5 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -679,47 +679,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) { @@ -1254,7 +1213,7 @@ static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev, fill_txdesc_checksum_common(txdesc, 16); } -static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { {0x0086, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_SDIO_MSK, @@ -1292,7 +1251,7 @@ static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { {0x0020, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -1396,7 +1355,7 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { {0x0093, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1454,7 +1413,7 @@ static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { +static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { {0x0007, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -1567,13 +1526,13 @@ static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8821c[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8821c[] = { trans_carddis_to_cardemu_8821c, trans_cardemu_to_act_8821c, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8821c[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8821c[] = { trans_act_to_cardemu_8821c, trans_cardemu_to_carddis_8821c, NULL @@ -1629,7 +1588,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { [6] = RTW_DEF_RFE(8821c, 0, 0), }; -static struct rtw_hw_reg rtw8821c_dig[] = { +static const struct rtw_hw_reg rtw8821c_dig[] = { [0] = { .addr = 0xc50, .mask = 0x7f }, }; @@ -1639,7 +1598,7 @@ static const struct rtw_ltecoex_addr rtw8821c_ltecoex_addr = { .rdata = LTECOEX_READ_DATA, }; -static struct rtw_page_table page_table_8821c[] = { +static const struct rtw_page_table page_table_8821c[] = { /* not sure what [0] stands for */ {16, 16, 16, 14, 1}, {16, 16, 16, 14, 1}, @@ -1648,7 +1607,7 @@ static struct rtw_page_table page_table_8821c[] = { {16, 16, 16, 14, 1}, }; -static struct rtw_rqpn rqpn_table_8821c[] = { +static const struct rtw_rqpn rqpn_table_8821c[] = { /* not sure what [0] stands for */ {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, @@ -1667,7 +1626,7 @@ static struct rtw_rqpn rqpn_table_8821c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8821c = { +static const struct rtw_prioq_addrs prioq_addrs_8821c = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -1683,10 +1642,10 @@ static struct rtw_prioq_addrs prioq_addrs_8821c = { .wsize = true, }; -static struct rtw_chip_ops rtw8821c_ops = { +static const struct rtw_chip_ops rtw8821c_ops = { .phy_set_param = rtw8821c_phy_set_param, .read_efuse = rtw8821c_read_efuse, - .query_rx_desc = rtw8821c_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8821c_set_channel, .mac_init = rtw8821c_mac_init, .read_rf = rtw_phy_read_rf, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 6edb17aea90e..24f76a36f23e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -934,47 +934,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs) { @@ -1978,13 +1937,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822b[] = { trans_carddis_to_cardemu_8822b, trans_cardemu_to_act_8822b, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822b[] = { trans_act_to_cardemu_8822b, trans_cardemu_to_carddis_8822b, NULL @@ -2156,7 +2115,7 @@ static const struct rtw_rqpn rqpn_table_8822b[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8822b = { +static const struct rtw_prioq_addrs prioq_addrs_8822b = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -2172,10 +2131,10 @@ static struct rtw_prioq_addrs prioq_addrs_8822b = { .wsize = true, }; -static struct rtw_chip_ops rtw8822b_ops = { +static const struct rtw_chip_ops rtw8822b_ops = { .phy_set_param = rtw8822b_phy_set_param, .read_efuse = rtw8822b_read_efuse, - .query_rx_desc = rtw8822b_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8822b_set_channel, .mac_init = rtw8822b_mac_init, .read_rf = rtw_phy_read_rf, @@ -2521,7 +2480,7 @@ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = { {0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, }; -static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { +static const struct rtw_hw_reg_offset rtw8822b_edcca_th[] = { [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0}, [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0}, }; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 1dbe1cdbc3fd..da74e66bda84 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -2690,48 +2690,6 @@ static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, } } -static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; - u8 *phy_status = NULL; - - memset(pkt_stat, 0, sizeof(*pkt_stat)); - - pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); - pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); - pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); - pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && - GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; - pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); - pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); - pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); - pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); - pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); - pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); - pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc); - pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); - - /* drv_info_sz is in unit of 8-bytes */ - pkt_stat->drv_info_sz *= 8; - - /* c2h cmd pkt's rx/phy status is not interested */ - if (pkt_stat->is_c2h) - return; - - hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + - pkt_stat->drv_info_sz); - pkt_stat->hdr = hdr; - if (pkt_stat->phy_status) { - phy_status = rx_desc + desc_sz + pkt_stat->shift; - query_phy_status(rtwdev, phy_status, pkt_stat); - } - - rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); -} - static void rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck, u8 *tx_pwr_ref_ofdm) @@ -4874,13 +4832,13 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { RTW_PWR_CMD_END, 0, 0}, }; -static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822c[] = { trans_carddis_to_cardemu_8822c, trans_cardemu_to_act_8822c, NULL }; -static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = { +static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822c[] = { trans_act_to_cardemu_8822c, trans_cardemu_to_carddis_8822c, NULL @@ -4972,7 +4930,7 @@ static const struct rtw_rqpn rqpn_table_8822c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -static struct rtw_prioq_addrs prioq_addrs_8822c = { +static const struct rtw_prioq_addrs prioq_addrs_8822c = { .prio[RTW_DMA_MAPPING_EXTRA] = { .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, }, @@ -4988,10 +4946,10 @@ static struct rtw_prioq_addrs prioq_addrs_8822c = { .wsize = true, }; -static struct rtw_chip_ops rtw8822c_ops = { +static const struct rtw_chip_ops rtw8822c_ops = { .phy_set_param = rtw8822c_phy_set_param, .read_efuse = rtw8822c_read_efuse, - .query_rx_desc = rtw8822c_query_rx_desc, + .query_phy_status = query_phy_status, .set_channel = rtw8822c_set_channel, .mac_init = rtw8822c_mac_init, .dump_fw_crash = rtw8822c_dump_fw_crash, @@ -5301,7 +5259,7 @@ static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = { .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p, }; -static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { +static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = { [EDCCA_TH_L2H_IDX] = { {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80 }, diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c index 66f9419588cf..1de93fc9efe9 100644 --- a/drivers/net/wireless/realtek/rtw88/rx.c +++ b/drivers/net/wireless/realtek/rtw88/rx.c @@ -187,11 +187,10 @@ fill_rx_status: } EXPORT_SYMBOL(rtw_update_rx_freq_from_ie); -void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_hdr *hdr, - struct ieee80211_rx_status *rx_status, - u8 *phy_status) +static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) { struct ieee80211_hw *hw = rtwdev->hw; u8 path; @@ -242,5 +241,64 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, } rtw_rx_addr_match(rtwdev, pkt_stat, hdr); + + /* Rtl8723cs driver checks for size < 14 or size > 8192 and + * simply drops the packet. + */ + if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) { + rx_status->flag |= RX_FLAG_NO_PSDU; + rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet"); + } +} + +void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status) +{ + u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; + struct rtw_rx_desc *rx_desc = rx_desc8; + struct ieee80211_hdr *hdr; + u32 enc_type, swdec; + void *phy_status; + + memset(pkt_stat, 0, sizeof(*pkt_stat)); + + pkt_stat->pkt_len = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PKT_LEN); + pkt_stat->crc_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_CRC32); + pkt_stat->icv_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ICV_ERR); + pkt_stat->drv_info_sz = le32_get_bits(rx_desc->w0, + RTW_RX_DESC_W0_DRV_INFO_SIZE); + enc_type = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ENC_TYPE); + pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT); + pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST); + swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC); + pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE; + + pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID); + + pkt_stat->is_c2h = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_C2H); + pkt_stat->ppdu_cnt = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_PPDU_CNT); + + pkt_stat->rate = le32_get_bits(rx_desc->w3, RTW_RX_DESC_W3_RX_RATE); + + pkt_stat->bw = le32_get_bits(rx_desc->w4, RTW_RX_DESC_W4_BW); + + pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL); + + /* drv_info_sz is in unit of 8-bytes */ + pkt_stat->drv_info_sz *= 8; + + /* c2h cmd pkt's rx/phy status is not interested */ + if (pkt_stat->is_c2h) + return; + + phy_status = rx_desc8 + desc_sz + pkt_stat->shift; + hdr = phy_status + pkt_stat->drv_info_sz; + pkt_stat->hdr = hdr; + + if (pkt_stat->phy_status) + rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat); + + rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status); } -EXPORT_SYMBOL(rtw_rx_fill_rx_status); +EXPORT_SYMBOL(rtw_rx_query_rx_desc); diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h index 9f0019112987..6b7dee245c0a 100644 --- a/drivers/net/wireless/realtek/rtw88/rx.h +++ b/drivers/net/wireless/realtek/rtw88/rx.h @@ -14,42 +14,40 @@ enum rtw_rx_desc_enc { RX_DESC_ENC_WEP104 = 5, }; -#define GET_RX_DESC_PHYST(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26)) -#define GET_RX_DESC_ICV_ERR(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15)) -#define GET_RX_DESC_CRC32(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14)) -#define GET_RX_DESC_SWDEC(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27)) -#define GET_RX_DESC_C2H(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28)) -#define GET_RX_DESC_PKT_LEN(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0)) -#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16)) -#define GET_RX_DESC_SHIFT(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24)) -#define GET_RX_DESC_ENC_TYPE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20)) -#define GET_RX_DESC_RX_RATE(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0)) -#define GET_RX_DESC_MACID(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0)) -#define GET_RX_DESC_PPDU_CNT(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29)) -#define GET_RX_DESC_TSFL(rxdesc) \ - le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0)) -#define GET_RX_DESC_BW(rxdesc) \ - (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4))) +struct rtw_rx_desc { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; +} __packed; + +#define RTW_RX_DESC_W0_PKT_LEN GENMASK(13, 0) +#define RTW_RX_DESC_W0_CRC32 BIT(14) +#define RTW_RX_DESC_W0_ICV_ERR BIT(15) +#define RTW_RX_DESC_W0_DRV_INFO_SIZE GENMASK(19, 16) +#define RTW_RX_DESC_W0_ENC_TYPE GENMASK(22, 20) +#define RTW_RX_DESC_W0_SHIFT GENMASK(25, 24) +#define RTW_RX_DESC_W0_PHYST BIT(26) +#define RTW_RX_DESC_W0_SWDEC BIT(27) + +#define RTW_RX_DESC_W1_MACID GENMASK(6, 0) + +#define RTW_RX_DESC_W2_C2H BIT(28) +#define RTW_RX_DESC_W2_PPDU_CNT GENMASK(30, 29) + +#define RTW_RX_DESC_W3_RX_RATE GENMASK(6, 0) + +#define RTW_RX_DESC_W4_BW GENMASK(5, 4) + +#define RTW_RX_DESC_W5_TSFL GENMASK(31, 0) void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, struct sk_buff *skb); -void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev, - struct rtw_rx_pkt_stat *pkt_stat, - struct ieee80211_hdr *hdr, - struct ieee80211_rx_status *rx_status, - u8 *phy_status); +void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8, + struct rtw_rx_pkt_stat *pkt_stat, + struct ieee80211_rx_status *rx_status); void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status, struct rtw_rx_pkt_stat *pkt_stat); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 21d0754dd7f6..f0b06ed8f76d 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -981,8 +981,7 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) while (true) { rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, - &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status); pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + pkt_stat.shift; @@ -1297,12 +1296,12 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev) struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; int i; - for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) - skb_queue_purge(&rtwsdio->tx_queue[i]); - flush_workqueue(rtwsdio->txwq); destroy_workqueue(rtwsdio->txwq); kfree(rtwsdio->tx_handler_data); + + for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++) + ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]); } int rtw_sdio_probe(struct sdio_func *sdio_func, diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index e83ab6fb83f5..ba314d90ab3f 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -423,10 +423,11 @@ static void rtw_usb_tx_handler(struct work_struct *work) static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb) { + struct rtw_dev *rtwdev = rtwusb->rtwdev; int i; for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) - skb_queue_purge(&rtwusb->tx_queue[i]); + ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]); } static void rtw_usb_write_port_complete(struct urb *urb) @@ -570,8 +571,8 @@ static void rtw_usb_rx_handler(struct work_struct *work) do { rx_desc = skb->data; - chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, - &rx_status); + rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, + &rx_status); pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz + pkt_stat.shift; @@ -889,9 +890,9 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) { struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); - rtw_usb_tx_queue_purge(rtwusb); flush_workqueue(rtwusb->txwq); destroy_workqueue(rtwusb->txwq); + rtw_usb_tx_queue_purge(rtwusb); } static int rtw_usb_intf_init(struct rtw_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 4476fc7e53db..8d140b94cb44 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -211,25 +211,17 @@ static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam, return 0; } -static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - const struct rtw89_sec_cam_entry *sec_cam, - bool inform_fw) +static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + const struct rtw89_sec_cam_entry *sec_cam, + bool inform_fw) { - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif; struct rtw89_addr_cam_entry *addr_cam; unsigned int i; int ret = 0; - if (!vif) { - rtw89_err(rtwdev, "No iface for deleting sec cam\n"); - return -EINVAL; - } - - rtwvif = (struct rtw89_vif *)vif->drv_priv; - addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); for_each_set_bit(i, addr_cam->sec_cam_map, RTW89_SEC_CAM_IN_ADDR_CAM) { if (addr_cam->sec_ent[i] != sec_cam->sec_cam_idx) @@ -239,11 +231,11 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, } if (inform_fw) { - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); } @@ -251,25 +243,17 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, return ret; } -static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key, - struct rtw89_sec_cam_entry *sec_cam) +static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_key_conf *key, + struct rtw89_sec_cam_entry *sec_cam) { - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif; struct rtw89_addr_cam_entry *addr_cam; u8 key_idx = 0; int ret; - if (!vif) { - rtw89_err(rtwdev, "No iface for adding sec cam\n"); - return -EINVAL; - } - - rtwvif = (struct rtw89_vif *)vif->drv_priv; - addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || key->cipher == WLAN_CIPHER_SUITE_WEP104) @@ -285,13 +269,13 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, addr_cam->sec_ent_keyid[key_idx] = key->keyidx; addr_cam->sec_ent[key_idx] = sec_cam->sec_cam_idx; set_bit(key_idx, addr_cam->sec_cam_map); - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", ret); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", ret); @@ -302,6 +286,92 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, return 0; } +static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + const struct rtw89_sec_cam_entry *sec_cam, + bool inform_fw) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *rtwvif; + unsigned int link_id; + int ret; + + if (!vif) { + rtw89_err(rtwdev, "No iface for deleting sec cam\n"); + return -EINVAL; + } + + rtwvif = vif_to_rtwvif(vif); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL; + if (rtwsta && !rtwsta_link) + continue; + + ret = __rtw89_cam_detach_sec_cam(rtwdev, rtwvif_link, rtwsta_link, + sec_cam, inform_fw); + if (ret) + return ret; + } + + return 0; +} + +static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + struct rtw89_sec_cam_entry *sec_cam) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *rtwvif; + unsigned int link_id; + int key_link_id; + int ret; + + if (!vif) { + rtw89_err(rtwdev, "No iface for adding sec cam\n"); + return -EINVAL; + } + + rtwvif = vif_to_rtwvif(vif); + + key_link_id = ieee80211_vif_is_mld(vif) ? key->link_id : 0; + if (key_link_id >= 0) { + rtwvif_link = rtwvif->links[key_link_id]; + rtwsta_link = rtwsta ? rtwsta->links[key_link_id] : NULL; + + if (!rtwvif_link || (rtwsta && !rtwsta_link)) { + rtw89_err(rtwdev, "No drv link for adding sec cam\n"); + return -ENOLINK; + } + + return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, + rtwsta_link, key, sec_cam); + } + + /* key_link_id < 0: MLD pairwise key */ + if (!rtwsta) { + rtw89_err(rtwdev, "No sta for adding MLD pairwise sec cam\n"); + return -EINVAL; + } + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, + rtwsta_link, key, sec_cam); + if (ret) + return ret; + } + + return 0; +} + static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -485,10 +555,10 @@ void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, clear_bit(bssid_cam->bssid_cam_idx, cam_info->bssid_cam_map); } -void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; rtw89_cam_deinit_addr_cam(rtwdev, addr_cam); rtw89_cam_deinit_bssid_cam(rtwdev, bssid_cam); @@ -593,7 +663,7 @@ static int rtw89_cam_get_avail_bssid_cam(struct rtw89_dev *rtwdev, } int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_bssid_cam_entry *bssid_cam, const u8 *bssid) { @@ -613,7 +683,7 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, } bssid_cam->bssid_cam_idx = bssid_cam_idx; - bssid_cam->phy_idx = rtwvif->phy_idx; + bssid_cam->phy_idx = rtwvif_link->phy_idx; bssid_cam->len = BSSID_CAM_ENT_SIZE; bssid_cam->offset = 0; bssid_cam->valid = true; @@ -622,20 +692,21 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, return 0; } -void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; - ether_addr_copy(bssid_cam->bssid, rtwvif->bssid); + ether_addr_copy(bssid_cam->bssid, rtwvif_link->bssid); } -int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - struct rtw89_addr_cam_entry *addr_cam = &rtwvif->addr_cam; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_addr_cam_entry *addr_cam = &rtwvif_link->addr_cam; + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; int ret; - ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, rtwvif->bssid); + ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, + rtwvif_link->bssid); if (ret) { rtw89_err(rtwdev, "failed to init bssid cam\n"); return ret; @@ -651,19 +722,27 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) } int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, u8 *cmd) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, u8 *cmd) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); - u8 bss_color = vif->bss_conf.he_bss_color.color; + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); + struct ieee80211_bss_conf *bss_conf; + u8 bss_color; u8 bss_mask; - if (vif->bss_conf.nontransmitted) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + bss_color = bss_conf->he_bss_color.color; + + if (bss_conf->nontransmitted) bss_mask = RTW89_BSSID_MATCH_5_BYTES; else bss_mask = RTW89_BSSID_MATCH_ALL; + rcu_read_unlock(); + FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); @@ -694,19 +773,30 @@ static u8 rtw89_cam_addr_hash(u8 start, const u8 *addr) } void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, u8 *cmd) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); - struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); - const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif->mac_addr; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); + struct ieee80211_link_sta *link_sta; + const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; u8 sma_hash, tma_hash, addr_msk_start; u8 sma_start = 0; u8 tma_start = 0; - u8 *tma = sta ? sta->addr : rtwvif->bssid; + const u8 *tma; + + rcu_read_lock(); + + if (sta) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + tma = link_sta->addr; + } else { + tma = rtwvif_link->bssid; + } if (addr_cam->addr_mask != 0) { addr_msk_start = __ffs(addr_cam->addr_mask); @@ -723,10 +813,10 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); - FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif->net_type); - FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif->bcn_hit_cond); - FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif->hit_rule); - FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif->phy_idx); + FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type); + FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond); + FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule); + FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx); FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); @@ -748,20 +838,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_TMA4(cmd, tma[4]); FWCMD_SET_ADDR_TMA5(cmd, tma[5]); - FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif->port); - FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif->port); - FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif->trigger); - FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif->lsig_txop); - FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif->tgt_ind); - FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif->frm_tgt_ind); - FWCMD_SET_ADDR_MACID(cmd, rtwsta ? rtwsta->mac_id : rtwvif->mac_id); - if (rtwvif->net_type == RTW89_NET_TYPE_INFRA) + FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port); + FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port); + FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger); + FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); + FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); + FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); + FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id); + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); - else if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); - FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif->wowlan_pattern); - FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif->wowlan_uc); - FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif->wowlan_magic); + FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern); + FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc); + FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic); FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); @@ -780,18 +871,22 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); + + rcu_read_unlock(); } void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v1 *h2c) { - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; - h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, + h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id, DCTLINFO_V1_C0_MACID) | le32_encode_bits(1, DCTLINFO_V1_C0_OP); @@ -862,15 +957,17 @@ void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, } void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v2 *h2c) { - struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif, rtwsta); + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; - h2c->c0 = le32_encode_bits(rtwsta ? rtwsta->mac_id : rtwvif->mac_id, + h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id, DCTLINFO_V2_C0_MACID) | le32_encode_bits(1, DCTLINFO_V2_C0_OP); diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index 5d7b624c2dd4..a6f72edd30fe 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -526,34 +526,34 @@ struct rtw89_h2c_dctlinfo_ud_v2 { #define DCTLINFO_V2_W12_MLD_TA_BSSID_H_V1 GENMASK(15, 0) #define DCTLINFO_V2_W12_ALL GENMASK(15, 0) -int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); -void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev, struct rtw89_addr_cam_entry *addr_cam, const struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_deinit_addr_cam(struct rtw89_dev *rtwdev, struct rtw89_addr_cam_entry *addr_cam); int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_bssid_cam_entry *bssid_cam, const u8 *bssid); void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *vif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *vif, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, u8 *cmd); void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v1 *h2c); void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v2 *h2c); int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, u8 *cmd); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, u8 *cmd); int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -564,6 +564,6 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev, struct ieee80211_key_conf *key, bool inform_fw); void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 7070c85e2c28..ba6332da8019 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -234,6 +234,18 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) rtw89_config_default_chandef(rtwdev); } +static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->chanctx_assigned) + return true; + + return false; +} + static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, struct rtw89_entity_weight *w) { @@ -255,7 +267,7 @@ static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, } rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (rtwvif->chanctx_assigned) + if (rtw89_vif_is_active_role(rtwvif)) w->active_roles++; } } @@ -387,9 +399,9 @@ int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev, static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, u64 tsf) { - struct rtw89_vif *rtwvif = role->rtwvif; + struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval); - u64 sync_tsf = READ_ONCE(rtwvif->sync_bcn_tsf); + u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); u32 remainder; if (tsf < sync_tsf) { @@ -413,8 +425,8 @@ static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux int ret; req.group = mcc->group; - req.macid_x = ref->rtwvif->mac_id; - req.macid_y = aux->rtwvif->mac_id; + req.macid_x = ref->rtwvif_link->mac_id; + req.macid_y = aux->rtwvif_link->mac_id; ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -440,10 +452,10 @@ static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES); arg.num = 2; - arg.infos[0].band = ref->rtwvif->mac_idx; - arg.infos[0].port = ref->rtwvif->port; - arg.infos[1].band = aux->rtwvif->mac_idx; - arg.infos[1].port = aux->rtwvif->port; + arg.infos[0].band = ref->rtwvif_link->mac_idx; + arg.infos[0].port = ref->rtwvif_link->port; + arg.infos[1].band = aux->rtwvif_link->mac_idx; + arg.infos[1].port = aux->rtwvif_link->port; ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt); if (ret) { @@ -522,23 +534,31 @@ out: static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_mcc_role *mcc_role = data; - struct rtw89_vif *target = mcc_role->rtwvif; + struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; if (rtwvif != target) return; - rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta->mac_id); + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n"); + return; + } + + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id); } static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *mcc_role) { - struct rtw89_vif *rtwvif = mcc_role->rtwvif; + struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; - rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif->mac_id); + rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id); ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_mcc_role_macid_sta_iter, mcc_role); @@ -564,8 +584,9 @@ static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev, static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *mcc_role) { - struct ieee80211_vif *vif = rtwvif_to_vif(mcc_role->rtwvif); + struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; struct ieee80211_p2p_noa_desc *noa_desc; + struct ieee80211_bss_conf *bss_conf; u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval); u32 max_toa_us, max_tob_us, max_dur_us; u32 start_time, interval, duration; @@ -576,13 +597,18 @@ static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, if (!mcc_role->is_go && !mcc_role->is_gc) return; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + /* find the first periodic NoA */ for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { - noa_desc = &vif->bss_conf.p2p_noa_attr.desc[i]; + noa_desc = &bss_conf->p2p_noa_attr.desc[i]; if (noa_desc->count == 255) goto fill; } + rcu_read_unlock(); return; fill: @@ -590,6 +616,8 @@ fill: interval = le32_to_cpu(noa_desc->interval); duration = le32_to_cpu(noa_desc->duration); + rcu_read_unlock(); + if (interval != bcn_intvl_us) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC role limit: mismatch interval: %d vs. %d\n", @@ -597,7 +625,7 @@ fill: return; } - ret = rtw89_mac_port_get_tsf(rtwdev, mcc_role->rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return; @@ -632,15 +660,21 @@ fill: } static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_mcc_role *role) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; const struct rtw89_chan *chan; memset(role, 0, sizeof(*role)); - role->rtwvif = rtwvif; - role->beacon_interval = vif->bss_conf.beacon_int; + role->rtwvif_link = rtwvif_link; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + role->beacon_interval = bss_conf->beacon_int; + + rcu_read_unlock(); if (!role->beacon_interval) { rtw89_warn(rtwdev, @@ -650,10 +684,10 @@ static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, role->duration = role->beacon_interval / 2; - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); role->is_2ghz = chan->band_type == RTW89_BAND_2G; - role->is_go = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_GO; - role->is_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO; + role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; rtw89_mcc_fill_role_macid_bitmap(rtwdev, role); rtw89_mcc_fill_role_policy(rtwdev, role); @@ -678,7 +712,7 @@ static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev) } struct rtw89_mcc_fill_role_selector { - struct rtw89_vif *bind_vif[NUM_OF_RTW89_CHANCTX]; + struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX]; }; static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES); @@ -689,7 +723,7 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, void *data) { struct rtw89_mcc_fill_role_selector *sel = data; - struct rtw89_vif *role_vif = sel->bind_vif[ordered_idx]; + struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx]; int ret; if (!role_vif) { @@ -712,21 +746,28 @@ static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) { struct rtw89_mcc_fill_role_selector sel = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; int ret; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (!rtwvif->chanctx_assigned) + if (!rtw89_vif_is_active_role(rtwvif)) + continue; + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n"); continue; + } - if (sel.bind_vif[rtwvif->chanctx_idx]) { + if (sel.bind_vif[rtwvif_link->chanctx_idx]) { rtw89_warn(rtwdev, "MCC skip extra vif <macid %d> on chanctx[%d]\n", - rtwvif->mac_id, rtwvif->chanctx_idx); + rtwvif_link->mac_id, rtwvif_link->chanctx_idx); continue; } - sel.bind_vif[rtwvif->chanctx_idx] = rtwvif; + sel.bind_vif[rtwvif_link->chanctx_idx] = rtwvif_link; } ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel); @@ -754,13 +795,13 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, memset(&pattern->courtesy, 0, sizeof(pattern->courtesy)); if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) { - pattern->courtesy.macid_tgt = aux->rtwvif->mac_id; - pattern->courtesy.macid_src = ref->rtwvif->mac_id; + pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id; + pattern->courtesy.macid_src = ref->rtwvif_link->mac_id; pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; pattern->courtesy.enable = true; } else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) { - pattern->courtesy.macid_tgt = ref->rtwvif->mac_id; - pattern->courtesy.macid_src = aux->rtwvif->mac_id; + pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id; + pattern->courtesy.macid_src = aux->rtwvif_link->mac_id; pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; pattern->courtesy.enable = true; } @@ -1263,7 +1304,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, u64 tsf_src; int ret; - ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif, &tsf_src); + ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return; @@ -1280,12 +1321,12 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder); tsf_ofst_tgt = bcn_intvl_src_us - remainder; - config->sync.macid_tgt = tgt->rtwvif->mac_id; - config->sync.band_tgt = tgt->rtwvif->mac_idx; - config->sync.port_tgt = tgt->rtwvif->port; - config->sync.macid_src = src->rtwvif->mac_id; - config->sync.band_src = src->rtwvif->mac_idx; - config->sync.port_src = src->rtwvif->port; + config->sync.macid_tgt = tgt->rtwvif_link->mac_id; + config->sync.band_tgt = tgt->rtwvif_link->mac_idx; + config->sync.port_tgt = tgt->rtwvif_link->port; + config->sync.macid_src = src->rtwvif_link->mac_id; + config->sync.band_src = src->rtwvif_link->mac_idx; + config->sync.port_src = src->rtwvif_link->port; config->sync.offset = tsf_ofst_tgt / 1024; config->sync.enable = true; @@ -1294,7 +1335,7 @@ static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev, config->sync.macid_tgt, config->sync.macid_src, config->sync.offset); - rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif, src->rtwvif, + rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link, config->sync.offset); } @@ -1305,13 +1346,13 @@ static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) struct rtw89_mcc_config *config = &mcc->config; u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval); u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref); - struct rtw89_vif *rtwvif = ref->rtwvif; + struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link; u64 tsf, start_tsf; u32 cur_tbtt_ofst; u64 min_time; int ret; - ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); return ret; @@ -1390,13 +1431,13 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro const struct rtw89_chan *chan; int ret; - chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); req.central_ch_seg0 = chan->channel; req.primary_ch = chan->primary_channel; req.bandwidth = chan->band_width; req.ch_band_type = chan->band_type; - req.macid = role->rtwvif->mac_id; + req.macid = role->rtwvif_link->mac_id; req.group = mcc->group; req.c2h_rpt = policy->c2h_rpt; req.tx_null_early = policy->tx_null_early; @@ -1421,7 +1462,7 @@ static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ro } ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, - role->rtwvif->mac_id, + role->rtwvif_link->mac_id, role->macid_bitmap); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -1448,7 +1489,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, slot_arg->duration = role->duration; slot_arg->role_num = 1; - chan = rtw89_chan_get(rtwdev, role->rtwvif->chanctx_idx); + chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI; slot_arg->roles[0].is_master = role == ref; @@ -1458,7 +1499,7 @@ void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, slot_arg->roles[0].primary_ch = chan->primary_channel; slot_arg->roles[0].en_tx_null = !policy->dis_tx_null; slot_arg->roles[0].null_early = policy->tx_null_early; - slot_arg->roles[0].macid = role->rtwvif->mac_id; + slot_arg->roles[0].macid = role->rtwvif_link->mac_id; slot_arg->roles[0].macid_main_bitmap = rtw89_mcc_role_fw_macid_bitmap_to_u32(role); } @@ -1569,7 +1610,7 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace) } } - req.macid = ref->rtwvif->mac_id; + req.macid = ref->rtwvif_link->mac_id; req.tsf_high = config->start_tsf >> 32; req.tsf_low = config->start_tsf; @@ -1598,7 +1639,7 @@ static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev, if (!courtesy->enable) return; - if (courtesy->macid_src == ref->rtwvif->mac_id) { + if (courtesy->macid_src == ref->rtwvif_link->mac_id) { slot_arg_src = &arg->slots[ref->slot_idx]; slot_idx_tgt = aux->slot_idx; } else { @@ -1717,9 +1758,9 @@ static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_chang struct rtw89_fw_mcc_duration req = { .group = mcc->group, .btc_in_group = false, - .start_macid = ref->rtwvif->mac_id, - .macid_x = ref->rtwvif->mac_id, - .macid_y = aux->rtwvif->mac_id, + .start_macid = ref->rtwvif_link->mac_id, + .macid_x = ref->rtwvif_link->mac_id, + .macid_y = aux->rtwvif_link->mac_id, .duration_x = ref->duration, .duration_y = aux->duration, .start_tsf_high = config->start_tsf >> 32, @@ -1813,18 +1854,18 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable) struct ieee80211_p2p_noa_desc noa_desc = {}; u64 start_time = config->start_tsf; u32 interval = config->mcc_interval; - struct rtw89_vif *rtwvif_go; + struct rtw89_vif_link *rtwvif_go; u32 duration; if (mcc->mode != RTW89_MCC_MODE_GO_STA) return; if (ref->is_go) { - rtwvif_go = ref->rtwvif; + rtwvif_go = ref->rtwvif_link; start_time += ieee80211_tu_to_usec(ref->duration); duration = config->mcc_interval - ref->duration; } else if (aux->is_go) { - rtwvif_go = aux->rtwvif; + rtwvif_go = aux->rtwvif_link; start_time += ieee80211_tu_to_usec(pattern->tob_ref) + ieee80211_tu_to_usec(config->beacon_offset) + ieee80211_tu_to_usec(pattern->toa_aux); @@ -1865,9 +1906,9 @@ static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev) return; if (ref->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true); else if (aux->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true); rtw89_mcc_handle_beacon_noa(rtwdev, true); } @@ -1882,9 +1923,9 @@ static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) return; if (ref->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false); else if (aux->is_go) - rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false); rtw89_mcc_handle_beacon_noa(rtwdev, false); } @@ -1942,7 +1983,7 @@ struct rtw89_mcc_stop_sel { static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel, const struct rtw89_mcc_role *mcc_role) { - sel->mac_id = mcc_role->rtwvif->mac_id; + sel->mac_id = mcc_role->rtwvif_link->mac_id; sel->slot_idx = mcc_role->slot_idx; } @@ -1953,7 +1994,7 @@ static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev, { struct rtw89_mcc_stop_sel *sel = data; - if (!mcc_role->rtwvif->chanctx_assigned) + if (!mcc_role->rtwvif_link->chanctx_assigned) return 0; rtw89_mcc_stop_sel_fill(sel, mcc_role); @@ -2081,7 +2122,7 @@ static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, int ret; ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, - upd->rtwvif->mac_id, + upd->rtwvif_link->mac_id, upd->macid_bitmap); if (ret) { rtw89_debug(rtwdev, RTW89_DBG_CHAN, @@ -2106,7 +2147,7 @@ static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, int i; arg.sch_idx = mcc->group; - arg.macid = upd->rtwvif->mac_id; + arg.macid = upd->rtwvif_link->mac_id; for (i = 0; i < 32; i++) { if (add & BIT(i)) { @@ -2144,7 +2185,7 @@ static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev, void *data) { struct rtw89_mcc_role upd = { - .rtwvif = mcc_role->rtwvif, + .rtwvif_link = mcc_role->rtwvif_link, }; int ret; @@ -2370,6 +2411,24 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev) rtw89_queue_chanctx_work(rtwdev); } +static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif, + enum rtw89_chanctx_idx idx1, + enum rtw89_chanctx_idx idx2) +{ + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + if (!rtwvif_link->chanctx_assigned) + continue; + + if (rtwvif_link->chanctx_idx == idx1) + rtwvif_link->chanctx_idx = idx2; + else if (rtwvif_link->chanctx_idx == idx2) + rtwvif_link->chanctx_idx = idx1; + } +} + static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx idx1, enum rtw89_chanctx_idx idx2) @@ -2386,14 +2445,8 @@ static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, swap(hal->chanctx[idx1], hal->chanctx[idx2]); - rtw89_for_each_rtwvif(rtwdev, rtwvif) { - if (!rtwvif->chanctx_assigned) - continue; - if (rtwvif->chanctx_idx == idx1) - rtwvif->chanctx_idx = idx2; - else if (rtwvif->chanctx_idx == idx2) - rtwvif->chanctx_idx = idx1; - } + rtw89_for_each_rtwvif(rtwdev, rtwvif) + __rtw89_swap_chanctx(rtwvif, idx1, idx2); cur = atomic_read(&hal->roc_chanctx_idx); if (cur == idx1) @@ -2444,14 +2497,14 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, } int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx) { struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; struct rtw89_entity_weight w = {}; - rtwvif->chanctx_idx = cfg->idx; - rtwvif->chanctx_assigned = true; + rtwvif_link->chanctx_idx = cfg->idx; + rtwvif_link->chanctx_assigned = true; cfg->ref_count++; if (cfg->idx == RTW89_CHANCTX_0) @@ -2469,7 +2522,7 @@ out: } void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx) { struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; @@ -2479,8 +2532,8 @@ void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, enum rtw89_entity_mode new; int ret; - rtwvif->chanctx_idx = RTW89_CHANCTX_0; - rtwvif->chanctx_assigned = false; + rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; + rtwvif_link->chanctx_assigned = false; cfg->ref_count--; if (cfg->ref_count != 0) diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index c6d31984e575..74de13a2e7da 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -43,18 +43,21 @@ struct rtw89_entity_weight { unsigned int active_roles; }; -static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev) +static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { struct rtw89_hal *hal = &rtwdev->hal; - return READ_ONCE(hal->entity_active); + return READ_ONCE(hal->entity_active[phy_idx]); } -static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active) +static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + bool active) { struct rtw89_hal *hal = &rtwdev->hal; - WRITE_ONCE(hal->entity_active, active); + WRITE_ONCE(hal->entity_active[phy_idx], active); } static inline @@ -106,10 +109,10 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx, u32 changed); int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx); void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_chanctx_conf *ctx); #endif diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index df51b29142aa..989e6e882c6e 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -125,6 +125,9 @@ static const u32 cxtbl[] = { 0xfafaaafa, /* 23 */ 0xfafffaff, /* 24 */ 0xea6a5a5a, /* 25 */ + 0xfaff5aff, /* 26 */ + 0xffffdfff, /* 27 */ + 0xe6555555, /* 28 */ }; static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { @@ -134,77 +137,88 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0), .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7, .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7, .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7, .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7, - .fwevntrptl = 1, .drvinfo_type = 1, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800, + .max_role_num = 6, }, {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0), .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0), .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1800, .max_role_num = 6, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800, + .max_role_num = 6, }, {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1, .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1280, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280, + .max_role_num = 5, }, {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0), .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2, .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, /* keep it to be the last as default entry */ @@ -213,7 +227,8 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1, .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1, .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0, - .fwevntrptl = 0, .drvinfo_type = 0, .info_buf = 1024, .max_role_num = 5, + .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024, + .max_role_num = 5, }, }; @@ -224,7 +239,7 @@ static const union rtw89_btc_wl_state_map btc_scanning_map = { .scan = 1, .connecting = 1, .roaming = 1, - .transacting = 1, + .dbccing = 1, ._4way = 1, }, }; @@ -3017,7 +3032,7 @@ static void _update_btc_state_map(struct rtw89_dev *rtwdev) struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info; if (wl->status.map.connecting || wl->status.map._4way || - wl->status.map.roaming) { + wl->status.map.roaming || wl->status.map.dbccing) { cx->state_map = BTC_WLINKING; } else if (wl->status.map.scan) { /* wl scan */ if (bt_linfo->status.map.inq_pag) @@ -3721,8 +3736,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) tbl_w1 = cxtbl[16]; } - btc->bt_req_en = false; - switch (type) { case BTC_CXP_USERDEF0: btc->update_policy_force = true; @@ -3744,6 +3757,10 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_WL: _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); break; + case BTC_CXP_OFF_WL2: + _slot_set_tbl(btc, CXST_OFF, cxtbl[1]); + _slot_set_type(btc, CXST_OFF, SLOT_ISO); + break; case BTC_CXP_OFF_EQ0: _slot_set_tbl(btc, CXST_OFF, cxtbl[0]); _slot_set_type(btc, CXST_OFF, SLOT_ISO); @@ -3757,6 +3774,12 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) case BTC_CXP_OFF_EQ3: _slot_set_tbl(btc, CXST_OFF, cxtbl[24]); break; + case BTC_CXP_OFF_EQ4: + _slot_set_tbl(btc, CXST_OFF, cxtbl[26]); + break; + case BTC_CXP_OFF_EQ5: + _slot_set_tbl(btc, CXST_OFF, cxtbl[27]); + break; case BTC_CXP_OFF_BWB0: _slot_set_tbl(btc, CXST_OFF, cxtbl[5]); break; @@ -3788,7 +3811,6 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) } break; case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */ - btc->bt_req_en = true; _write_scbd(rtwdev, BTC_WSCB_TDMA, true); *t = t_def[CXTD_OFF_EXT]; @@ -3831,9 +3853,9 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); break; case BTC_CXP_OFFE_2GBWMIXB: - _slot_set(btc, CXST_E2G, 0, 0x55555555, SLOT_MIX); + _slot_set(btc, CXST_E2G, 0, 0xea5a5555, SLOT_MIX); _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - cpu_to_le32(0x55555555), s_def[CXST_EBT].cxtype); + s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); break; case BTC_CXP_OFFE_WL: /* for 4-way */ _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX); @@ -3842,6 +3864,8 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) default: break; } + _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur, + s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype); _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur, s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype); break; @@ -4246,6 +4270,7 @@ static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec, _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE); break; case BTC_ANT_WRFK: + case BTC_ANT_WRFK2: rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL); _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO); _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE); @@ -4623,12 +4648,21 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev) static void _action_bt_pan(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info; + struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; + struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G); switch (btc->cx.state_map) { case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */ - _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + if (a2dp.active || !pan.exist) { + btc->dm.slot_dur[CXST_W1] = 80; + btc->dm.slot_dur[CXST_B1] = 20; + _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN); + } else { + _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN); + } break; case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */ _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN); @@ -4814,8 +4848,16 @@ static void _action_wl_rfk(struct rtw89_dev *rtwdev) rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n", __func__, rfk.band); - _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); - _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + btc->dm.tdma_instant_excute = 1; + + if (rfk.state == BTC_WRFK_ONESHOT_START || + btc->ant_type == BTC_ANT_SHARED) { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2); + _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK); + } else { + _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK); + _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK); + } } static void _set_btg_ctrl(struct rtw89_dev *rtwdev) @@ -4855,6 +4897,8 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev) if (rtwdev->dbcc_en) { if (ver->fwlrole == 0) { + wl_rinfo.dbcc_2g_phy = RTW89_PHY_MAX; + for (i = 0; i < RTW89_PHY_MAX; i++) { if (wl_dinfo->real_band[i] == RTW89_BAND_2G) wl_rinfo.dbcc_2g_phy = i; @@ -4989,18 +5033,16 @@ struct rtw89_txtime_data { bool reenable; }; -static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_txtime_data *iter_data) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_txtime_data *iter_data = - (struct rtw89_txtime_data *)data; struct rtw89_dev *rtwdev = iter_data->rtwdev; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_cx *cx = &btc->cx; struct rtw89_btc_wl_info *wl = &cx->wl; struct rtw89_btc_wl_link_info *plink = NULL; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 tx_time = iter_data->tx_time; u8 tx_retry = iter_data->tx_retry; u16 enable = iter_data->enable; @@ -5023,8 +5065,8 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* backup the original tx time before tx-limit on */ if (reenable) { - rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time); - rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry); + rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time); + rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); @@ -5032,22 +5074,37 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) /* restore the original tx time if no tx-limit */ if (!enable) { - rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true, + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true, plink->tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n", __func__, plink->tx_time, plink->tx_retry); } else { - rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time); - rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry); + rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time); + rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): set, tx_time=%d tx_retry= %d\n", __func__, tx_time, tx_retry); } } +static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_txtime_data *iter_data = + (struct rtw89_txtime_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + static void _set_wl_tx_limit(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -5231,8 +5288,14 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc; struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc; struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc; + struct rtw89_btc_dm *dm = &btc->dm; u8 profile_map = 0; + if (dm->freerun_chk) { + _action_freerun(rtwdev); + return; + } + if (bt_linfo->hfp_desc.exist) profile_map |= BTC_BT_HFP; @@ -5247,30 +5310,20 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) switch (profile_map) { case BTC_BT_NOPROFILE: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (pan.active) + if (pan.active) _action_bt_pan(rtwdev); else _action_bt_idle(rtwdev); break; case BTC_BT_HFP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hfp(rtwdev); + _action_bt_hfp(rtwdev); break; case BTC_BT_HFP | BTC_BT_HID: case BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else - _action_bt_hid(rtwdev); + _action_bt_hid(rtwdev); break; case BTC_BT_A2DP: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); - else if (a2dp.sink) + if (a2dp.sink) _action_bt_a2dpsink(rtwdev); else if (bt_linfo->multi_link.now && !hid.pair_cnt) _action_bt_a2dp_pan(rtwdev); @@ -5283,13 +5336,18 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_HFP: case BTC_BT_A2DP | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID: - if (_check_freerun(rtwdev)) - _action_freerun(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else if (pan.active) + _action_bt_a2dp_pan_hid(rtwdev); else _action_bt_a2dp_hid(rtwdev); break; case BTC_BT_A2DP | BTC_BT_PAN: - _action_bt_a2dp_pan(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan(rtwdev); break; case BTC_BT_PAN | BTC_BT_HFP: case BTC_BT_PAN | BTC_BT_HID: @@ -5299,7 +5357,10 @@ static void _action_by_bt(struct rtw89_dev *rtwdev) case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID: case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP: default: - _action_bt_a2dp_pan_hid(rtwdev); + if (a2dp.sink) + _action_bt_a2dpsink(rtwdev); + else + _action_bt_a2dp_pan_hid(rtwdev); break; } } @@ -5319,7 +5380,7 @@ static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev) policy_type = BTC_CXP_OFFE_WL; else if (btc->cx.wl.status.val & btc_scanning_map.val) policy_type = BTC_CXP_OFFE_2GBWMIXB; - else if (btc->cx.bt.link_info.profile_cnt.now == 0) + else if (btc->cx.bt.link_info.status.map.connect == 0) policy_type = BTC_CXP_OFFE_2GISOB; else policy_type = BTC_CXP_OFFE_2GBWISOB; @@ -6891,6 +6952,8 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) bt->scan_rx_low_pri = false; igno_bt = false; + dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */ + if (always_freerun) { _action_freerun(rtwdev); igno_bt = true; @@ -6929,18 +6992,9 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason) goto exit; } - if (cx->state_map == BTC_WLINKING) { - if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA || - mode == BTC_WLINK_5G) { - _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; - goto exit; - } - } - - if (wl->status.map.scan) { + if (wl->status.val & btc_scanning_map.val) { _action_wl_scan(rtwdev); - bt->scan_rx_low_pri = false; + bt->scan_rx_low_pri = true; goto exit; } @@ -7176,10 +7230,6 @@ void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band) btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++; - wl->scan_info.band[phy_idx] = band; - wl->scan_info.phy_map |= BIT(phy_idx); - _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN); - if (rtwdev->dbcc_en) { wl->dbcc_info.scan_band[phy_idx] = band; _update_dbcc_band(rtwdev, phy_idx); @@ -7374,13 +7424,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) "[BTC], %s(): bt_info[2]=0x%02x\n", __func__, bt->raw_info[2]); - /* reset to mo-connect before update */ - b->status.val = BTC_BLINK_NOCONNECT; b->profile_cnt.last = b->profile_cnt.now; - b->relink.last = b->relink.now; - a2dp->exist_last = a2dp->exist; - b->multi_link.last = b->multi_link.now; - bt->inq_pag.last = bt->inq_pag.now; b->profile_cnt.now = 0; hid->type = 0; @@ -7399,7 +7443,8 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->profile_cnt.now += (u8)hid->exist; a2dp->exist = btinfo.lb2.a2dp; b->profile_cnt.now += (u8)a2dp->exist; - pan->active = btinfo.lb2.pan; + pan->exist = btinfo.lb2.pan; + b->profile_cnt.now += (u8)pan->exist; btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK); /* parse raw info low-Byte3 */ @@ -7423,8 +7468,14 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte1 */ btinfo.val = bt->raw_info[BTC_BTINFO_H1]; b->status.map.ble_connect = btinfo.hb1.ble_connect; - if (btinfo.hb1.ble_connect) - hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU); + if (btinfo.hb1.ble_connect) { + if (hid->exist) + hid->type |= BTC_HID_BLE; + else if (btinfo.hb1.voice) + hid->type |= BTC_HID_RCU_VOICE; + else + hid->type |= BTC_HID_RCU; + } cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit); bt->reinit = btinfo.hb1.reinit; @@ -7436,7 +7487,6 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) if (bt->igno_wl && !cx->wl.status.map.rf_off) _set_bt_ignore_wlan_act(rtwdev, false); - hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0); bt->ble_scan_en = btinfo.hb1.ble_scan; cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw); @@ -7446,8 +7496,7 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) /* parse raw info high-Byte2 */ btinfo.val = bt->raw_info[BTC_BTINFO_H2]; - pan->exist = btinfo.hb2.pan_active; - b->profile_cnt.now += (u8)pan->exist; + pan->active = !!btinfo.hb2.pan_active; cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update); b->afh_update = btinfo.hb2.afh_update; @@ -7455,8 +7504,9 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) b->slave_role = btinfo.hb2.slave; hid->slot_info = btinfo.hb2.hid_slot; hid->pair_cnt = btinfo.hb2.hid_cnt; - hid->type |= (hid->slot_info == BTC_HID_218 ? - BTC_HID_218 : BTC_HID_418); + if (!b->status.map.ble_connect || hid->pair_cnt > 1) + hid->type |= (hid->slot_info == BTC_HID_218 ? + BTC_HID_218 : BTC_HID_418); /* parse raw info high-Byte3 */ btinfo.val = bt->raw_info[BTC_BTINFO_H3]; a2dp->bitpool = btinfo.hb3.a2dp_bitpool; @@ -7479,13 +7529,16 @@ static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len) _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO); } -void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, enum btc_role_state state) +void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + enum btc_role_state state) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; struct rtw89_btc *btc = &rtwdev->btc; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; @@ -7493,51 +7546,59 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif struct rtw89_btc_wl_link_info *wlinfo = NULL; u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], role is STA=%d\n", vif->type == NL80211_IFTYPE_STATION); - rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port); + rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n", chan->band_type, chan->channel, chan->band_width); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n", state == BTC_ROLE_MSTS_STA_CONN_END); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], bcn_period=%d dtim_period=%d\n", - vif->bss_conf.beacon_int, vif->bss_conf.dtim_period); + bss_conf->beacon_int, bss_conf->dtim_period); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); - if (rtwsta) { rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n", - rtwsta->mac_id); + rtwsta_link->mac_id); rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA support HE=%d VHT=%d HT=%d\n", - sta->deflink.he_cap.has_he, - sta->deflink.vht_cap.vht_supported, - sta->deflink.ht_cap.ht_supported); - if (sta->deflink.he_cap.has_he) + link_sta->he_cap.has_he, + link_sta->vht_cap.vht_supported, + link_sta->ht_cap.ht_supported); + if (link_sta->he_cap.has_he) mode |= BIT(BTC_WL_MODE_HE); - if (sta->deflink.vht_cap.vht_supported) + if (link_sta->vht_cap.vht_supported) mode |= BIT(BTC_WL_MODE_VHT); - if (sta->deflink.ht_cap.ht_supported) + if (link_sta->ht_cap.ht_supported) mode |= BIT(BTC_WL_MODE_HT); r.mode = mode; } - if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) + if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) { + rcu_read_unlock(); return; + } rtw89_debug(rtwdev, RTW89_DBG_BTC, - "[BTC], wifi_role=%d\n", rtwvif->wifi_role); + "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role); - r.role = rtwvif->wifi_role; - r.phy = rtwvif->phy_idx; - r.pid = rtwvif->port; + r.role = rtwvif_link->wifi_role; + r.phy = rtwvif_link->phy_idx; + r.pid = rtwvif_link->port; r.active = true; r.connected = MLME_LINKED; - r.bcn_period = vif->bss_conf.beacon_int; - r.dtim_period = vif->bss_conf.dtim_period; + r.bcn_period = bss_conf->beacon_int; + r.dtim_period = bss_conf->dtim_period; r.band = chan->band_type; r.ch = chan->channel; r.bw = chan->band_width; @@ -7545,10 +7606,12 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif r.chdef.center_ch = chan->channel; r.chdef.bw = chan->band_width; r.chdef.chan = chan->primary_channel; - ether_addr_copy(r.mac_addr, rtwvif->mac_addr); + ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr); + + rcu_read_unlock(); - if (rtwsta && vif->type == NL80211_IFTYPE_STATION) - r.mac_id = rtwsta->mac_id; + if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) + r.mac_id = rtwsta_link->mac_id; btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++; @@ -7779,26 +7842,26 @@ struct rtw89_btc_wl_sta_iter_data { bool is_traffic_change; }; -static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +static +void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_btc_wl_sta_iter_data *iter_data) { - struct rtw89_btc_wl_sta_iter_data *iter_data = - (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_dev *rtwdev = iter_data->rtwdev; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; const struct rtw89_btc_ver *ver = btc->ver; struct rtw89_btc_wl_info *wl = &btc->cx.wl; struct rtw89_btc_wl_link_info *link_info = NULL; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_traffic_stats *link_info_t = NULL; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_traffic_stats *stats = &rtwvif->stats; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_btc_wl_role_info *r; struct rtw89_btc_wl_role_info_v1 *r1; u32 last_tx_rate, last_rx_rate; u16 last_tx_lvl, last_rx_lvl; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u8 rssi; u8 busy = 0; u8 dir = 0; @@ -7806,11 +7869,11 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) u8 i = 0; bool is_sta_change = false, is_traffic_change = false; - rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi); link_info = &wl->link_info[port]; - link_info->stat.traffic = rtwvif->stats; + link_info->stat.traffic = *stats; link_info_t = &link_info->stat.traffic; if (link_info->connected == MLME_NO_LINK) { @@ -7858,19 +7921,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->busy_all |= busy; iter_data->dir_all |= BIT(dir); - if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 && + if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 && last_rx_rate > RTW89_HW_RATE_CCK2 && link_info_t->rx_tfc_lv > RTW89_TFC_IDLE) link_info->rx_rate_drop_cnt++; - if (last_tx_rate != rtwsta->ra_report.hw_rate || - last_rx_rate != rtwsta->rx_hw_rate || + if (last_tx_rate != rtwsta_link->ra_report.hw_rate || + last_rx_rate != rtwsta_link->rx_hw_rate || last_tx_lvl != link_info_t->tx_tfc_lv || last_rx_lvl != link_info_t->rx_tfc_lv) is_traffic_change = true; - link_info_t->tx_rate = rtwsta->ra_report.hw_rate; - link_info_t->rx_rate = rtwsta->rx_hw_rate; + link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate; + link_info_t->rx_rate = rtwsta_link->rx_hw_rate; if (link_info->role == RTW89_WIFI_ROLE_STATION || link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) { @@ -7882,19 +7945,19 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) r = &wl->role_info; r->active_role[port].tx_lvl = stats->tx_tfc_lv; r->active_role[port].rx_lvl = stats->rx_tfc_lv; - r->active_role[port].tx_rate = rtwsta->ra_report.hw_rate; - r->active_role[port].rx_rate = rtwsta->rx_hw_rate; + r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 1) { r1 = &wl->role_info_v1; r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv; r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv; - r1->active_role_v1[port].tx_rate = rtwsta->ra_report.hw_rate; - r1->active_role_v1[port].rx_rate = rtwsta->rx_hw_rate; + r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate; + r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate; } else if (ver->fwlrole == 2) { dm->trx_info.tx_lvl = stats->tx_tfc_lv; dm->trx_info.rx_lvl = stats->rx_tfc_lv; - dm->trx_info.tx_rate = rtwsta->ra_report.hw_rate; - dm->trx_info.rx_rate = rtwsta->rx_hw_rate; + dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate; + dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate; } dm->trx_info.tx_tp = link_info_t->tx_throughput; @@ -7914,6 +7977,21 @@ static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) iter_data->is_traffic_change = true; } +static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_btc_wl_sta_iter_data *iter_data = + (struct rtw89_btc_wl_sta_iter_data *)data; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data); + } +} + #define BTC_NHM_CHK_INTVL 20 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) @@ -7963,6 +8041,53 @@ void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev) } } +static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func) +{ + struct rtw89_btc *btc = &rtwdev->btc; + const struct rtw89_btc_ver *ver = btc->ver; + + switch (func) { + case BTF_EVNT_RPT: + case BTF_EVNT_BT_INFO: + case BTF_EVNT_BT_SCBD: + case BTF_EVNT_BT_REG: + case BTF_EVNT_CX_RUNINFO: + case BTF_EVNT_BT_PSD: + return func; + case BTF_EVNT_BT_DEV_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_BUF_OVERFLOW; + else + return BTF_EVNT_BT_DEV_INFO; + case BTF_EVNT_BT_LEAUDIO_INFO: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_BUF_OVERFLOW; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_BUF_OVERFLOW: + if (ver->fwc2hfunc == 0) + return BTF_EVNT_MAX; + else if (ver->fwc2hfunc == 1) + return BTF_EVNT_C2H_LOOPBACK; + else if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_C2H_LOOPBACK: + if (ver->fwc2hfunc == 2) + return func; + else + return BTF_EVNT_MAX; + case BTF_EVNT_MAX: + default: + return BTF_EVNT_MAX; + } +} + void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func) { @@ -7979,10 +8104,14 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (class != BTFC_FW_EVENT) return; + func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func); + switch (func) { - case BTF_EVNT_RPT: case BTF_EVNT_BUF_OVERFLOW: pfwinfo->event[func]++; + break; + case BTF_EVNT_RPT: + pfwinfo->event[func]++; /* Don't need rtw89_leave_ps_mode() */ btc_fw_event(rtwdev, func, buf, len); break; diff --git a/drivers/net/wireless/realtek/rtw89/coex.h b/drivers/net/wireless/realtek/rtw89/coex.h index de53b56632f7..dbdb56e063ef 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.h +++ b/drivers/net/wireless/realtek/rtw89/coex.h @@ -271,8 +271,10 @@ void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work); void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work); void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work); -void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, enum btc_role_state state); +void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + enum btc_role_state state); void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state); void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map, enum btc_wl_rfk_type type, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 4553810634c6..bba5bde95bb4 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -352,10 +352,6 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; bool entity_active; - entity_active = rtw89_get_entity_state(rtwdev); - if (!entity_active) - return; - mode = rtw89_get_entity_mode(rtwdev); switch (mode) { case RTW89_ENTITY_MODE_SCC: @@ -375,6 +371,11 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) chanctx_idx = roc_idx; phy_idx = RTW89_PHY_0; + + entity_active = rtw89_get_entity_state(rtwdev, phy_idx); + if (!entity_active) + return; + chan = rtw89_chan_get(rtwdev, chanctx_idx); chip->ops->set_txpwr(rtwdev, chan, phy_idx); } @@ -393,8 +394,6 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; bool entity_active; - entity_active = rtw89_get_entity_state(rtwdev); - mode = rtw89_entity_recalc(rtwdev); switch (mode) { case RTW89_ENTITY_MODE_SCC: @@ -416,6 +415,8 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) mac_idx = RTW89_MAC_0; phy_idx = RTW89_PHY_0; + entity_active = rtw89_get_entity_state(rtwdev, phy_idx); + chan = rtw89_chan_get(rtwdev, chanctx_idx); chan_rcd = rtw89_chan_rcd_get(rtwdev, chanctx_idx); @@ -432,19 +433,10 @@ int rtw89_set_channel(struct rtw89_dev *rtwdev) rtw89_chip_rfk_band_changed(rtwdev, phy_idx, chan); } - rtw89_set_entity_state(rtwdev, true); + rtw89_set_entity_state(rtwdev, phy_idx, true); return 0; } -void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_chan *chan) -{ - const struct cfg80211_chan_def *chandef; - - chandef = rtw89_chandef_get(rtwdev, rtwvif->chanctx_idx); - rtw89_get_channel_params(chandef, chan); -} - static enum rtw89_core_tx_type rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, struct sk_buff *skb) @@ -463,8 +455,9 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req, enum btc_pkt_type pkt_type) { - struct ieee80211_sta *sta = tx_req->sta; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct ieee80211_link_sta *link_sta; struct sk_buff *skb = tx_req->skb; struct rtw89_sta *rtwsta; u8 ampdu_num; @@ -478,21 +471,26 @@ rtw89_core_tx_update_ampdu_info(struct rtw89_dev *rtwdev, if (!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_AMPDU)) return; - if (!sta) { + if (!rtwsta_link) { rtw89_warn(rtwdev, "cannot set ampdu info without sta\n"); return; } tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; - rtwsta = (struct rtw89_sta *)sta->drv_priv; + rtwsta = rtwsta_link->rtwsta; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); ampdu_num = (u8)((rtwsta->ampdu_params[tid].agg_num ? rtwsta->ampdu_params[tid].agg_num : - 4 << sta->deflink.ht_cap.ampdu_factor) - 1); + 4 << link_sta->ht_cap.ampdu_factor) - 1); desc_info->agg_en = true; - desc_info->ampdu_density = sta->deflink.ht_cap.ampdu_density; + desc_info->ampdu_density = link_sta->ht_cap.ampdu_density; desc_info->ampdu_num = ampdu_num; + + rcu_read_unlock(); } static void @@ -569,9 +567,13 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan) { struct sk_buff *skb = tx_req->skb; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = tx_info->control.vif; + struct ieee80211_bss_conf *bss_conf; u16 lowest_rate; + u16 rate; if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE || (vif && vif->p2p)) @@ -581,25 +583,35 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta) + if (!rtwvif_link) return lowest_rate; - return __ffs(vif->bss_conf.basic_rates) + lowest_rate; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->basic_rates || !rtwsta_link) { + rate = lowest_rate; + goto out; + } + + rate = __ffs(bss_conf->basic_rates) + lowest_rate; + +out: + rcu_read_unlock(); + + return rate; } static u8 rtw89_core_tx_get_mac_id(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; - if (!sta) - return rtwvif->mac_id; + if (!rtwsta_link) + return rtwvif_link->mac_id; - rtwsta = (struct rtw89_sta *)sta->drv_priv; - return rtwsta->mac_id; + return rtwsta_link->mac_id; } static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev, @@ -618,11 +630,10 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); struct sk_buff *skb = tx_req->skb; u8 qsel, ch_dma; @@ -631,7 +642,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, desc_info->qsel = qsel; desc_info->ch_dma = ch_dma; - desc_info->port = desc_info->hiq ? rtwvif->port : 0; + desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL; desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE; @@ -701,26 +712,36 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req, enum btc_pkt_type pkt_type) { - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct sk_buff *skb = tx_req->skb; struct ieee80211_hdr *hdr = (void *)skb->data; + struct ieee80211_link_sta *link_sta; __le16 fc = hdr->frame_control; /* AP IOT issue with EAPoL, ARP and DHCP */ if (pkt_type < PACKET_MAX) return false; - if (!sta || !sta->deflink.he_cap.has_he) + if (!rtwsta_link) return false; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (!link_sta->he_cap.has_he) { + rcu_read_unlock(); + return false; + } + + rcu_read_unlock(); + if (!ieee80211_is_data_qos(fc)) return false; if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN) return false; - if (rtwsta && rtwsta->ra_report.might_fallback_legacy) + if (rtwsta_link && rtwsta_link->ra_report.might_fallback_legacy) return false; return true; @@ -730,8 +751,7 @@ static void __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct sk_buff *skb = tx_req->skb; struct ieee80211_hdr *hdr = (void *)skb->data; __le16 fc = hdr->frame_control; @@ -747,7 +767,7 @@ __rtw89_core_tx_adjust_he_qos_htc(struct rtw89_dev *rtwdev, hdr = data; htc = data + hdr_len; hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_ORDER); - *htc = rtwsta->htc_template ? rtwsta->htc_template : + *htc = rtwsta_link->htc_template ? rtwsta_link->htc_template : le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) | le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_CAS, RTW89_HTC_MASK_CTL_ID); @@ -761,8 +781,7 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, enum btc_pkt_type pkt_type) { struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; - struct ieee80211_vif *vif = tx_req->vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; if (!__rtw89_core_tx_check_he_qos_htc(rtwdev, tx_req, pkt_type)) goto desc_bk; @@ -773,23 +792,25 @@ rtw89_core_tx_update_he_qos_htc(struct rtw89_dev *rtwdev, desc_info->a_ctrl_bsr = true; desc_bk: - if (!rtwvif || rtwvif->last_a_ctrl == desc_info->a_ctrl_bsr) + if (!rtwvif_link || rtwvif_link->last_a_ctrl == desc_info->a_ctrl_bsr) return; - rtwvif->last_a_ctrl = desc_info->a_ctrl_bsr; + rtwvif_link->last_a_ctrl = desc_info->a_ctrl_bsr; desc_info->bk = true; } static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; - enum rtw89_chanctx_idx idx = rtwvif->chanctx_idx; + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx); + struct ieee80211_link_sta *link_sta; u16 lowest_rate; + u16 rate; if (rate_pattern->enable) return rate_pattern->rate; @@ -801,20 +822,31 @@ static u16 rtw89_core_get_data_rate(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - if (!sta || !sta->deflink.supp_rates[chan->band_type]) + if (!rtwsta_link) return lowest_rate; - return __ffs(sta->deflink.supp_rates[chan->band_type]) + lowest_rate; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (!link_sta->supp_rates[chan->band_type]) { + rate = lowest_rate; + goto out; + } + + rate = __ffs(link_sta->supp_rates[chan->band_type]) + lowest_rate; + +out: + rcu_read_unlock(); + + return rate; } static void rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { - struct ieee80211_vif *vif = tx_req->vif; - struct ieee80211_sta *sta = tx_req->sta; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_vif_link *rtwvif_link = tx_req->rtwvif_link; + struct rtw89_sta_link *rtwsta_link = tx_req->rtwsta_link; struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; struct sk_buff *skb = tx_req->skb; u8 tid, tid_indicate; @@ -829,10 +861,10 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, desc_info->tid_indicate = tid_indicate; desc_info->qsel = qsel; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); - desc_info->port = desc_info->hiq ? rtwvif->port : 0; - desc_info->er_cap = rtwsta ? rtwsta->er_cap : false; - desc_info->stbc = rtwsta ? rtwsta->ra.stbc_cap : false; - desc_info->ldpc = rtwsta ? rtwsta->ra.ldpc_cap : false; + desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; + desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false; + desc_info->stbc = rtwsta_link ? rtwsta_link->ra.stbc_cap : false; + desc_info->ldpc = rtwsta_link ? rtwsta_link->ra.ldpc_cap : false; /* enable wd_info for AMPDU */ desc_info->en_wd_info = true; @@ -1027,13 +1059,34 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev, int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel) { + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_core_tx_request tx_req = {0}; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_vif_link *rtwvif_link; int ret; + /* By default, driver writes tx via the link on HW-0. And then, + * according to links' status, HW can change tx to another link. + */ + + if (rtwsta) { + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "tx: find no sta link on HW-0\n"); + return -ENOLINK; + } + } + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "tx: find no vif link on HW-0\n"); + return -ENOLINK; + } + tx_req.skb = skb; - tx_req.sta = sta; - tx_req.vif = vif; + tx_req.rtwvif_link = rtwvif_link; + tx_req.rtwsta_link = rtwsta_link; rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); @@ -1514,16 +1567,24 @@ static u8 rtw89_get_data_rate_nss(struct rtw89_dev *rtwdev, u16 data_rate) static void rtw89_core_rx_process_phy_ppdu_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_rx_phy_ppdu *phy_ppdu = (struct rtw89_rx_phy_ppdu *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_dev *rtwdev = rtwsta->rtwdev; struct rtw89_hal *hal = &rtwdev->hal; + struct rtw89_sta_link *rtwsta_link; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; u8 ant_pos = U8_MAX; u8 evm_pos = 0; int i; - if (rtwsta->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; + + if (rtwsta_link->mac_id != phy_ppdu->mac_id || !phy_ppdu->to_self) return; if (hal->ant_diversity && hal->antenna_rx) { @@ -1531,22 +1592,24 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data, evm_pos = ant_pos; } - ewma_rssi_add(&rtwsta->avg_rssi, phy_ppdu->rssi_avg); + ewma_rssi_add(&rtwsta_link->avg_rssi, phy_ppdu->rssi_avg); if (ant_pos < ant_num) { - ewma_rssi_add(&rtwsta->rssi[ant_pos], phy_ppdu->rssi[0]); + ewma_rssi_add(&rtwsta_link->rssi[ant_pos], phy_ppdu->rssi[0]); } else { for (i = 0; i < rtwdev->chip->rf_path_num; i++) - ewma_rssi_add(&rtwsta->rssi[i], phy_ppdu->rssi[i]); + ewma_rssi_add(&rtwsta_link->rssi[i], phy_ppdu->rssi[i]); } if (phy_ppdu->ofdm.has && (phy_ppdu->has_data || phy_ppdu->has_bcn)) { - ewma_snr_add(&rtwsta->avg_snr, phy_ppdu->ofdm.avg_snr); + ewma_snr_add(&rtwsta_link->avg_snr, phy_ppdu->ofdm.avg_snr); if (rtw89_get_data_rate_nss(rtwdev, phy_ppdu->rate) == 1) { - ewma_evm_add(&rtwsta->evm_1ss, phy_ppdu->ofdm.evm_min); + ewma_evm_add(&rtwsta_link->evm_1ss, phy_ppdu->ofdm.evm_min); } else { - ewma_evm_add(&rtwsta->evm_min[evm_pos], phy_ppdu->ofdm.evm_min); - ewma_evm_add(&rtwsta->evm_max[evm_pos], phy_ppdu->ofdm.evm_max); + ewma_evm_add(&rtwsta_link->evm_min[evm_pos], + phy_ppdu->ofdm.evm_min); + ewma_evm_add(&rtwsta_link->evm_max[evm_pos], + phy_ppdu->ofdm.evm_max); } } } @@ -1876,17 +1939,19 @@ struct rtw89_vif_rx_stats_iter_data { }; static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct sk_buff *skb) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct ieee80211_trigger *tf = (struct ieee80211_trigger *)skb->data; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u8 *pos, *end, type, tf_bw; u16 aid, tf_rua; - if (!ether_addr_equal(vif->bss_conf.bssid, tf->ta) || - rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || - rtwvif->net_type == RTW89_NET_TYPE_NO_LINK) + if (!ether_addr_equal(bss_conf->bssid, tf->ta) || + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION || + rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK) return; type = le64_get_bits(tf->common_info, IEEE80211_TRIGGER_TYPE_MASK); @@ -1915,7 +1980,7 @@ static void rtw89_stats_trigger_frame(struct rtw89_dev *rtwdev, rtwdev->stats.rx_tf_acc++; if (tf_bw == IEEE80211_TRIGGER_ULBW_160_80P80MHZ && rua <= NL80211_RATE_INFO_HE_RU_ALLOC_106) - rtwvif->pwr_diff_en = true; + rtwvif_link->pwr_diff_en = true; break; } @@ -1986,7 +2051,7 @@ static void rtw89_core_cancel_6ghz_probe_tx(struct rtw89_dev *rtwdev, ieee80211_queue_work(rtwdev->hw, &rtwdev->cancel_6ghz_probe_work); } -static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, +static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link, struct ieee80211_hdr *hdr, size_t len) { struct ieee80211_mgmt *mgmt = (typeof(mgmt))hdr; @@ -1994,20 +2059,22 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif *rtwvif, if (len < offsetof(typeof(*mgmt), u.beacon.variable)) return; - WRITE_ONCE(rtwvif->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); + WRITE_ONCE(rtwvif_link->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); } static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_vif_rx_stats_iter_data *iter_data = data; struct rtw89_dev *rtwdev = iter_data->rtwdev; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; struct sk_buff *skb = iter_data->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rtw89_rx_phy_ppdu *phy_ppdu = iter_data->phy_ppdu; + struct ieee80211_bss_conf *bss_conf; + struct rtw89_vif_link *rtwvif_link; const u8 *bssid = iter_data->bssid; if (rtwdev->scanning && @@ -2015,33 +2082,49 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, ieee80211_is_probe_resp(hdr->frame_control))) rtw89_core_cancel_6ghz_probe_tx(rtwdev, skb); - if (!vif->bss_conf.bssid) - return; + rcu_read_lock(); + + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) + goto out; + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->bssid) + goto out; if (ieee80211_is_trigger(hdr->frame_control)) { - rtw89_stats_trigger_frame(rtwdev, vif, skb); - return; + rtw89_stats_trigger_frame(rtwdev, rtwvif_link, bss_conf, skb); + goto out; } - if (!ether_addr_equal(vif->bss_conf.bssid, bssid)) - return; + if (!ether_addr_equal(bss_conf->bssid, bssid)) + goto out; if (ieee80211_is_beacon(hdr->frame_control)) { if (vif->type == NL80211_IFTYPE_STATION && !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags)) { - rtw89_vif_sync_bcn_tsf(rtwvif, hdr, skb->len); + rtw89_vif_sync_bcn_tsf(rtwvif_link, hdr, skb->len); rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu); } pkt_stat->beacon_nr++; + + if (phy_ppdu) + ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg); } - if (!ether_addr_equal(vif->addr, hdr->addr1)) - return; + if (!ether_addr_equal(bss_conf->addr, hdr->addr1)) + goto out; if (desc_info->data_rate < RTW89_HW_RATE_NR) pkt_stat->rx_rate_cnt[desc_info->data_rate]++; rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); + +out: + rcu_read_unlock(); } static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, @@ -2432,15 +2515,23 @@ void rtw89_core_stats_sta_rx_status_iter(void *data, struct ieee80211_sta *sta) struct rtw89_core_iter_rx_status *iter_data = (struct rtw89_core_iter_rx_status *)data; struct ieee80211_rx_status *rx_status = iter_data->rx_status; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; struct rtw89_rx_desc_info *desc_info = iter_data->desc_info; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; u8 mac_id = iter_data->mac_id; - if (mac_id != rtwsta->mac_id) + /* FIXME: For single link, taking link on HW-0 here is okay. But, when + * enabling multiple active links, we should determine the right link. + */ + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; + + if (mac_id != rtwsta_link->mac_id) return; - rtwsta->rx_status = *rx_status; - rtwsta->rx_hw_rate = desc_info->data_rate; + rtwsta_link->rx_status = *rx_status; + rtwsta_link->rx_hw_rate = desc_info->data_rate; } static void rtw89_core_stats_sta_rx_status(struct rtw89_dev *rtwdev, @@ -2546,6 +2637,10 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; + /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */ + if (rtwdev->support_mlo) + return RTW89_PS_MODE_NONE; + if (rtw89_disable_ps_mode || !chip->ps_mode_supported || RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) return RTW89_PS_MODE_NONE; @@ -2658,7 +2753,7 @@ static void rtw89_core_ba_work(struct work_struct *work) list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) { struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); u8 tid = txq->tid; if (!sta) { @@ -2686,8 +2781,8 @@ skip_ba_work: spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { struct rtw89_txq *rtwtxq, *tmp; @@ -2701,8 +2796,8 @@ static void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { struct rtw89_txq *rtwtxq, *tmp; @@ -2718,10 +2813,10 @@ static void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, spin_unlock_bh(&rtwdev->ba_lock); } -static void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta) +void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct sk_buff *skb, *tmp; skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { @@ -2762,7 +2857,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev, struct ieee80211_hw *hw = rtwdev->hw; struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq); struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); if (test_bit(RTW89_TXQ_F_FORBID_BA, &rtwtxq->flags)) return; @@ -2838,10 +2933,19 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, bool *sched_txq, bool *reinvoke) { struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; - struct ieee80211_sta *sta = txq->sta; - struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(txq->sta); + struct rtw89_sta_link *rtwsta_link; - if (!sta || rtwsta->max_agg_wait <= 0) + if (!rtwsta) + return false; + + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) { + rtw89_err(rtwdev, "agg wait: find no link on HW-0\n"); + return false; + } + + if (rtwsta_link->max_agg_wait <= 0) return false; if (rtwdev->stats.tx_tfc_lv <= RTW89_TFC_MID) @@ -2855,7 +2959,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev, return false; } - if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta->max_agg_wait) { + if (*frame_cnt == 1 && rtwtxq->wait_cnt < rtwsta_link->max_agg_wait) { *reinvoke = true; rtwtxq->wait_cnt++; return true; @@ -2879,7 +2983,7 @@ static void rtw89_core_txq_schedule(struct rtw89_dev *rtwdev, u8 ac, bool *reinv ieee80211_txq_schedule_start(hw, ac); while ((txq = ieee80211_next_txq(hw, ac))) { rtwtxq = (struct rtw89_txq *)txq->drv_priv; - rtwvif = (struct rtw89_vif *)txq->vif->drv_priv; + rtwvif = vif_to_rtwvif(txq->vif); if (rtwvif->offchan) { ieee80211_return_txq(hw, txq, true); @@ -2955,16 +3059,23 @@ static void rtw89_forbid_ba_work(struct work_struct *w) static void rtw89_core_sta_pending_tx_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif_target = data, *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_vif_link *target = data; + struct rtw89_vif_link *rtwvif_link; struct sk_buff *skb, *tmp; + unsigned int link_id; int qsel, ret; - if (rtwvif->chanctx_idx != rtwvif_target->chanctx_idx) - return; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->chanctx_idx == target->chanctx_idx) + goto bottom; + + return; +bottom: if (skb_queue_len(&rtwsta->roc_queue) == 0) return; @@ -2982,17 +3093,17 @@ static void rtw89_core_sta_pending_tx_iter(void *data, } static void rtw89_core_handle_sta_pending_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_core_sta_pending_tx_iter, - rtwvif); + rtwvif_link); } static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool qos, bool ps) + struct rtw89_vif_link *rtwvif_link, bool qos, bool ps) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; struct sk_buff *skb; @@ -3002,7 +3113,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, return 0; rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + sta = ieee80211_find_sta(vif, vif->cfg.ap_addr); if (!sta) { ret = -EINVAL; goto out; @@ -3040,31 +3151,48 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; + struct rtw89_vif_link *rtwvif_link; struct cfg80211_chan_def roc_chan; - struct rtw89_vif *tmp; + struct rtw89_vif *tmp_vif; + u32 reg; int ret; lockdep_assert_held(&rtwdev->mutex); rtw89_leave_ips_by_hwflags(rtwdev); rtw89_leave_lps(rtwdev); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "roc start: find no link on HW-0\n"); + return; + } + rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_ROC); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, true); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, true); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-1 failed: %d\n", ret); - rtw89_for_each_rtwvif(rtwdev, tmp) - if (tmp->chanctx_idx == rtwvif->chanctx_idx) - tmp->offchan = true; + rtw89_for_each_rtwvif(rtwdev, tmp_vif) { + struct rtw89_vif_link *tmp_link; + unsigned int link_id; + + rtw89_vif_for_each_link(tmp_vif, tmp_link, link_id) { + if (tmp_link->chanctx_idx == rtwvif_link->chanctx_idx) { + tmp_vif->offchan = true; + break; + } + } + } cfg80211_chandef_create(&roc_chan, &roc->chan, NL80211_CHAN_NO_HT); - rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, &roc_chan); + rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, &roc_chan); rtw89_set_channel(rtwdev); - rtw89_write32_clr(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_clr(rtwdev, reg, B_AX_A_UC_CAM_MATCH | B_AX_A_BC_CAM_MATCH); ieee80211_ready_on_channel(hw); cancel_delayed_work(&rtwvif->roc.roc_work); @@ -3077,7 +3205,9 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; - struct rtw89_vif *tmp; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *tmp_vif; + u32 reg; int ret; lockdep_assert_held(&rtwdev->mutex); @@ -3087,24 +3217,27 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_leave_ips_by_hwflags(rtwdev); rtw89_leave_lps(rtwdev); - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rtwdev->hal.rx_fltr); + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "roc end: find no link on HW-0\n"); + return; + } + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); roc->state = RTW89_ROC_IDLE; - rtw89_config_roc_chandef(rtwdev, rtwvif->chanctx_idx, NULL); + rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL); rtw89_chanctx_proceed(rtwdev); - ret = rtw89_core_send_nullfunc(rtwdev, rtwvif, true, false); + ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false); if (ret) rtw89_debug(rtwdev, RTW89_DBG_TXRX, "roc send null-0 failed: %d\n", ret); - rtw89_for_each_rtwvif(rtwdev, tmp) - if (tmp->chanctx_idx == rtwvif->chanctx_idx) - tmp->offchan = false; + rtw89_for_each_rtwvif(rtwdev, tmp_vif) + tmp_vif->offchan = false; - rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif); + rtw89_core_handle_sta_pending_tx(rtwdev, rtwvif_link); queue_work(rtwdev->txq_wq, &rtwdev->txq_work); if (hw->conf.flags & IEEE80211_CONF_IDLE) @@ -3188,39 +3321,52 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; bool tfc_changed; tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); + rtw89_for_each_rtwvif(rtwdev, rtwvif) { rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); - rtw89_fw_h2c_tp_offload(rtwdev, rtwvif); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); } return tfc_changed; } -static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - if ((rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) || - rtwvif->tdls_peer) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) return; - if (rtwvif->offchan) - return; - - if (rtwvif->stats.tx_tfc_lv == RTW89_TFC_IDLE && - rtwvif->stats.rx_tfc_lv == RTW89_TFC_IDLE) - rtw89_enter_lps(rtwdev, rtwvif, true); + rtw89_enter_lps(rtwdev, rtwvif_link, true); } static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + if (rtwvif->tdls_peer) + continue; + if (rtwvif->offchan) + continue; + + if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE || + rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) + continue; - rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_vif_enter_lps(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_vif_enter_lps(rtwdev, rtwvif_link); + } } static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) @@ -3234,14 +3380,16 @@ static void rtw89_core_rfk_track(struct rtw89_dev *rtwdev) rtw89_chip_rfk_track(rtwdev); } -void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_P2P_PS_CHANGE); else - rtw89_process_p2p_ps(rtwdev, vif); + rtw89_process_p2p_ps(rtwdev, rtwvif_link, bss_conf); } void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, @@ -3326,7 +3474,8 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits) } int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_cam_info *cam_info = &rtwdev->cam_info; @@ -3363,7 +3512,7 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, } entry->tid = tid; - list_add_tail(&entry->list, &rtwsta->ba_cam_list); + list_add_tail(&entry->list, &rtwsta_link->ba_cam_list); *cam_idx = idx; @@ -3371,7 +3520,8 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, } int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx) + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx) { struct rtw89_cam_info *cam_info = &rtwdev->cam_info; struct rtw89_ba_cam_entry *entry = NULL, *tmp; @@ -3379,7 +3529,7 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, lockdep_assert_held(&rtwdev->mutex); - list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) { + list_for_each_entry_safe(entry, tmp, &rtwsta_link->ba_cam_list, list) { if (entry->tid != tid) continue; @@ -3396,24 +3546,25 @@ int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, #define RTW89_TYPE_MAPPING(_type) \ case NL80211_IFTYPE_ ## _type: \ - rtwvif->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_ ## _type; \ break -void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) +void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_bss_conf *bss_conf; switch (vif->type) { case NL80211_IFTYPE_STATION: if (vif->p2p) - rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_CLIENT; else - rtwvif->wifi_role = RTW89_WIFI_ROLE_STATION; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_STATION; break; case NL80211_IFTYPE_AP: if (vif->p2p) - rtwvif->wifi_role = RTW89_WIFI_ROLE_P2P_GO; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_P2P_GO; else - rtwvif->wifi_role = RTW89_WIFI_ROLE_AP; + rtwvif_link->wifi_role = RTW89_WIFI_ROLE_AP; break; RTW89_TYPE_MAPPING(ADHOC); RTW89_TYPE_MAPPING(MONITOR); @@ -3426,23 +3577,27 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: - rtwvif->net_type = RTW89_NET_TYPE_AP_MODE; - rtwvif->self_role = RTW89_SELF_ROLE_AP; + rtwvif_link->net_type = RTW89_NET_TYPE_AP_MODE; + rtwvif_link->self_role = RTW89_SELF_ROLE_AP; break; case NL80211_IFTYPE_ADHOC: - rtwvif->net_type = RTW89_NET_TYPE_AD_HOC; - rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; + rtwvif_link->net_type = RTW89_NET_TYPE_AD_HOC; + rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; break; case NL80211_IFTYPE_STATION: if (assoc) { - rtwvif->net_type = RTW89_NET_TYPE_INFRA; - rtwvif->trigger = vif->bss_conf.he_support; + rtwvif_link->net_type = RTW89_NET_TYPE_INFRA; + + rcu_read_lock(); + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + rtwvif_link->trigger = bss_conf->he_support; + rcu_read_unlock(); } else { - rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; - rtwvif->trigger = false; + rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; + rtwvif_link->trigger = false; } - rtwvif->self_role = RTW89_SELF_ROLE_CLIENT; - rtwvif->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; + rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT; + rtwvif_link->addr_cam.sec_ent_mode = RTW89_ADDR_CAM_SEC_NORMAL; break; case NL80211_IFTYPE_MONITOR: break; @@ -3452,137 +3607,110 @@ void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc) } } -int rtw89_core_sta_add(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); struct rtw89_hal *hal = &rtwdev->hal; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; int i; int ret; - rtwsta->rtwdev = rtwdev; - rtwsta->rtwvif = rtwvif; - rtwsta->prev_rssi = 0; - INIT_LIST_HEAD(&rtwsta->ba_cam_list); - skb_queue_head_init(&rtwsta->roc_queue); - - for (i = 0; i < ARRAY_SIZE(sta->txq); i++) - rtw89_core_txq_init(rtwdev, sta->txq[i]); - - ewma_rssi_init(&rtwsta->avg_rssi); - ewma_snr_init(&rtwsta->avg_snr); - ewma_evm_init(&rtwsta->evm_1ss); + rtwsta_link->prev_rssi = 0; + INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); + ewma_rssi_init(&rtwsta_link->avg_rssi); + ewma_snr_init(&rtwsta_link->avg_snr); + ewma_evm_init(&rtwsta_link->evm_1ss); for (i = 0; i < ant_num; i++) { - ewma_rssi_init(&rtwsta->rssi[i]); - ewma_evm_init(&rtwsta->evm_min[i]); - ewma_evm_init(&rtwsta->evm_max[i]); + ewma_rssi_init(&rtwsta_link->rssi[i]); + ewma_evm_init(&rtwsta_link->evm_min[i]); + ewma_evm_init(&rtwsta_link->evm_max[i]); } if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - /* for station mode, assign the mac_id from itself */ - rtwsta->mac_id = rtwvif->mac_id; - /* must do rtw89_reg_6ghz_recalc() before rfk channel */ - ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); + ret = rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); if (ret) return ret; - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_CONN_START); - rtw89_chip_rfk_channel(rtwdev, rtwvif); + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { - rtwsta->mac_id = rtw89_acquire_mac_id(rtwdev); - if (rtwsta->mac_id == RTW89_MAX_MAC_ID_NUM) - return -ENOSPC; - - ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta->mac_id, false); + ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); if (ret) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); rtw89_warn(rtwdev, "failed to send h2c macid pause\n"); return ret; } - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_CREATE); if (ret) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } - ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) return ret; - ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) return ret; - - rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; } -int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); if (vif->type == NL80211_IFTYPE_STATION) - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, false); - - rtwdev->total_sta_assoc--; - if (sta->tdls) - rtwvif->tdls_peer--; - rtwsta->disassoc = true; + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); return 0; } -int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); int ret; - rtw89_mac_bf_monitor_calc(rtwdev, sta, true); - rtw89_mac_bf_disassoc(rtwdev, vif, sta); - rtw89_core_free_sta_pending_ba(rtwdev, sta); - rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); - rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, true); + rtw89_mac_bf_disassoc(rtwdev, rtwvif_link, rtwsta_link); if (vif->type == NL80211_IFTYPE_AP || sta->tdls) - rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); + rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); if (sta->tdls) - rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); + rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - rtw89_vif_type_mapping(vif, false); - rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, true); + rtw89_vif_type_mapping(rtwvif_link, false); + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, true); } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); return ret; } - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, true); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, true); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -3591,106 +3719,114 @@ int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, return ret; } -int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif, rtwsta); + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, + rtwsta_link); const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); int ret; if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { if (sta->tdls) { - ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif, bssid_cam, sta->addr); + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + ret = rtw89_cam_init_bssid_cam(rtwdev, rtwvif_link, bssid_cam, + link_sta->addr); if (ret) { rtw89_warn(rtwdev, "failed to send h2c init bssid cam for TDLS\n"); + rcu_read_unlock(); return ret; } + + rcu_read_unlock(); } - ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta->addr_cam, bssid_cam); + ret = rtw89_cam_init_addr_cam(rtwdev, &rtwsta_link->addr_cam, bssid_cam); if (ret) { rtw89_warn(rtwdev, "failed to send h2c init addr cam\n"); return ret; } } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cmac table\n"); return ret; } - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, false); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, false); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } - rtwdev->total_sta_assoc++; - if (sta->tdls) - rtwvif->tdls_peer++; - rtw89_phy_ra_assoc(rtwdev, sta); - rtw89_mac_bf_assoc(rtwdev, vif, sta); - rtw89_mac_bf_monitor_calc(rtwdev, sta, false); + rtw89_phy_ra_assoc(rtwdev, rtwsta_link); + rtw89_mac_bf_assoc(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_bf_monitor_calc(rtwdev, rtwsta_link, false); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); if (bss_conf->he_support && !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)) - rtwsta->er_cap = true; + rtwsta_link->er_cap = true; - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rcu_read_unlock(); + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_CONN_END); - rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta->htc_template, chan); - rtw89_phy_ul_tb_assoc(rtwdev, rtwvif); + rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan); + rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); + ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); if (ret) { rtw89_warn(rtwdev, "failed to send h2c general packet\n"); return ret; } - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); } return ret; } -int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); int ret; if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - rtw89_reg_6ghz_recalc(rtwdev, rtwvif, false); - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, false); + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link, BTC_ROLE_MSTS_STA_DIS_CONN); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { - rtw89_release_mac_id(rtwdev, rtwsta->mac_id); - - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_REMOVE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c role info\n"); return ret; } - - rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); } return 0; @@ -4152,15 +4288,16 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev) void rtw89_core_update_beacon_work(struct work_struct *work) { struct rtw89_dev *rtwdev; - struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, - update_beacon_work); + struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, + update_beacon_work); - if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE) return; - rtwdev = rtwvif->rtwdev; + rtwdev = rtwvif_link->rtwvif->rtwdev; + mutex_lock(&rtwdev->mutex); - rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); mutex_unlock(&rtwdev->mutex); } @@ -4266,8 +4403,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_phy_dm_init(rtwdev); - rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); - rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + rtw89_mac_cfg_ppdu_status_bands(rtwdev, true); + rtw89_mac_update_rts_threshold(rtwdev); rtw89_tas_reset(rtwdev); @@ -4355,6 +4492,168 @@ void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id) clear_bit(mac_id, rtwdev->mac_id_map); } +void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + u8 mac_id, u8 port) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 support_link_num = chip->support_link_num; + u8 support_mld_num = 0; + unsigned int link_id; + u8 index; + + bitmap_zero(rtwvif->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + rtwvif->links[link_id] = NULL; + + rtwvif->rtwdev = rtwdev; + + if (rtwdev->support_mlo) { + rtwvif->links_inst_valid_num = support_link_num; + support_mld_num = chip->support_macid_num / support_link_num; + } else { + rtwvif->links_inst_valid_num = 1; + } + + for (index = 0; index < rtwvif->links_inst_valid_num; index++) { + struct rtw89_vif_link *inst = &rtwvif->links_inst[index]; + + inst->rtwvif = rtwvif; + inst->mac_id = mac_id + index * support_mld_num; + inst->mac_idx = RTW89_MAC_0 + index; + inst->phy_idx = RTW89_PHY_0 + index; + + /* multi-link use the same port id on different HW bands */ + inst->port = port; + } +} + +void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta, u8 mac_id) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u8 support_link_num = chip->support_link_num; + u8 support_mld_num = 0; + unsigned int link_id; + u8 index; + + bitmap_zero(rtwsta->links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) + rtwsta->links[link_id] = NULL; + + rtwsta->rtwdev = rtwdev; + rtwsta->rtwvif = rtwvif; + + if (rtwdev->support_mlo) { + rtwsta->links_inst_valid_num = support_link_num; + support_mld_num = chip->support_macid_num / support_link_num; + } else { + rtwsta->links_inst_valid_num = 1; + } + + for (index = 0; index < rtwsta->links_inst_valid_num; index++) { + struct rtw89_sta_link *inst = &rtwsta->links_inst[index]; + + inst->rtwvif_link = &rtwvif->links_inst[index]; + + inst->rtwsta = rtwsta; + inst->mac_id = mac_id + index * support_mld_num; + } +} + +struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, + unsigned int link_id) +{ + struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; + u8 index; + int ret; + + if (rtwvif_link) + return rtwvif_link; + + index = find_first_zero_bit(rtwvif->links_inst_map, + rtwvif->links_inst_valid_num); + if (index == rtwvif->links_inst_valid_num) { + ret = -EBUSY; + goto err; + } + + rtwvif_link = &rtwvif->links_inst[index]; + rtwvif_link->link_id = link_id; + + set_bit(index, rtwvif->links_inst_map); + rtwvif->links[link_id] = rtwvif_link; + return rtwvif_link; + +err: + rtw89_err(rtwvif->rtwdev, "vif (link_id %u) failed to set link: %d\n", + link_id, ret); + return NULL; +} + +void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id) +{ + struct rtw89_vif_link **container = &rtwvif->links[link_id]; + struct rtw89_vif_link *link = *container; + u8 index; + + if (!link) + return; + + index = rtw89_vif_link_inst_get_index(link); + clear_bit(index, rtwvif->links_inst_map); + *container = NULL; +} + +struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, + unsigned int link_id) +{ + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_vif_link *rtwvif_link = rtwvif->links[link_id]; + struct rtw89_sta_link *rtwsta_link = rtwsta->links[link_id]; + u8 index; + int ret; + + if (rtwsta_link) + return rtwsta_link; + + if (!rtwvif_link) { + ret = -ENOLINK; + goto err; + } + + index = rtw89_vif_link_inst_get_index(rtwvif_link); + if (test_bit(index, rtwsta->links_inst_map)) { + ret = -EBUSY; + goto err; + } + + rtwsta_link = &rtwsta->links_inst[index]; + rtwsta_link->link_id = link_id; + + set_bit(index, rtwsta->links_inst_map); + rtwsta->links[link_id] = rtwsta_link; + return rtwsta_link; + +err: + rtw89_err(rtwsta->rtwdev, "sta (link_id %u) failed to set link: %d\n", + link_id, ret); + return NULL; +} + +void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id) +{ + struct rtw89_sta_link **container = &rtwsta->links[link_id]; + struct rtw89_sta_link *link = *container; + u8 index; + + if (!link) + return; + + index = rtw89_sta_link_inst_get_index(link); + clear_bit(index, rtwsta->links_inst_map); + *container = NULL; +} + int rtw89_core_init(struct rtw89_dev *rtwdev) { struct rtw89_btc *btc = &rtwdev->btc; @@ -4444,39 +4743,45 @@ void rtw89_core_deinit(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_core_deinit); -void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, const u8 *mac_addr, bool hw_scan) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); rtwdev->scanning = true; rtw89_leave_lps(rtwdev); if (hw_scan) rtw89_leave_ips_by_hwflags(rtwdev); - ether_addr_copy(rtwvif->mac_addr, mac_addr); - rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type); - rtw89_chip_rfk_scan(rtwdev, rtwvif, true); + ether_addr_copy(rtwvif_link->mac_addr, mac_addr); + rtw89_btc_ntfy_scan_start(rtwdev, rtwvif_link->phy_idx, chan->band_type); + rtw89_chip_rfk_scan(rtwdev, rtwvif_link, true); rtw89_hci_recalc_int_mit(rtwdev); rtw89_phy_config_edcca(rtwdev, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, mac_addr); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr); } void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, bool hw_scan) + struct rtw89_vif_link *rtwvif_link, bool hw_scan) { - struct rtw89_vif *rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; + struct ieee80211_bss_conf *bss_conf; - if (!rtwvif) + if (!rtwvif_link) return; - ether_addr_copy(rtwvif->mac_addr, vif->addr); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); + + rcu_read_unlock(); + + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); - rtw89_chip_rfk_scan(rtwdev, rtwvif, false); - rtw89_btc_ntfy_scan_finish(rtwdev, RTW89_PHY_0); + rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); + rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx); rtw89_phy_config_edcca(rtwdev, false); rtwdev->scanning = false; @@ -4688,17 +4993,39 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_chip_info_setup); +void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + if (!bss_conf->he_support || !vif->cfg.assoc) { + rcu_read_unlock(); + return; + } + + rcu_read_unlock(); + + if (chip->ops->set_txpwr_ul_tb_offset) + chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif_link->mac_idx); +} + static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; + u8 n = rtwdev->support_mlo ? chip->support_link_num : 1; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; int ret; int tx_headroom = IEEE80211_HT_CTL_LEN; - hw->vif_data_size = sizeof(struct rtw89_vif); - hw->sta_data_size = sizeof(struct rtw89_sta); + hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n); + hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n); hw->txq_data_size = sizeof(struct rtw89_txq); hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 4ed9034fdb46..38df161bfd35 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -829,6 +829,8 @@ enum rtw89_phy_idx { RTW89_PHY_MAX }; +#define __RTW89_MLD_MAX_LINK_NUM 2 + enum rtw89_chanctx_idx { RTW89_CHANCTX_0 = 0, RTW89_CHANCTX_1 = 1, @@ -1166,8 +1168,8 @@ struct rtw89_core_tx_request { enum rtw89_core_tx_type tx_type; struct sk_buff *skb; - struct ieee80211_vif *vif; - struct ieee80211_sta *sta; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_tx_desc_info desc_info; }; @@ -1350,7 +1352,6 @@ struct rtw89_btc_wl_smap { u32 connecting: 1; u32 roaming: 1; u32 dbccing: 1; - u32 transacting: 1; u32 _4way: 1; u32 rf_off: 1; u32 lps: 2; @@ -2937,6 +2938,7 @@ struct rtw89_btc_dm { u8 wl_pre_agc: 2; u8 wl_lna2: 1; + u8 freerun_chk: 1; u8 wl_pre_agc_rb: 2; u8 bt_select: 2; /* 0:s0, 1:s1, 2:s0 & s1, refer to enum btc_bt_index */ u8 slot_req_more: 1; @@ -2975,6 +2977,8 @@ enum rtw89_btc_btf_fw_event { BTF_EVNT_BT_REG = 3, BTF_EVNT_CX_RUNINFO = 4, BTF_EVNT_BT_PSD = 5, + BTF_EVNT_BT_DEV_INFO = 6, /* fwc2hfunc > 0 */ + BTF_EVNT_BT_LEAUDIO_INFO = 7, /* fwc2hfunc > 1 */ BTF_EVNT_BUF_OVERFLOW, BTF_EVNT_C2H_LOOPBACK, BTF_EVNT_MAX, @@ -3141,6 +3145,7 @@ struct rtw89_btc_ver { u8 fcxinit; u8 fwevntrptl; + u8 fwc2hfunc; u8 drvinfo_type; u16 info_buf; u8 max_role_num; @@ -3354,12 +3359,13 @@ struct rtw89_sec_cam_entry { u8 key[32]; }; -struct rtw89_sta { +struct rtw89_sta_link { + struct rtw89_sta *rtwsta; + unsigned int link_id; + u8 mac_id; - bool disassoc; bool er_cap; - struct rtw89_dev *rtwdev; - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; struct rtw89_ra_info ra; struct rtw89_ra_report ra_report; int max_agg_wait; @@ -3370,15 +3376,12 @@ struct rtw89_sta { struct ewma_evm evm_1ss; struct ewma_evm evm_min[RF_PATH_MAX]; struct ewma_evm evm_max[RF_PATH_MAX]; - struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; - DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); struct ieee80211_rx_status rx_status; u16 rx_hw_rate; __le32 htc_template; struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */ struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */ struct list_head ba_cam_list; - struct sk_buff_head roc_queue; bool use_cfg_mask; struct cfg80211_bitrate_mask mask; @@ -3460,10 +3463,10 @@ struct rtw89_p2p_noa_setter { u8 noa_index; }; -struct rtw89_vif { - struct list_head list; - struct rtw89_dev *rtwdev; - struct rtw89_roc roc; +struct rtw89_vif_link { + struct rtw89_vif *rtwvif; + unsigned int link_id; + bool chanctx_assigned; /* only valid when running with chanctx_ops */ enum rtw89_chanctx_idx chanctx_idx; enum rtw89_reg_6ghz_power reg_6ghz_power; @@ -3473,7 +3476,6 @@ struct rtw89_vif { u8 port; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; - __be32 ip_addr; u8 phy_idx; u8 mac_idx; u8 net_type; @@ -3484,7 +3486,6 @@ struct rtw89_vif { u8 hit_rule; u8 last_noa_nr; u64 sync_bcn_tsf; - bool offchan; bool trigger; bool lsig_txop; u8 tgt_ind; @@ -3498,15 +3499,11 @@ struct rtw89_vif { bool pre_pwr_diff_en; bool pwr_diff_en; u8 def_tri_idx; - u32 tdls_peer; struct work_struct update_beacon_work; struct rtw89_addr_cam_entry addr_cam; struct rtw89_bssid_cam_entry bssid_cam; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; - struct rtw89_traffic_stats stats; struct rtw89_phy_rate_pattern rate_pattern; - struct cfg80211_scan_request *scan_req; - struct ieee80211_scan_ies *scan_ies; struct list_head general_pkt_list; struct rtw89_p2p_noa_setter p2p_noa; }; @@ -3599,11 +3596,11 @@ struct rtw89_chip_ops { void (*rfk_hw_init)(struct rtw89_dev *rtwdev); void (*rfk_init)(struct rtw89_dev *rtwdev); void (*rfk_init_late)(struct rtw89_dev *rtwdev); - void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + void (*rfk_channel)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void (*rfk_band_changed)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan); - void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + void (*rfk_scan)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool start); void (*rfk_track)(struct rtw89_dev *rtwdev); void (*power_trim)(struct rtw89_dev *rtwdev); @@ -3646,23 +3643,25 @@ struct rtw89_chip_ops { u32 *tx_en, enum rtw89_sch_tx_sel sel); int (*resume_sch_tx)(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en); int (*h2c_dctl_sec_cam)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_default_cmac_tbl)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_assoc_cmac_tbl)(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_ampdu_cmac_tbl)(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*h2c_update_beacon)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); - int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link); + int (*h2c_ba_cam)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params); void (*btc_set_rfe)(struct rtw89_dev *rtwdev); @@ -4445,6 +4444,8 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0, RTW89_FW_FEATURE_WOW_REASON_V1, RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, + RTW89_FW_FEATURE_RFK_RXDCK_V0, + RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, }; struct rtw89_fw_suit { @@ -4672,7 +4673,7 @@ struct rtw89_hal { struct rtw89_chanctx chanctx[NUM_OF_RTW89_CHANCTX]; struct cfg80211_chan_def roc_chandef; - bool entity_active; + bool entity_active[RTW89_PHY_MAX]; bool entity_pause; enum rtw89_entity_mode entity_mode; @@ -4750,6 +4751,7 @@ DECLARE_EWMA(thermal, 4, 4); struct rtw89_phy_stat { struct ewma_thermal avg_thermal[RF_PATH_MAX]; + struct ewma_rssi bcn_rssi; struct rtw89_pkt_stat cur_pkt_stat; struct rtw89_pkt_stat last_pkt_stat; }; @@ -5196,7 +5198,7 @@ struct rtw89_early_h2c { }; struct rtw89_hw_scan_info { - struct ieee80211_vif *scanning_vif; + struct rtw89_vif_link *scanning_vif; struct list_head pkt_list[NUM_NL80211_BANDS]; struct rtw89_chan op_chan; bool abort; @@ -5371,7 +5373,7 @@ struct rtw89_wow_aoac_report { }; struct rtw89_wow_param { - struct ieee80211_vif *wow_vif; + struct rtw89_vif_link *rtwvif_link; DECLARE_BITMAP(flags, RTW89_WOW_FLAG_NUM); struct rtw89_wow_cam_info patterns[RTW89_MAX_PATTERN_NUM]; struct rtw89_wow_key_info key_info; @@ -5408,7 +5410,7 @@ struct rtw89_mcc_policy { }; struct rtw89_mcc_role { - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; struct rtw89_mcc_policy policy; struct rtw89_mcc_limit limit; @@ -5608,6 +5610,121 @@ struct rtw89_dev { u8 priv[] __aligned(sizeof(void *)); }; +struct rtw89_vif { + struct rtw89_dev *rtwdev; + struct list_head list; + + u8 mac_addr[ETH_ALEN]; + __be32 ip_addr; + + struct rtw89_traffic_stats stats; + u32 tdls_peer; + + struct ieee80211_scan_ies *scan_ies; + struct cfg80211_scan_request *scan_req; + + struct rtw89_roc roc; + bool offchan; + + u8 links_inst_valid_num; + DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + struct rtw89_vif_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; + struct rtw89_vif_link links_inst[] __counted_by(links_inst_valid_num); +}; + +static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif_link, + const struct rtw89_vif *rtwvif, + unsigned int link_id) +{ + *rtwvif_link = rtwvif->links[link_id]; + return !!*rtwvif_link; +} + +#define rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) \ + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ + if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id)) + +struct rtw89_sta { + struct rtw89_dev *rtwdev; + struct rtw89_vif *rtwvif; + + bool disassoc; + + struct sk_buff_head roc_queue; + + struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS]; + DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS); + + u8 links_inst_valid_num; + DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM); + struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS]; + struct rtw89_sta_link links_inst[] __counted_by(links_inst_valid_num); +}; + +static inline bool rtw89_sta_assign_link_is_valid(struct rtw89_sta_link **rtwsta_link, + const struct rtw89_sta *rtwsta, + unsigned int link_id) +{ + *rtwsta_link = rtwsta->links[link_id]; + return !!*rtwsta_link; +} + +#define rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) \ + for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \ + if (rtw89_sta_assign_link_is_valid(&(rtwsta_link), rtwsta, link_id)) + +static inline u8 rtw89_vif_get_main_macid(struct rtw89_vif *rtwvif) +{ + /* const after init, so no need to check if active first */ + return rtwvif->links_inst[0].mac_id; +} + +static inline u8 rtw89_vif_get_main_port(struct rtw89_vif *rtwvif) +{ + /* const after init, so no need to check if active first */ + return rtwvif->links_inst[0].port; +} + +static inline struct rtw89_vif_link * +rtw89_vif_get_link_inst(struct rtw89_vif *rtwvif, u8 index) +{ + if (index >= rtwvif->links_inst_valid_num || + !test_bit(index, rtwvif->links_inst_map)) + return NULL; + return &rtwvif->links_inst[index]; +} + +static inline +u8 rtw89_vif_link_inst_get_index(struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + + return rtwvif_link - rtwvif->links_inst; +} + +static inline u8 rtw89_sta_get_main_macid(struct rtw89_sta *rtwsta) +{ + /* const after init, so no need to check if active first */ + return rtwsta->links_inst[0].mac_id; +} + +static inline struct rtw89_sta_link * +rtw89_sta_get_link_inst(struct rtw89_sta *rtwsta, u8 index) +{ + if (index >= rtwsta->links_inst_valid_num || + !test_bit(index, rtwsta->links_inst_map)) + return NULL; + return &rtwsta->links_inst[index]; +} + +static inline +u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + + return rtwsta_link - rtwsta->links_inst; +} + static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { @@ -5972,9 +6089,26 @@ static inline struct ieee80211_vif *rtwvif_to_vif_safe(struct rtw89_vif *rtwvif) return rtwvif ? rtwvif_to_vif(rtwvif) : NULL; } +static inline +struct ieee80211_vif *rtwvif_link_to_vif(struct rtw89_vif_link *rtwvif_link) +{ + return rtwvif_to_vif(rtwvif_link->rtwvif); +} + +static inline +struct ieee80211_vif *rtwvif_link_to_vif_safe(struct rtw89_vif_link *rtwvif_link) +{ + return rtwvif_link ? rtwvif_link_to_vif(rtwvif_link) : NULL; +} + +static inline struct rtw89_vif *vif_to_rtwvif(struct ieee80211_vif *vif) +{ + return (struct rtw89_vif *)vif->drv_priv; +} + static inline struct rtw89_vif *vif_to_rtwvif_safe(struct ieee80211_vif *vif) { - return vif ? (struct rtw89_vif *)vif->drv_priv : NULL; + return vif ? vif_to_rtwvif(vif) : NULL; } static inline struct ieee80211_sta *rtwsta_to_sta(struct rtw89_sta *rtwsta) @@ -5989,11 +6123,88 @@ static inline struct ieee80211_sta *rtwsta_to_sta_safe(struct rtw89_sta *rtwsta) return rtwsta ? rtwsta_to_sta(rtwsta) : NULL; } +static inline +struct ieee80211_sta *rtwsta_link_to_sta(struct rtw89_sta_link *rtwsta_link) +{ + return rtwsta_to_sta(rtwsta_link->rtwsta); +} + +static inline +struct ieee80211_sta *rtwsta_link_to_sta_safe(struct rtw89_sta_link *rtwsta_link) +{ + return rtwsta_link ? rtwsta_link_to_sta(rtwsta_link) : NULL; +} + +static inline struct rtw89_sta *sta_to_rtwsta(struct ieee80211_sta *sta) +{ + return (struct rtw89_sta *)sta->drv_priv; +} + static inline struct rtw89_sta *sta_to_rtwsta_safe(struct ieee80211_sta *sta) { - return sta ? (struct rtw89_sta *)sta->drv_priv : NULL; + return sta ? sta_to_rtwsta(sta) : NULL; +} + +static inline struct ieee80211_bss_conf * +__rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink) +{ + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct ieee80211_bss_conf *bss_conf; + + bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]); + if (unlikely(!bss_conf)) { + *nolink = true; + return &vif->bss_conf; + } + + *nolink = false; + return bss_conf; } +#define rtw89_vif_rcu_dereference_link(rtwvif_link, assert) \ +({ \ + typeof(rtwvif_link) p = rtwvif_link; \ + struct ieee80211_bss_conf *bss_conf; \ + bool nolink; \ + \ + bss_conf = __rtw89_vif_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ + rtw89_err(p->rtwvif->rtwdev, \ + "%s: cannot find exact bss_conf for link_id %u\n",\ + __func__, p->link_id); \ + bss_conf; \ +}) + +static inline struct ieee80211_link_sta * +__rtw89_sta_rcu_dereference_link(struct rtw89_sta_link *rtwsta_link, bool *nolink) +{ + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); + struct ieee80211_link_sta *link_sta; + + link_sta = rcu_dereference(sta->link[rtwsta_link->link_id]); + if (unlikely(!link_sta)) { + *nolink = true; + return &sta->deflink; + } + + *nolink = false; + return link_sta; +} + +#define rtw89_sta_rcu_dereference_link(rtwsta_link, assert) \ +({ \ + typeof(rtwsta_link) p = rtwsta_link; \ + struct ieee80211_link_sta *link_sta; \ + bool nolink; \ + \ + link_sta = __rtw89_sta_rcu_dereference_link(p, &nolink); \ + if (unlikely(nolink) && (assert)) \ + rtw89_err(p->rtwsta->rtwdev, \ + "%s: cannot find exact link_sta for link_id %u\n",\ + __func__, p->link_id); \ + link_sta; \ +}) + static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw) { if (hw_bw == RTW89_CHANNEL_WIDTH_160) @@ -6078,29 +6289,29 @@ enum nl80211_he_ru_alloc rtw89_he_rua_to_ru_alloc(u16 rua) } static inline -struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +struct rtw89_addr_cam_entry *rtw89_get_addr_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - if (rtwsta) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + if (rtwsta_link) { + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) - return &rtwsta->addr_cam; + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + return &rtwsta_link->addr_cam; } - return &rtwvif->addr_cam; + return &rtwvif_link->addr_cam; } static inline -struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - if (rtwsta) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); + if (rtwsta_link) { + struct ieee80211_sta *sta = rtwsta_link_to_sta(rtwsta_link); if (sta->tdls) - return &rtwsta->bssid_cam; + return &rtwsta_link->bssid_cam; } - return &rtwvif->bssid_cam; + return &rtwvif_link->bssid_cam; } static inline @@ -6159,11 +6370,10 @@ const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev, static inline const struct rtw89_chan *rtw89_scan_chan_get(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; - if (rtwvif) - return rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + if (rtwvif_link) + return rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); else return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); } @@ -6240,12 +6450,12 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev) } static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->rfk_channel) - chip->ops->rfk_channel(rtwdev, rtwvif); + chip->ops->rfk_channel(rtwdev, rtwvif_link); } static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, @@ -6259,12 +6469,12 @@ static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, } static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool start) + struct rtw89_vif_link *rtwvif_link, bool start) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->rfk_scan) - chip->ops->rfk_scan(rtwdev, rtwvif, start); + chip->ops->rfk_scan(rtwdev, rtwvif_link, start); } static inline void rtw89_chip_rfk_track(struct rtw89_dev *rtwdev) @@ -6279,8 +6489,12 @@ static inline void rtw89_chip_set_txpwr_ctrl(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - if (chip->ops->set_txpwr_ctrl) - chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0); + if (!chip->ops->set_txpwr_ctrl) + return; + + chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + chip->ops->set_txpwr_ctrl(rtwdev, RTW89_PHY_1); } static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev) @@ -6291,8 +6505,8 @@ static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev) chip->ops->power_trim(rtwdev); } -static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) +static inline void __rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -6300,6 +6514,13 @@ static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev, chip->ops->init_txpwr_unit(rtwdev, phy_idx); } +static inline void rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev) +{ + __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_1); +} + static inline u8 rtw89_chip_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { @@ -6347,20 +6568,6 @@ static inline void rtw89_chip_cfg_txrx_path(struct rtw89_dev *rtwdev) chip->ops->cfg_txrx_path(rtwdev); } -static inline -void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) -{ - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - const struct rtw89_chip_info *chip = rtwdev->chip; - - if (!vif->bss_conf.he_support || !vif->cfg.assoc) - return; - - if (chip->ops->set_txpwr_ul_tb_offset) - chip->ops->set_txpwr_ul_tb_offset(rtwdev, 0, rtwvif->mac_idx); -} - static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -6457,14 +6664,14 @@ int rtw89_chip_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en) static inline int rtw89_chip_h2c_dctl_sec_cam(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (!chip->ops->h2c_dctl_sec_cam) return 0; - return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); } static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) @@ -6479,13 +6686,14 @@ static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) return hdr->addr3; } -static inline bool rtw89_sta_has_beamformer_cap(struct ieee80211_sta *sta) +static inline +bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta) { - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || - (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) || + (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || - (sta->deflink.he_cap.he_cap_elem.phy_cap_info[4] & + (link_sta->he_cap.he_cap_elem.phy_cap_info[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) return true; return false; @@ -6605,21 +6813,21 @@ void rtw89_core_napi_start(struct rtw89_dev *rtwdev); void rtw89_core_napi_stop(struct rtw89_dev *rtwdev); int rtw89_core_napi_init(struct rtw89_dev *rtwdev); void rtw89_core_napi_deinit(struct rtw89_dev *rtwdev); -int rtw89_core_sta_add(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_assoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_disassoc(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_disconnect(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); +int rtw89_core_sta_link_remove(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_core_set_tid_config(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, struct cfg80211_tid_config *tid_config); @@ -6635,22 +6843,40 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev); u8 rtw89_acquire_mac_id(struct rtw89_dev *rtwdev); void rtw89_release_mac_id(struct rtw89_dev *rtwdev, u8 mac_id); +void rtw89_init_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + u8 mac_id, u8 port); +void rtw89_init_sta(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta, u8 mac_id); +struct rtw89_vif_link *rtw89_vif_set_link(struct rtw89_vif *rtwvif, + unsigned int link_id); +void rtw89_vif_unset_link(struct rtw89_vif *rtwvif, unsigned int link_id); +struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, + unsigned int link_id); +void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef, struct rtw89_chan *chan); int rtw89_set_channel(struct rtw89_dev *rtwdev); -void rtw89_get_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_chan *chan); u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size); void rtw89_core_release_bit_map(unsigned long *addr, u8 bit); void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits); int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx); -void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc); + struct rtw89_sta_link *rtwsta_link, u8 tid, + u8 *cam_idx); +void rtw89_core_free_sta_pending_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_core_free_sta_pending_forbid_ba(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, + struct ieee80211_sta *sta); +void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc); int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); +void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); int rtw89_regd_setup(struct rtw89_dev *rtwdev); int rtw89_regd_init(struct rtw89_dev *rtwdev, @@ -6667,13 +6893,15 @@ void rtw89_core_update_beacon_work(struct work_struct *work); void rtw89_roc_work(struct work_struct *work); void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); -void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, const u8 *mac_addr, bool hw_scan); void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, bool hw_scan); -int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool hw_scan); +int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool active); -void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_core_update_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf); void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event); #endif diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 29f85210f919..74b0c722a5b8 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3506,7 +3506,9 @@ out: return count; } -static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) +static void rtw89_sta_link_info_get_iter(struct seq_file *m, + struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { static const char * const he_gi_str[] = { [NL80211_RATE_INFO_HE_GI_0_8] = "0.8", @@ -3518,20 +3520,26 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) [NL80211_RATE_INFO_EHT_GI_1_6] = "1.6", [NL80211_RATE_INFO_EHT_GI_3_2] = "3.2", }; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rate_info *rate = &rtwsta->ra_report.txrate; - struct ieee80211_rx_status *status = &rtwsta->rx_status; - struct seq_file *m = (struct seq_file *)data; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rate_info *rate = &rtwsta_link->ra_report.txrate; + struct ieee80211_rx_status *status = &rtwsta_link->rx_status; struct rtw89_hal *hal = &rtwdev->hal; u8 ant_num = hal->ant_diversity ? 2 : rtwdev->chip->rf_path_num; bool ant_asterisk = hal->tx_path_diversity || hal->ant_diversity; + struct ieee80211_link_sta *link_sta; u8 evm_min, evm_max, evm_1ss; + u16 max_rc_amsdu_len; u8 rssi; u8 snr; int i; - seq_printf(m, "TX rate [%d]: ", rtwsta->mac_id); + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + max_rc_amsdu_len = link_sta->agg.max_rc_amsdu_len; + + rcu_read_unlock(); + + seq_printf(m, "TX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); if (rate->flags & RATE_INFO_FLAGS_MCS) seq_printf(m, "HT MCS-%d%s", rate->mcs, @@ -3549,13 +3557,13 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) eht_gi_str[rate->eht_gi] : "N/A"); else seq_printf(m, "Legacy %d", rate->legacy); - seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : ""); + seq_printf(m, "%s", rtwsta_link->ra_report.might_fallback_legacy ? " FB_G" : ""); seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(rate->bw)); - seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate); - seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait, - sta->deflink.agg.max_rc_amsdu_len); + seq_printf(m, " (hw_rate=0x%x)", rtwsta_link->ra_report.hw_rate); + seq_printf(m, " ==> agg_wait=%d (%d)\n", rtwsta_link->max_agg_wait, + max_rc_amsdu_len); - seq_printf(m, "RX rate [%d]: ", rtwsta->mac_id); + seq_printf(m, "RX rate [%u, %u]: ", rtwsta_link->mac_id, rtwsta_link->link_id); switch (status->encoding) { case RX_ENC_LEGACY: @@ -3582,24 +3590,24 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) break; } seq_printf(m, " BW:%u", rtw89_rate_info_bw_to_mhz(status->bw)); - seq_printf(m, "\t(hw_rate=0x%x)\n", rtwsta->rx_hw_rate); + seq_printf(m, " (hw_rate=0x%x)\n", rtwsta_link->rx_hw_rate); - rssi = ewma_rssi_read(&rtwsta->avg_rssi); + rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); seq_printf(m, "RSSI: %d dBm (raw=%d, prev=%d) [", - RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta->prev_rssi); + RTW89_RSSI_RAW_TO_DBM(rssi), rssi, rtwsta_link->prev_rssi); for (i = 0; i < ant_num; i++) { - rssi = ewma_rssi_read(&rtwsta->rssi[i]); + rssi = ewma_rssi_read(&rtwsta_link->rssi[i]); seq_printf(m, "%d%s%s", RTW89_RSSI_RAW_TO_DBM(rssi), ant_asterisk && (hal->antenna_tx & BIT(i)) ? "*" : "", i + 1 == ant_num ? "" : ", "); } seq_puts(m, "]\n"); - evm_1ss = ewma_evm_read(&rtwsta->evm_1ss); + evm_1ss = ewma_evm_read(&rtwsta_link->evm_1ss); seq_printf(m, "EVM: [%2u.%02u, ", evm_1ss >> 2, (evm_1ss & 0x3) * 25); for (i = 0; i < (hal->ant_diversity ? 2 : 1); i++) { - evm_min = ewma_evm_read(&rtwsta->evm_min[i]); - evm_max = ewma_evm_read(&rtwsta->evm_max[i]); + evm_min = ewma_evm_read(&rtwsta_link->evm_min[i]); + evm_max = ewma_evm_read(&rtwsta_link->evm_max[i]); seq_printf(m, "%s(%2u.%02u, %2u.%02u)", i == 0 ? "" : " ", evm_min >> 2, (evm_min & 0x3) * 25, @@ -3607,10 +3615,22 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) } seq_puts(m, "]\t"); - snr = ewma_snr_read(&rtwsta->avg_snr); + snr = ewma_snr_read(&rtwsta_link->avg_snr); seq_printf(m, "SNR: %u\n", snr); } +static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta) +{ + struct seq_file *m = (struct seq_file *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + rtw89_sta_link_info_get_iter(m, rtwdev, rtwsta_link); +} + static void rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat, enum rtw89_hw_rate first_rate, int len) @@ -3653,13 +3673,16 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_rx_rate_cnt_info *info; enum rtw89_hw_rate first_rate; + u8 rssi; int i; + rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi); + seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n", stats->tx_throughput, stats->tx_throughput_raw, stats->tx_tfc_lv, stats->rx_throughput, stats->rx_throughput_raw, stats->rx_tfc_lv); - seq_printf(m, "Beacon: %u, TF: %u\n", pkt_stat->beacon_nr, - stats->rx_tf_periodic); + seq_printf(m, "Beacon: %u (%d dBm), TF: %u\n", pkt_stat->beacon_nr, + RTW89_RSSI_RAW_TO_DBM(rssi), stats->rx_tf_periodic); seq_printf(m, "Avg packet length: TX=%u, RX=%u\n", stats->tx_avg_len, stats->rx_avg_len); @@ -3737,28 +3760,41 @@ static void rtw89_dump_pkt_offload(struct seq_file *m, struct list_head *pkt_lis seq_puts(m, "\n"); } +static void rtw89_vif_link_ids_get(struct seq_file *m, u8 *mac, + struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif_link->bssid_cam; + + seq_printf(m, " [%u] %pM\n", rtwvif_link->mac_id, rtwvif_link->mac_addr); + seq_printf(m, "\tlink_id=%u\n", rtwvif_link->link_id); + seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); + rtw89_dump_addr_cam(m, rtwdev, &rtwvif_link->addr_cam); + rtw89_dump_pkt_offload(m, &rtwvif_link->general_pkt_list, + "\tpkt_ofld[GENERAL]: "); +} + static void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; struct seq_file *m = (struct seq_file *)data; - struct rtw89_bssid_cam_entry *bssid_cam = &rtwvif->bssid_cam; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - seq_printf(m, "VIF [%d] %pM\n", rtwvif->mac_id, rtwvif->mac_addr); - seq_printf(m, "\tbssid_cam_idx=%u\n", bssid_cam->bssid_cam_idx); - rtw89_dump_addr_cam(m, rtwdev, &rtwvif->addr_cam); - rtw89_dump_pkt_offload(m, &rtwvif->general_pkt_list, "\tpkt_ofld[GENERAL]: "); + seq_printf(m, "VIF %pM\n", rtwvif->mac_addr); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_vif_link_ids_get(m, mac, rtwdev, rtwvif_link); } -static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) +static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; struct rtw89_ba_cam_entry *entry; bool first = true; - list_for_each_entry(entry, &rtwsta->ba_cam_list, list) { + list_for_each_entry(entry, &rtwsta_link->ba_cam_list, list) { if (first) { seq_puts(m, "\tba_cam "); first = false; @@ -3771,16 +3807,36 @@ static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta) seq_puts(m, "\n"); } +static void rtw89_sta_link_ids_get(struct seq_file *m, + struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) +{ + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + seq_printf(m, " [%u] %pM\n", rtwsta_link->mac_id, link_sta->addr); + + rcu_read_unlock(); + + seq_printf(m, "\tlink_id=%u\n", rtwsta_link->link_id); + rtw89_dump_addr_cam(m, rtwdev, &rtwsta_link->addr_cam); + rtw89_dump_ba_cam(m, rtwdev, rtwsta_link); +} + static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; struct seq_file *m = (struct seq_file *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; - seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr, - sta->tdls ? "(TDLS)" : ""); - rtw89_dump_addr_cam(m, rtwdev, &rtwsta->addr_cam); - rtw89_dump_ba_cam(m, rtwsta); + seq_printf(m, "STA %pM %s\n", sta->addr, sta->tdls ? "(TDLS)" : ""); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + rtw89_sta_link_ids_get(m, rtwdev, rtwsta_link); } static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index d9b0e7ebe619..2c2fdf21f065 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -665,11 +665,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 37, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD), + __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER), @@ -687,6 +689,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, @@ -1741,8 +1744,8 @@ plain_log: } #define H2C_CAM_LEN 60 -int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, const u8 *scan_mac_addr) +int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr) { struct sk_buff *skb; int ret; @@ -1753,8 +1756,9 @@ int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, return -ENOMEM; } skb_put(skb, H2C_CAM_LEN); - rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif, rtwsta, scan_mac_addr, skb->data); - rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif, rtwsta, skb->data); + rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr, + skb->data); + rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1776,8 +1780,8 @@ fail: } int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { struct rtw89_h2c_dctlinfo_ud_v1 *h2c; u32 len = sizeof(*h2c); @@ -1792,7 +1796,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_dctlinfo_ud_v1 *)skb->data; - rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif, rtwsta, h2c); + rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif_link, rtwsta_link, h2c); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1815,8 +1819,8 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1); int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { struct rtw89_h2c_dctlinfo_ud_v2 *h2c; u32 len = sizeof(*h2c); @@ -1831,7 +1835,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data; - rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif, rtwsta, h2c); + rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif_link, rtwsta_link, h2c); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -1854,10 +1858,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_dctlinfo_ud_v2 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -1908,21 +1912,24 @@ fail: } EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); -int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_h2c_ba_cam *h2c; - u8 macid = rtwsta->mac_id; + u8 macid = rtwsta_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; int ret; ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx) : + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because * hardware can create dynamic BA CAM automatically. @@ -1960,7 +1967,8 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, if (chip->bacam_ver == RTW89_BACAM_V0_EXT) { h2c->w1 |= le32_encode_bits(1, RTW89_H2C_BA_CAM_W1_STD_EN) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BA_CAM_W1_BAND); + le32_encode_bits(rtwvif_link->mac_idx, + RTW89_H2C_BA_CAM_W1_BAND); } end: @@ -2039,13 +2047,14 @@ void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev) } } -int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_h2c_ba_cam_v1 *h2c; - u8 macid = rtwsta->mac_id; + u8 macid = rtwsta_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; u8 entry_idx; @@ -2053,8 +2062,10 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, int ret; ret = valid ? - rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) : - rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx); + rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx) : + rtw89_core_release_sta_ba_entry(rtwdev, rtwsta_link, params->tid, + &entry_idx); if (ret) { /* it still works even if we don't have static BA CAM, because * hardware can create dynamic BA CAM automatically. @@ -2092,7 +2103,8 @@ int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, entry_idx += chip->bacam_dynamic_num; /* std entry right after dynamic ones */ h2c->w1 = le32_encode_bits(entry_idx, RTW89_H2C_BA_CAM_V1_W1_ENTRY_IDX_MASK) | le32_encode_bits(1, RTW89_H2C_BA_CAM_V1_W1_STD_ENTRY_EN) | - le32_encode_bits(!!rtwvif->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); + le32_encode_bits(!!rtwvif_link->mac_idx, + RTW89_H2C_BA_CAM_V1_W1_BAND_SEL); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -2197,15 +2209,14 @@ fail: } static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { static const u8 gtkbody[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_eapol_2_of_2 *eapol_pkt; + struct ieee80211_bss_conf *bss_conf; struct ieee80211_hdr_3addr *hdr; struct sk_buff *skb; u8 key_des_ver; @@ -2227,10 +2238,17 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS | IEEE80211_FCTL_PROTECTED); + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(hdr->addr1, bss_conf->bssid); - ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); ether_addr_copy(hdr->addr3, bss_conf->bssid); + rcu_read_unlock(); + skb_put_zero(skb, sec_hdr_len); eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt)); @@ -2241,11 +2259,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, } static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); + struct ieee80211_bss_conf *bss_conf; struct ieee80211_hdr_3addr *hdr; struct rtw89_sa_query *sa_query; struct sk_buff *skb; @@ -2258,10 +2275,17 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION | IEEE80211_FCTL_PROTECTED); + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(hdr->addr1, bss_conf->bssid); - ether_addr_copy(hdr->addr2, vif->addr); + ether_addr_copy(hdr->addr2, bss_conf->addr); ether_addr_copy(hdr->addr3, bss_conf->bssid); + rcu_read_unlock(); + skb_put_zero(skb, sec_hdr_len); sa_query = skb_put_zero(skb, sizeof(*sa_query)); @@ -2272,8 +2296,9 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, } static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct ieee80211_hdr_3addr *hdr; @@ -2295,9 +2320,9 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); hdr->frame_control = fc; - ether_addr_copy(hdr->addr1, rtwvif->bssid); - ether_addr_copy(hdr->addr2, rtwvif->mac_addr); - ether_addr_copy(hdr->addr3, rtwvif->bssid); + ether_addr_copy(hdr->addr1, rtwvif_link->bssid); + ether_addr_copy(hdr->addr2, rtwvif_link->mac_addr); + ether_addr_copy(hdr->addr3, rtwvif_link->bssid); skb_put_zero(skb, sec_hdr_len); @@ -2312,18 +2337,18 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, arp_hdr->ar_pln = 4; arp_hdr->ar_op = htons(ARPOP_REPLY); - ether_addr_copy(arp_skb->sender_hw, rtwvif->mac_addr); + ether_addr_copy(arp_skb->sender_hw, rtwvif_link->mac_addr); arp_skb->sender_ip = rtwvif->ip_addr; return skb; } static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, enum rtw89_fw_pkt_ofld_type type, u8 *id) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_pktofld_info *info; struct sk_buff *skb; int ret; @@ -2346,13 +2371,13 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true); break; case RTW89_PKT_OFLD_TYPE_EAPOL_KEY: - skb = rtw89_eapol_get(rtwdev, rtwvif); + skb = rtw89_eapol_get(rtwdev, rtwvif_link); break; case RTW89_PKT_OFLD_TYPE_SA_QUERY: - skb = rtw89_sa_query_get(rtwdev, rtwvif); + skb = rtw89_sa_query_get(rtwdev, rtwvif_link); break; case RTW89_PKT_OFLD_TYPE_ARP_RSP: - skb = rtw89_arp_response_get(rtwdev, rtwvif); + skb = rtw89_arp_response_get(rtwdev, rtwvif_link); break; default: goto err; @@ -2367,7 +2392,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, if (ret) goto err; - list_add_tail(&info->list, &rtwvif->general_pkt_list); + list_add_tail(&info->list, &rtwvif_link->general_pkt_list); *id = info->id; return 0; @@ -2377,9 +2402,10 @@ err: } void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool notify_fw) + struct rtw89_vif_link *rtwvif_link, + bool notify_fw) { - struct list_head *pkt_list = &rtwvif->general_pkt_list; + struct list_head *pkt_list = &rtwvif_link->general_pkt_list; struct rtw89_pktofld_info *info, *tmp; list_for_each_entry_safe(info, tmp, pkt_list, list) { @@ -2394,16 +2420,20 @@ void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif_link, + notify_fw); } #define H2C_GENERAL_PKT_LEN 6 #define H2C_GENERAL_PKT_ID_UND 0xff int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u8 macid) + struct rtw89_vif_link *rtwvif_link, u8 macid) { u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND; u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND; @@ -2411,11 +2441,11 @@ int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct sk_buff *skb; int ret; - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_PS_POLL, &pkt_id_ps_poll); - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id_null); - rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_QOS_NULL, &pkt_id_qos_null); skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN); @@ -2494,10 +2524,10 @@ fail: return ret; } -int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_h2c_lps_ch_info *h2c; u32 len = sizeof(*h2c); @@ -2546,13 +2576,14 @@ fail: } #define H2C_P2P_ACT_LEN 20 -int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct ieee80211_p2p_noa_desc *desc, u8 act, u8 noa_id) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; - u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow; + bool p2p_type_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; + u8 ctwindow_oppps = bss_conf->p2p_noa_attr.oppps_ctwindow; struct sk_buff *skb; u8 *cmd; int ret; @@ -2565,7 +2596,7 @@ int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, skb_put(skb, H2C_P2P_ACT_LEN); cmd = skb->data; - RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif->mac_id); + RTW89_SET_FWCMD_P2P_MACID(cmd, rtwvif_link->mac_id); RTW89_SET_FWCMD_P2P_P2PID(cmd, 0); RTW89_SET_FWCMD_P2P_NOAID(cmd, noa_id); RTW89_SET_FWCMD_P2P_ACT(cmd, act); @@ -2622,11 +2653,11 @@ static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev, #define H2C_CMC_TBL_LEN 68 int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - u8 macid = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 macid = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct sk_buff *skb; int ret; @@ -2648,7 +2679,7 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, } SET_CMC_TBL_DOPPLER_CTRL(skb->data, 0); SET_CMC_TBL_TXPWR_TOLERENCE(skb->data, 0); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) SET_CMC_TBL_DATA_DCM(skb->data, 0); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -2671,10 +2702,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl); int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -2755,24 +2786,25 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7); static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, u8 *pads) + struct ieee80211_link_sta *link_sta, + u8 *pads) { bool ppe_th; u8 ppe16, ppe8; - u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; - u8 ppe_thres_hdr = sta->deflink.he_cap.ppe_thres[0]; + u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; + u8 ppe_thres_hdr = link_sta->he_cap.ppe_thres[0]; u8 ru_bitmap; u8 n, idx, sh; u16 ppe; int i; ppe_th = FIELD_GET(IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT, - sta->deflink.he_cap.he_cap_elem.phy_cap_info[6]); + link_sta->he_cap.he_cap_elem.phy_cap_info[6]); if (!ppe_th) { u8 pad; pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK, - sta->deflink.he_cap.he_cap_elem.phy_cap_info[9]); + link_sta->he_cap.he_cap_elem.phy_cap_info[9]); for (i = 0; i < RTW89_PPE_BW_NUM; i++) pads[i] = pad; @@ -2794,7 +2826,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, sh = n & 7; n += IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2; - ppe = le16_to_cpu(*((__le16 *)&sta->deflink.he_cap.ppe_thres[idx])); + ppe = le16_to_cpu(*((__le16 *)&link_sta->he_cap.ppe_thres[idx])); ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; sh += IEEE80211_PPE_THRES_INFO_PPET_SIZE; ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; @@ -2809,23 +2841,35 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, } int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); + struct ieee80211_link_sta *link_sta; struct sk_buff *skb; u8 pads[RTW89_PPE_BW_NUM]; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; u16 lowest_rate; int ret; memset(pads, 0, sizeof(pads)); - if (sta && sta->deflink.he_cap.has_he) - __get_sta_he_pkt_padding(rtwdev, sta, pads); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); + return -ENOMEM; + } + + rcu_read_lock(); + + if (rtwsta_link) + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (rtwsta_link && link_sta->he_cap.has_he) + __get_sta_he_pkt_padding(rtwdev, link_sta, pads); if (vif->p2p) lowest_rate = RTW89_HW_RATE_OFDM6; @@ -2834,11 +2878,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN); - if (!skb) { - rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); - return -ENOMEM; - } skb_put(skb, H2C_CMC_TBL_LEN); SET_CTRL_INFO_MACID(skb->data, mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); @@ -2851,7 +2890,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, SET_CMC_TBL_ULDL(skb->data, 1); else SET_CMC_TBL_ULDL(skb->data, 0); - SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif->port); + SET_CMC_TBL_MULTI_PORT_ID(skb->data, rtwvif_link->port); if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD_V1) { SET_CMC_TBL_NOMINAL_PKT_PADDING_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_20]); SET_CMC_TBL_NOMINAL_PKT_PADDING40_V1(skb->data, pads[RTW89_CHANNEL_WIDTH_40]); @@ -2863,12 +2902,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, SET_CMC_TBL_NOMINAL_PKT_PADDING80(skb->data, pads[RTW89_CHANNEL_WIDTH_80]); SET_CMC_TBL_NOMINAL_PKT_PADDING160(skb->data, pads[RTW89_CHANNEL_WIDTH_160]); } - if (sta) + if (rtwsta_link) SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(skb->data, - sta->deflink.he_cap.has_he); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + link_sta->he_cap.has_he); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) SET_CMC_TBL_DATA_DCM(skb->data, 0); + rcu_read_unlock(); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, chip->h2c_cctl_func_id, 0, 1, @@ -2889,9 +2930,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl); static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, u8 *pads) + struct ieee80211_link_sta *link_sta, + u8 *pads) { - u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; + u8 nss = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; u16 ppe_thres_hdr; u8 ppe16, ppe8; u8 n, idx, sh; @@ -2900,12 +2942,12 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, u16 ppe; int i; - ppe_th = !!u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], + ppe_th = !!u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT); if (!ppe_th) { u8 pad; - pad = u8_get_bits(sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5], + pad = u8_get_bits(link_sta->eht_cap.eht_cap_elem.phy_cap_info[5], IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK); for (i = 0; i < RTW89_PPE_BW_NUM; i++) @@ -2914,7 +2956,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, return; } - ppe_thres_hdr = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres); + ppe_thres_hdr = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres); ru_bitmap = u16_get_bits(ppe_thres_hdr, IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK); n = hweight8(ru_bitmap); @@ -2931,7 +2973,7 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, sh = n & 7; n += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2; - ppe = get_unaligned_le16(sta->deflink.eht_cap.eht_ppe_thres + idx); + ppe = get_unaligned_le16(link_sta->eht_cap.eht_ppe_thres + idx); ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; sh += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE; ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK; @@ -2946,14 +2988,15 @@ static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev, } int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta); - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; u8 pads[RTW89_PPE_BW_NUM]; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -2961,11 +3004,24 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, int ret; memset(pads, 0, sizeof(pads)); - if (sta) { - if (sta->deflink.eht_cap.has_eht) - __get_sta_eht_pkt_padding(rtwdev, sta, pads); - else if (sta->deflink.he_cap.has_he) - __get_sta_he_pkt_padding(rtwdev, sta, pads); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); + return -ENOMEM; + } + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->eht_cap.has_eht) + __get_sta_eht_pkt_padding(rtwdev, link_sta, pads); + else if (link_sta->he_cap.has_he) + __get_sta_he_pkt_padding(rtwdev, link_sta, pads); } if (vif->p2p) @@ -2975,11 +3031,6 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, else lowest_rate = RTW89_HW_RATE_OFDM6; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); - if (!skb) { - rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n"); - return -ENOMEM; - } skb_put(skb, len); h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; @@ -3000,16 +3051,16 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, h2c->w3 = le32_encode_bits(0, CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL); - h2c->w4 = le32_encode_bits(rtwvif->port, CCTLINFO_G7_W4_MULTI_PORT_ID); + h2c->w4 = le32_encode_bits(rtwvif_link->port, CCTLINFO_G7_W4_MULTI_PORT_ID); h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_MULTI_PORT_ID); - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { h2c->w4 |= le32_encode_bits(0, CCTLINFO_G7_W4_DATA_DCM); h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM); } - if (vif->bss_conf.eht_support) { - u16 punct = vif->bss_conf.chanreq.oper.punctured; + if (bss_conf->eht_support) { + u16 punct = bss_conf->chanreq.oper.punctured; h2c->w4 |= le32_encode_bits(~punct, CCTLINFO_G7_W4_ACT_SUBCH_CBW); @@ -3036,12 +3087,14 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, CCTLINFO_G7_W6_ULDL); h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); - if (sta) { - h2c->w8 = le32_encode_bits(sta->deflink.he_cap.has_he, + if (rtwsta_link) { + h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT); } + rcu_read_unlock(); + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, @@ -3062,10 +3115,10 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7); int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; struct rtw89_h2c_cctlinfo_ud_g7 *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; @@ -3102,7 +3155,7 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, else if (agg_num > 0x200 && agg_num <= 0x400) ba_bmap = 5; - h2c->c0 = le32_encode_bits(rtwsta->mac_id, CCTLINFO_G7_C0_MACID) | + h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, CCTLINFO_G7_C0_MACID) | le32_encode_bits(1, CCTLINFO_G7_C0_OP); h2c->w3 = le32_encode_bits(ba_bmap, CCTLINFO_G7_W3_BA_BMAP); @@ -3128,7 +3181,7 @@ fail: EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7); int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta) + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; struct sk_buff *skb; @@ -3140,15 +3193,15 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, return -ENOMEM; } skb_put(skb, H2C_CMC_TBL_LEN); - SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); + SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); - if (rtwsta->cctl_tx_time) { + if (rtwsta_link->cctl_tx_time) { SET_CMC_TBL_AMPDU_TIME_SEL(skb->data, 1); - SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta->ampdu_max_time); + SET_CMC_TBL_AMPDU_MAX_TIME(skb->data, rtwsta_link->ampdu_max_time); } - if (rtwsta->cctl_tx_retry_limit) { + if (rtwsta_link->cctl_tx_retry_limit) { SET_CMC_TBL_DATA_TXCNT_LMT_SEL(skb->data, 1); - SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta->data_tx_cnt_lmt); + SET_CMC_TBL_DATA_TX_CNT_LMT(skb->data, rtwsta_link->data_tx_cnt_lmt); } rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -3170,7 +3223,7 @@ fail: } int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta) + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; struct sk_buff *skb; @@ -3185,7 +3238,7 @@ int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, return -ENOMEM; } skb_put(skb, H2C_CMC_TBL_LEN); - SET_CTRL_INFO_MACID(skb->data, rtwsta->mac_id); + SET_CTRL_INFO_MACID(skb->data, rtwsta_link->mac_id); SET_CTRL_INFO_OPERATION(skb->data, 1); __rtw89_fw_h2c_set_tx_path(rtwdev, skb); @@ -3209,11 +3262,11 @@ fail: } int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_h2c_bcn_upd *h2c; struct sk_buff *skb_beacon; struct ieee80211_hdr *hdr; @@ -3240,7 +3293,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, return -ENOMEM; } - noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); + noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); if (noa_len && (noa_len <= skb_tailroom(skb_beacon) || pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { @@ -3260,11 +3313,11 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcn_upd *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_W0_PORT) | + h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_W0_PORT) | le32_encode_bits(0, RTW89_H2C_BCN_UPD_W0_MBSSID) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) | le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_W0_GRP_IE_OFST); - h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | + h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) | le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_W1_SSN_SEL) | le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_W1_SSN_MODE) | le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_W1_RATE); @@ -3289,10 +3342,10 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon); int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_h2c_bcn_upd_be *h2c; struct sk_buff *skb_beacon; struct ieee80211_hdr *hdr; @@ -3319,7 +3372,7 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, return -ENOMEM; } - noa_len = rtw89_p2p_noa_fetch(rtwvif, &noa_data); + noa_len = rtw89_p2p_noa_fetch(rtwvif_link, &noa_data); if (noa_len && (noa_len <= skb_tailroom(skb_beacon) || pskb_expand_head(skb_beacon, 0, noa_len, GFP_KERNEL) == 0)) { @@ -3339,11 +3392,11 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcn_upd_be *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | + h2c->w0 = le32_encode_bits(rtwvif_link->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) | le32_encode_bits(0, RTW89_H2C_BCN_UPD_BE_W0_MBSSID) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) | le32_encode_bits(tim_offset | BIT(7), RTW89_H2C_BCN_UPD_BE_W0_GRP_IE_OFST); - h2c->w1 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | + h2c->w1 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) | le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_BE_W1_SSN_SEL) | le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_BE_W1_SSN_MODE) | le32_encode_bits(beacon_rate, RTW89_H2C_BCN_UPD_BE_W1_RATE); @@ -3373,22 +3426,22 @@ EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); #define H2C_ROLE_MAINTAIN_LEN 4 int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, enum rtw89_upd_mode upd_mode) { struct sk_buff *skb; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; u8 self_role; int ret; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) { - if (rtwsta) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { + if (rtwsta_link) self_role = RTW89_SELF_ROLE_AP_CLIENT; else - self_role = rtwvif->self_role; + self_role = rtwvif_link->self_role; } else { - self_role = rtwvif->self_role; + self_role = rtwvif_link->self_role; } skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN); @@ -3400,7 +3453,7 @@ int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, SET_FWROLE_MAINTAIN_MACID(skb->data, mac_id); SET_FWROLE_MAINTAIN_SELF_ROLE(skb->data, self_role); SET_FWROLE_MAINTAIN_UPD_MODE(skb->data, upd_mode); - SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif->wifi_role); + SET_FWROLE_MAINTAIN_WIFI_ROLE(skb->data, rtwvif_link->wifi_role); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT, @@ -3421,39 +3474,53 @@ fail: } static enum rtw89_fw_sta_type -rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) +rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; + enum rtw89_fw_sta_type type; + + rcu_read_lock(); - if (!sta) + if (!rtwsta_link) goto by_vif; - if (sta->deflink.eht_cap.has_eht) - return RTW89_FW_BE_STA; - else if (sta->deflink.he_cap.has_he) - return RTW89_FW_AX_STA; + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->eht_cap.has_eht) + type = RTW89_FW_BE_STA; + else if (link_sta->he_cap.has_he) + type = RTW89_FW_AX_STA; else - return RTW89_FW_N_AC_STA; + type = RTW89_FW_N_AC_STA; + + goto out; by_vif: - if (vif->bss_conf.eht_support) - return RTW89_FW_BE_STA; - else if (vif->bss_conf.he_support) - return RTW89_FW_AX_STA; + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (bss_conf->eht_support) + type = RTW89_FW_BE_STA; + else if (bss_conf->he_support) + type = RTW89_FW_AX_STA; else - return RTW89_FW_N_AC_STA; + type = RTW89_FW_N_AC_STA; + +out: + rcu_read_unlock(); + + return type; } -int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, bool dis_conn) +int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool dis_conn) { struct sk_buff *skb; - u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id; - u8 self_role = rtwvif->self_role; + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + u8 self_role = rtwvif_link->self_role; enum rtw89_fw_sta_type sta_type; - u8 net_type = rtwvif->net_type; + u8 net_type = rtwvif_link->net_type; struct rtw89_h2c_join_v1 *h2c_v1; struct rtw89_h2c_join *h2c; u32 len = sizeof(*h2c); @@ -3465,7 +3532,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, format_v1 = true; } - if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) { + if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta_link) { self_role = RTW89_SELF_ROLE_AP_CLIENT; net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type; } @@ -3480,16 +3547,17 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(mac_id, RTW89_H2C_JOININFO_W0_MACID) | le32_encode_bits(dis_conn, RTW89_H2C_JOININFO_W0_OP) | - le32_encode_bits(rtwvif->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | - le32_encode_bits(rtwvif->wmm, RTW89_H2C_JOININFO_W0_WMM) | - le32_encode_bits(rtwvif->trigger, RTW89_H2C_JOININFO_W0_TGR) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_JOININFO_W0_BAND) | + le32_encode_bits(rtwvif_link->wmm, RTW89_H2C_JOININFO_W0_WMM) | + le32_encode_bits(rtwvif_link->trigger, RTW89_H2C_JOININFO_W0_TGR) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_ISHESTA) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DLBW) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_TF_MAC_PAD) | le32_encode_bits(0, RTW89_H2C_JOININFO_W0_DL_T_PE) | - le32_encode_bits(rtwvif->port, RTW89_H2C_JOININFO_W0_PORT_ID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_JOININFO_W0_PORT_ID) | le32_encode_bits(net_type, RTW89_H2C_JOININFO_W0_NET_TYPE) | - le32_encode_bits(rtwvif->wifi_role, RTW89_H2C_JOININFO_W0_WIFI_ROLE) | + le32_encode_bits(rtwvif_link->wifi_role, + RTW89_H2C_JOININFO_W0_WIFI_ROLE) | le32_encode_bits(self_role, RTW89_H2C_JOININFO_W0_SELF_ROLE); if (!format_v1) @@ -3497,7 +3565,7 @@ int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data; - sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif, rtwsta); + sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif_link, rtwsta_link); h2c_v1->w1 = le32_encode_bits(sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE); h2c_v1->w2 = 0; @@ -3618,7 +3686,7 @@ fail: } #define H2C_EDCA_LEN 12 -int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 ac, u32 val) { struct sk_buff *skb; @@ -3631,7 +3699,7 @@ int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, } skb_put(skb, H2C_EDCA_LEN); RTW89_SET_EDCA_SEL(skb->data, 0); - RTW89_SET_EDCA_BAND(skb->data, rtwvif->mac_idx); + RTW89_SET_EDCA_BAND(skb->data, rtwvif_link->mac_idx); RTW89_SET_EDCA_WMM(skb->data, 0); RTW89_SET_EDCA_AC(skb->data, ac); RTW89_SET_EDCA_PARAM(skb->data, val); @@ -3655,7 +3723,8 @@ fail: } #define H2C_TSF32_TOGL_LEN 4 -int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en) { struct sk_buff *skb; @@ -3671,9 +3740,9 @@ int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif skb_put(skb, H2C_TSF32_TOGL_LEN); cmd = skb->data; - RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif->mac_idx); + RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, rtwvif_link->mac_idx); RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, en); - RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif->port); + RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, rtwvif_link->port); RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, early_us); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -3727,11 +3796,10 @@ fail: } int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, bool connect) { - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL; + struct ieee80211_bss_conf *bss_conf; s32 thold = RTW89_DEFAULT_CQM_THOLD; u32 hyst = RTW89_DEFAULT_CQM_HYST; struct rtw89_h2c_bcnfltr *h2c; @@ -3742,9 +3810,20 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw)) return -EINVAL; - if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA) + if (!rtwvif_link || rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) return -EINVAL; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false); + + if (bss_conf->cqm_rssi_hyst) + hyst = bss_conf->cqm_rssi_hyst; + if (bss_conf->cqm_rssi_thold) + thold = bss_conf->cqm_rssi_thold; + + rcu_read_unlock(); + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n"); @@ -3754,11 +3833,6 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, skb_put(skb, len); h2c = (struct rtw89_h2c_bcnfltr *)skb->data; - if (bss_conf->cqm_rssi_hyst) - hyst = bss_conf->cqm_rssi_hyst; - if (bss_conf->cqm_rssi_thold) - thold = bss_conf->cqm_rssi_thold; - h2c->w0 = le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) | le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) | le32_encode_bits(connect, RTW89_H2C_BCNFLTR_W0_MON_EN) | @@ -3768,7 +3842,7 @@ int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, le32_encode_bits(hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) | le32_encode_bits(thold + MAX_RSSI, RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD, @@ -3833,15 +3907,16 @@ fail: return ret; } -int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_traffic_stats *stats = &rtwvif->stats; struct rtw89_h2c_ofld *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; - if (rtwvif->net_type != RTW89_NET_TYPE_INFRA) + if (rtwvif_link->net_type != RTW89_NET_TYPE_INFRA) return -EINVAL; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -3853,7 +3928,7 @@ int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) skb_put(skb, len); h2c = (struct rtw89_h2c_ofld *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) | le32_encode_bits(stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) | le32_encode_bits(stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP); @@ -4688,6 +4763,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, return 0; } +static int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, struct list_head *chan_list) { @@ -4759,8 +4835,10 @@ int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, return 0; } +static int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list) + struct list_head *chan_list, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct rtw89_h2c_chinfo_elem_be *elem; @@ -4785,7 +4863,8 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, h2c->ch_num = ch_num; h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */ - h2c->arg = u8_encode_bits(RTW89_PHY_0, RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK); + h2c->arg = u8_encode_bits(rtwvif_link->mac_idx, + RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK); list_for_each_entry(ch_info, chan_list, list) { elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, sizeof(*elem)); @@ -4858,7 +4937,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, #define RTW89_SCAN_DELAY_TSF_UNIT 104800 int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan) { struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; @@ -4880,7 +4959,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, h2c = (struct rtw89_h2c_scanofld *)skb->data; if (option->delay) { - ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif, &tsf); + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "NLO failed to get port tsf: %d\n", ret); scan_mode = RTW89_SCAN_IMMEDIATE; @@ -4890,9 +4969,9 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, } } - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | - le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | - le32_encode_bits(RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) | + le32_encode_bits(rtwvif_link->mac_idx, RTW89_H2C_SCANOFLD_W0_BAND) | le32_encode_bits(option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION); h2c->w1 = le32_encode_bits(true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) | @@ -4963,9 +5042,10 @@ static void rtw89_scan_get_6g_disabled_chan(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct cfg80211_scan_request *req = rtwvif->scan_req; @@ -5016,8 +5096,8 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, le32_encode_bits(option->repeat, RTW89_H2C_SCANOFLD_BE_W0_REPEAT) | le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_NOTIFY_END) | le32_encode_bits(true, RTW89_H2C_SCANOFLD_BE_W0_LEARN_CH) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | - le32_encode_bits(rtwvif->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) | le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_W0_BAND); h2c->w1 = le32_encode_bits(option->num_macc_role, RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE) | @@ -5082,11 +5162,11 @@ flex_member: for (i = 0; i < option->num_opch; i++) { opch = ptr; - opch->w0 = le32_encode_bits(rtwvif->mac_id, + opch->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) | le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) | - le32_encode_bits(rtwvif->port, + le32_encode_bits(rtwvif_link->port, RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) | le32_encode_bits(RTW89_SCAN_OPMODE_INTV, RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) | @@ -5518,30 +5598,44 @@ fail: } int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, - const struct rtw89_chan *chan) + const struct rtw89_chan *chan, bool is_chl_k) { + struct rtw89_h2c_rf_rxdck_v0 *v0; struct rtw89_h2c_rf_rxdck *h2c; u32 len = sizeof(*h2c); struct sk_buff *skb; + int ver = -1; int ret; + if (RTW89_CHK_FW_FEATURE(RFK_RXDCK_V0, &rtwdev->fw)) { + len = sizeof(*v0); + ver = 0; + } + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c RF RXDCK\n"); return -ENOMEM; } skb_put(skb, len); - h2c = (struct rtw89_h2c_rf_rxdck *)skb->data; + v0 = (struct rtw89_h2c_rf_rxdck_v0 *)skb->data; + + v0->len = len; + v0->phy = phy_idx; + v0->is_afe = false; + v0->kpath = RF_AB; + v0->cur_band = chan->band_type; + v0->cur_bw = chan->band_width; + v0->cur_ch = chan->channel; + v0->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + + if (ver == 0) + goto hdr; - h2c->len = len; - h2c->phy = phy_idx; - h2c->is_afe = false; - h2c->kpath = RF_AB; - h2c->cur_band = chan->band_type; - h2c->cur_bw = chan->band_width; - h2c->cur_ch = chan->channel; - h2c->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + h2c = (struct rtw89_h2c_rf_rxdck *)skb->data; + h2c->is_chl_k = is_chl_k; +hdr: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, H2C_FUNC_RFK_RXDCK_OFFLOAD, 0, 0, len); @@ -5871,12 +5965,10 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev) } static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct cfg80211_scan_request *req, struct rtw89_pktofld_info *info, enum nl80211_band band, u8 ssid_idx) { - struct cfg80211_scan_request *req = rtwvif->scan_req; - if (band != NL80211_BAND_6GHZ) return false; @@ -5892,11 +5984,13 @@ static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, } static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct sk_buff *skb, u8 ssid_idx) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct ieee80211_scan_ies *ies = rtwvif->scan_ies; + struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_pktofld_info *info; struct sk_buff *new; int ret = 0; @@ -5921,8 +6015,7 @@ static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev, goto out; } - rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band, - ssid_idx); + rtw89_is_6ghz_wildcard_probe_req(rtwdev, req, info, band, ssid_idx); ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, &info->id, new); if (ret) { @@ -5939,22 +6032,23 @@ out: } static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct sk_buff *skb; u8 num = req->n_ssids, i; int ret; for (i = 0; i < num; i++) { - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, req->ssids[i].ssid, req->ssids[i].ssid_len, req->ie_len); if (!skb) return -ENOMEM; - ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, i); + ret = rtw89_append_probe_req_ie(rtwdev, rtwvif_link, skb, i); kfree_skb(skb); if (ret) @@ -5965,13 +6059,12 @@ static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev, } static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, + struct ieee80211_scan_ies *ies, struct cfg80211_scan_request *req, struct rtw89_mac_chinfo *ch_info) { - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; struct list_head *pkt_list = rtwdev->scan_info.pkt_list; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_6ghz_params *params; struct rtw89_pktofld_info *info, *tmp; struct ieee80211_hdr *hdr; @@ -6000,8 +6093,11 @@ static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev, if (found) continue; - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, NULL, 0, req->ie_len); + if (!skb) + return -ENOMEM; + skb_put_data(skb, ies->ies[NL80211_BAND_6GHZ], ies->len[NL80211_BAND_6GHZ]); skb_put_data(skb, ies->common_ies, ies->common_ie_len); hdr = (struct ieee80211_hdr *)skb->data; @@ -6090,8 +6186,9 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, struct rtw89_mac_chinfo *ch_info) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct ieee80211_scan_ies *ies = rtwvif->scan_ies; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; struct rtw89_pktofld_info *info; @@ -6117,7 +6214,7 @@ static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type, } } - ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info); + ret = rtw89_update_6ghz_rnr_chan(rtwdev, ies, req, ch_info); if (ret) rtw89_warn(rtwdev, "RNR fails: %d\n", ret); @@ -6207,8 +6304,8 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, struct rtw89_mac_chinfo_be *ch_info) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_pktofld_info *info; u8 band, probe_count = 0, i; @@ -6265,7 +6362,7 @@ static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, } int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -6315,8 +6412,9 @@ out: } int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo *ch_info, *tmp; struct ieee80211_channel *channel; @@ -6392,7 +6490,7 @@ out: } int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -6432,7 +6530,8 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, list_add_tail(&ch_info->list, &chan_list); } - ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list); + ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list, + rtwvif_link); out: list_for_each_entry_safe(ch_info, tmp, &chan_list, list) { @@ -6444,8 +6543,9 @@ out: } int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_mac_chinfo_be *ch_info, *tmp; struct ieee80211_channel *channel; @@ -6491,7 +6591,8 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, } rtwdev->scan_info.last_chan_idx = idx; - ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list); + ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, list_len, &chan_list, + rtwvif_link); out: list_for_each_entry_safe(ch_info, tmp, &chan_list, list) { @@ -6503,79 +6604,86 @@ out: } static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected) + struct rtw89_vif_link *rtwvif_link, bool connected) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; int ret; - ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif); + ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update probe request failed\n"); goto out; } - ret = mac->add_chan_list(rtwdev, rtwvif, connected); + ret = mac->add_chan_list(rtwdev, rtwvif_link, connected); out: return ret; } -void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct cfg80211_scan_request *req = &scan_req->req; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, + rtwvif_link->chanctx_idx); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; u32 rx_fltr = rtwdev->hal.rx_fltr; u8 mac_addr[ETH_ALEN]; + u32 reg; + + /* clone op and keep it during scan */ + rtwdev->scan_info.op_chan = *chan; - rtw89_get_channel(rtwdev, rtwvif, &rtwdev->scan_info.op_chan); - rtwdev->scan_info.scanning_vif = vif; + rtwdev->scan_info.scanning_vif = rtwvif_link; rtwdev->scan_info.last_chan_idx = 0; rtwdev->scan_info.abort = false; rtwvif->scan_ies = &scan_req->ies; rtwvif->scan_req = req; ieee80211_stop_queues(rtwdev->hw); - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, false); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, false); if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) get_random_mask_addr(mac_addr, req->mac_addr, req->mac_addr_mask); else - ether_addr_copy(mac_addr, vif->addr); - rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true); + ether_addr_copy(mac_addr, rtwvif_link->mac_addr); + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, true); rx_fltr &= ~B_AX_A_BCN_CHK_EN; rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr); rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN); } -void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool aborted) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); struct cfg80211_scan_info info = { .aborted = aborted, }; + struct rtw89_vif *rtwvif; + u32 reg; - if (!vif) + if (!rtwvif_link) return; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rtwdev->hal.rx_fltr); + rtwvif = rtwvif_link->rtwvif; + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); - rtw89_core_scan_complete(rtwdev, vif, true); + rtw89_core_scan_complete(rtwdev, rtwvif_link, true); ieee80211_scan_completed(rtwdev->hw, &info); ieee80211_wake_queues(rtwdev->hw); - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, true); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true); rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); rtw89_release_pkt_list(rtwdev); @@ -6588,14 +6696,15 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, rtw89_chanctx_proceed(rtwdev); } -void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; int ret; scan_info->abort = true; - ret = rtw89_hw_scan_offload(rtwdev, vif, false); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, false); if (ret) rtw89_warn(rtwdev, "rtw89_hw_scan_offload failed ret %d\n", ret); @@ -6604,40 +6713,43 @@ void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) * RTW89_SCAN_END_SCAN_NOTIFY, so that ieee80211_stop() can flush scan * work properly. */ - rtw89_hw_scan_complete(rtwdev, vif, true); + rtw89_hw_scan_complete(rtwdev, rtwvif_link, true); } static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - /* This variable implies connected or during attempt to connect */ - if (!is_zero_ether_addr(rtwvif->bssid)) - return true; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + /* This variable implies connected or during attempt to connect */ + if (!is_zero_ether_addr(rtwvif_link->bssid)) + return true; + } } return false; } -int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_scan_option opt = {0}; - struct rtw89_vif *rtwvif; bool connected; int ret = 0; - rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL; - if (!rtwvif) + if (!rtwvif_link) return -EINVAL; connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); opt.enable = enable; opt.target_ch_mode = connected; if (enable) { - ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected); + ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif_link, connected); if (ret) goto out; } @@ -6645,14 +6757,14 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) { opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP; opt.scan_mode = RTW89_SCAN_MODE_SA; - opt.band = RTW89_PHY_0; + opt.band = rtwvif_link->mac_idx; opt.num_macc_role = 0; opt.mlo_mode = rtwdev->mlo_dbcc_mode; opt.num_opch = connected ? 1 : 0; opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID; } - ret = mac->scan_offload(rtwdev, &opt, rtwvif, false); + ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false); out: return ret; } @@ -6758,7 +6870,7 @@ fail: } #define H2C_KEEP_ALIVE_LEN 4 -int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct sk_buff *skb; @@ -6766,7 +6878,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, int ret; if (enable) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_NULL_DATA, &pkt_id); if (ret) @@ -6784,7 +6896,7 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, RTW89_SET_KEEP_ALIVE_ENABLE(skb->data, enable); RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(skb->data, pkt_id); RTW89_SET_KEEP_ALIVE_PERIOD(skb->data, 5); - RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif->mac_id); + RTW89_SET_KEEP_ALIVE_MACID(skb->data, rtwvif_link->mac_id); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, @@ -6806,7 +6918,7 @@ fail: return ret; } -int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_h2c_arp_offload *h2c; @@ -6816,7 +6928,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, int ret; if (enable) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_ARP_RSP, &pkt_id); if (ret) @@ -6834,7 +6946,7 @@ int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(enable, RTW89_H2C_ARP_OFFLOAD_W0_ENABLE) | le32_encode_bits(0, RTW89_H2C_ARP_OFFLOAD_W0_ACTION) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | le32_encode_bits(pkt_id, RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, @@ -6859,11 +6971,11 @@ fail: #define H2C_DISCONNECT_DETECT_LEN 8 int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable) + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct sk_buff *skb; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN); @@ -6902,7 +7014,7 @@ fail: return ret; } -int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; @@ -6923,7 +7035,7 @@ int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, h2c->w0 = le32_encode_bits(enable, RTW89_H2C_NLO_W0_ENABLE) | le32_encode_bits(enable, RTW89_H2C_NLO_W0_IGNORE_CIPHER) | - le32_encode_bits(rtwvif->mac_id, RTW89_H2C_NLO_W0_MACID); + le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_NLO_W0_MACID); if (enable) { h2c->nlo_cnt = nd_config->n_match_sets; @@ -6953,12 +7065,12 @@ fail: return ret; } -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_h2c_wow_global *h2c; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; @@ -7002,12 +7114,12 @@ fail: #define H2C_WAKEUP_CTRL_LEN 4 int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct sk_buff *skb; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN); @@ -7100,13 +7212,13 @@ fail: } int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_gtk_info *gtk_info = &rtw_wow->gtk_info; struct rtw89_h2c_wow_gtk_ofld *h2c; - u8 macid = rtwvif->mac_id; + u8 macid = rtwvif_link->mac_id; u32 len = sizeof(*h2c); u8 pkt_id_sa_query = 0; struct sk_buff *skb; @@ -7128,14 +7240,14 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, if (!enable) goto hdr; - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_EAPOL_KEY, &pkt_id_eapol); if (ret) goto fail; if (gtk_info->igtk_keyid) { - ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif_link, RTW89_PKT_OFLD_TYPE_SA_QUERY, &pkt_id_sa_query); if (ret) @@ -7173,7 +7285,7 @@ fail: return ret; } -int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable) { struct rtw89_wait_info *wait = &rtwdev->mac.ps_wait; @@ -7189,7 +7301,7 @@ int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, skb_put(skb, len); h2c = (struct rtw89_h2c_fwips *)skb->data; - h2c->w0 = le32_encode_bits(rtwvif->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_FW_IPS_W0_MACID) | le32_encode_bits(enable, RTW89_H2C_FW_IPS_W0_ENABLE); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index ad47e77d740b..d338c3aec725 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -4286,7 +4286,7 @@ struct rtw89_h2c_rf_dack { __le32 type; } __packed; -struct rtw89_h2c_rf_rxdck { +struct rtw89_h2c_rf_rxdck_v0 { u8 len; u8 phy; u8 is_afe; @@ -4297,6 +4297,11 @@ struct rtw89_h2c_rf_rxdck { u8 rxdck_dbg_en; } __packed; +struct rtw89_h2c_rf_rxdck { + struct rtw89_h2c_rf_rxdck_v0 v0; + u8 is_chl_k; +} __packed; + enum rtw89_rf_log_type { RTW89_RF_RUN_LOG = 0, RTW89_RF_RPT_LOG = 1, @@ -4313,6 +4318,42 @@ struct rtw89_c2h_rf_run_log { __le32 arg[4]; } __packed; +struct rtw89_c2h_rf_iqk_rpt_log { + bool iqk_tx_fail[2]; + bool iqk_rx_fail[2]; + bool is_iqk_init; + bool is_reload; + bool is_wb_txiqk[2]; + bool is_wb_rxiqk[2]; + bool is_nbiqk; + bool txiqk_en; + bool rxiqk_en; + bool lok_en; + bool iqk_xym_en; + bool iqk_sram_en; + bool iqk_fft_en; + bool is_fw_iqk; + bool is_iqk_enable; + bool iqk_cfir_en; + bool thermal_rek_en; + u8 iqk_band[2]; + u8 iqk_ch[2]; + u8 iqk_bw[2]; + u8 iqk_times; + u8 version; + u8 phy; + u8 fwk_status; + u8 rsvd; + __le32 reload_cnt; + __le32 iqk_fail_cnt; + __le32 lok_idac[2]; + __le32 lok_vbuf[2]; + __le32 rftxgain[2][4]; + __le32 rfrxgain[2][4]; + __le32 tx_xym[2][4]; + __le32 rx_xym[2][4]; +} __packed; + struct rtw89_c2h_rf_dpk_rpt_log { u8 ver; u8 idx[2]; @@ -4334,19 +4375,25 @@ struct rtw89_c2h_rf_dpk_rpt_log { struct rtw89_c2h_rf_dack_rpt_log { u8 fwdack_ver; - u8 fwdack_rpt_ver; + u8 fwdack_info_ver; u8 msbk_d[2][2][16]; u8 dadck_d[2][2]; u8 cdack_d[2][2][2]; - __le16 addck2_d[2][2][2]; + u8 addck2_hd[2][2][2]; + u8 addck2_ld[2][2][2]; u8 adgaink_d[2][2]; - __le16 biask_d[2][2]; + u8 biask_hd[2][2]; + u8 biask_ld[2][2]; u8 addck_timeout; u8 cdack_timeout; u8 dadck_timeout; u8 msbk_timeout; u8 adgaink_timeout; + u8 wbadcdck_timeout; + u8 drck_timeout; u8 dack_fail; + u8 wbdck_d[2]; + u8 rck_d; } __packed; struct rtw89_c2h_rf_rxdck_rpt_log { @@ -4357,6 +4404,14 @@ struct rtw89_c2h_rf_rxdck_rpt_log { u8 timeout[2]; } __packed; +struct rtw89_c2h_rf_tssi_rpt_log { + s8 alignment_power[2][2][4]; + u8 alignment_power_cw_h[2][2][4]; + u8 alignment_power_cw_l[2][2][4]; + u8 tssi_alimk_state[2][2]; + u8 default_txagc_offset[2][2]; +} __packed; + struct rtw89_c2h_rf_txgapk_rpt_log { __le32 r0x8010[2]; __le32 chk_cnt; @@ -4404,59 +4459,59 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len); int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta); + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta); + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); -int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *vif, - struct rtw89_sta *rtwsta, const u8 *scan_mac_addr); + struct rtw89_vif_link *rtwvif_link); +int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif, + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr); int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta); + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h); void rtw89_fw_c2h_work(struct work_struct *work); int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, enum rtw89_upd_mode upd_mode); -int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta, bool dis_conn); +int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool dis_conn); int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en); int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp, bool pause); -int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 ac, u32 val); int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, + struct rtw89_vif_link *rtwvif_link, bool connect); int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); -int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi); int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type); @@ -4472,17 +4527,13 @@ int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev, u8 type); int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id); int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, struct sk_buff *skb_ofld); -int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list); -int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, - struct list_head *chan_list); int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *opt, - struct rtw89_vif *vif, + struct rtw89_vif_link *vif, bool wowlan); int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, struct rtw89_scan_option *opt, - struct rtw89_vif *vif, + struct rtw89_vif_link *vif, bool wowlan); int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev, struct rtw89_fw_h2c_rf_reg_info *info, @@ -4501,21 +4552,26 @@ int rtw89_fw_h2c_rf_txgapk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan); int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, - const struct rtw89_chan *chan); + const struct rtw89_chan *chan, bool is_chl_k); int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, u8 *buf, u16 len, bool rack, bool dack); int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len); void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev); void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev); -int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 macid); void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool notify_fw); + struct rtw89_vif_link *rtwvif_link, + bool notify_fw); void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw); -int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params); -int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params); void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, @@ -4524,8 +4580,8 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users, int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, struct rtw89_lps_parm *lps_param); int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); -int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link); +int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len); struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len); @@ -4534,49 +4590,56 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, struct rtw89_mac_c2h_info *c2h_info); int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable); void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev); -void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_scan_request *req); -void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_scan_request *scan_req); +void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool aborted); -int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool enable); -void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev, const struct rtw89_pkt_drop_params *params); -int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf, struct ieee80211_p2p_noa_desc *desc, u8 act, u8 noa_id); -int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool en); -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); -int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); +int rtw89_fw_h2c_cfg_pno(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); -int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); -int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); +int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable); + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, struct rtw89_wow_cam_info *cam_info); int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool enable); int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev, @@ -4621,51 +4684,73 @@ static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev) } static inline int rtw89_chip_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_default_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); } static inline int rtw89_chip_h2c_default_dmac_tbl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_sta *rtwsta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->h2c_default_dmac_tbl) - return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif, rtwsta); + return chip->ops->h2c_default_dmac_tbl(rtwdev, rtwvif_link, rtwsta_link); return 0; } static inline int rtw89_chip_h2c_update_beacon(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_update_beacon(rtwdev, rtwvif); + return chip->ops->h2c_update_beacon(rtwdev, rtwvif_link); } static inline int rtw89_chip_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; - return chip->ops->h2c_assoc_cmac_tbl(rtwdev, vif, sta); + return chip->ops->h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); } -static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +static inline +int rtw89_chip_h2c_ampdu_link_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->ops->h2c_ampdu_cmac_tbl) - return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + return chip->ops->h2c_ampdu_cmac_tbl(rtwdev, rtwvif_link, + rtwsta_link); + + return 0; +} + +static inline int rtw89_chip_h2c_ampdu_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + struct rtw89_sta *rtwsta) +{ + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = rtw89_chip_h2c_ampdu_link_cmac_tbl(rtwdev, rtwvif_link, + rtwsta_link); + if (ret) + return ret; + } return 0; } @@ -4675,8 +4760,20 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = chip->ops->h2c_ba_cam(rtwdev, rtwvif_link, rtwsta_link, + valid, params); + if (ret) + return ret; + } - return chip->ops->h2c_ba_cam(rtwdev, rtwsta, valid, params); + return 0; } /* must consider compatibility; don't insert new in the mid */ diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index c70a23a763b0..e09f926bb4a0 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -1483,7 +1483,8 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags); clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags); rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR); - rtw89_set_entity_state(rtwdev, false); + rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false); + rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false); } return 0; @@ -4076,17 +4077,17 @@ static const struct rtw89_port_reg rtw89_port_base_ax = { }; static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u8 type) + struct rtw89_vif_link *rtwvif_link, u8 type) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif->port); + u8 mask = B_AX_PTCL_DBG_INFO_MASK_BY_PORT(rtwvif_link->port); u32 reg_info, reg_ctrl; u32 val; int ret; - reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif->mac_idx); - reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif->mac_idx); + reg_info = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg_info, rtwvif_link->mac_idx); + reg_ctrl = rtw89_mac_reg_by_idx(rtwdev, p->ptcl_dbg, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg_ctrl, B_AX_PTCL_DBG_SEL_MASK, type); rtw89_write32_set(rtwdev, reg_ctrl, B_AX_PTCL_DBG_EN); @@ -4098,26 +4099,32 @@ static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, rtw89_warn(rtwdev, "Polling beacon packet empty fail\n"); } -static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, 1); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, 0); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 0); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, 2); - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK, 1); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, 1); - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); - - rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM0); - if (rtwvif->port == RTW89_PORT_0) - rtw89_mac_check_packet_ctrl(rtwdev, rtwvif, AX_PTCL_DBG_BCNQ_NUM1); - - rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif->port)); - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TBTT_PROHIB_EN); + rtw89_write32_set(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, + 1); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, + 0); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, + 0); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, 2); + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, + B_AX_TBTTERLY_MASK, 1); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, + B_AX_BCN_SPACE_MASK, 1); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); + + rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM0); + if (rtwvif_link->port == RTW89_PORT_0) + rtw89_mac_check_packet_ctrl(rtwdev, rtwvif_link, AX_PTCL_DBG_BCNQ_NUM1); + + rtw89_write32_clr(rtwdev, p->bcn_drop_all, BIT(rtwvif_link->port)); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TBTT_PROHIB_EN); fsleep(2000); } @@ -4131,286 +4138,329 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvi #define BCN_ERLY_SET_DLY (10 * 2) static void rtw89_mac_port_cfg_func_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_bss_conf *bss_conf; bool need_backup = false; u32 backup_val; + u16 beacon_int; - if (!rtw89_read32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN)) + if (!rtw89_read32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN)) return; - if (chip->chip_id == RTL8852A && rtwvif->port != RTW89_PORT_0) { + if (chip->chip_id == RTL8852A && rtwvif_link->port != RTW89_PORT_0) { need_backup = true; - backup_val = rtw89_read32_port(rtwdev, rtwvif, p->tbtt_prohib); + backup_val = rtw89_read32_port(rtwdev, rtwvif_link, p->tbtt_prohib); } - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) - rtw89_mac_bcn_drop(rtwdev, rtwvif); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + rtw89_mac_bcn_drop(rtwdev, rtwvif_link); if (chip->chip_id == RTL8852A) { - rtw89_write32_port_clr(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK); - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, 1); - rtw89_write16_port_clr(rtwdev, rtwvif, p->tbtt_early, B_AX_TBTTERLY_MASK); - rtw89_write16_port_clr(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_SETUP_MASK); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, + B_AX_TBTT_HOLD_MASK, 1); + rtw89_write16_port_clr(rtwdev, rtwvif_link, p->tbtt_early, + B_AX_TBTTERLY_MASK); + rtw89_write16_port_clr(rtwdev, rtwvif_link, p->bcn_early, + B_AX_BCNERLY_MASK); } - msleep(vif->bss_conf.beacon_int + 1); - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_PORT_FUNC_EN | + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + beacon_int = bss_conf->beacon_int; + + rcu_read_unlock(); + + msleep(beacon_int + 1); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN | B_AX_BRK_SETUP); - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSFTR_RST); - rtw89_write32_port(rtwdev, rtwvif, p->bcn_cnt_tmr, 0); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSFTR_RST); + rtw89_write32_port(rtwdev, rtwvif_link, p->bcn_cnt_tmr, 0); if (need_backup) - rtw89_write32_port(rtwdev, rtwvif, p->tbtt_prohib, backup_val); + rtw89_write32_port(rtwdev, rtwvif_link, p->tbtt_prohib, backup_val); } static void rtw89_mac_port_cfg_tx_rpt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, + B_AX_TXBCN_RPT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TXBCN_RPT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, + B_AX_TXBCN_RPT_EN); } static void rtw89_mac_port_cfg_rx_rpt(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, + B_AX_RXBCN_RPT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_RXBCN_RPT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, + B_AX_RXBCN_RPT_EN); } static void rtw89_mac_port_cfg_net_type(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->port_cfg, B_AX_NET_TYPE_MASK, - rtwvif->net_type); + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->port_cfg, B_AX_NET_TYPE_MASK, + rtwvif_link->net_type); } static void rtw89_mac_port_cfg_bcn_prct(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - bool en = rtwvif->net_type != RTW89_NET_TYPE_NO_LINK; + bool en = rtwvif_link->net_type != RTW89_NET_TYPE_NO_LINK; u32 bits = B_AX_TBTT_PROHIB_EN | B_AX_BRK_SETUP; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bits); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bits); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bits); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bits); } static void rtw89_mac_port_cfg_rx_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; u32 bit = B_AX_RX_BSSID_FIT_EN; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, bit); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, bit); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, bit); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, bit); } void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_TSF_UDT_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_TSF_UDT_EN); } static void rtw89_mac_port_cfg_rx_sync_by_nettype(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - bool en = rtwvif->net_type == RTW89_NET_TYPE_INFRA || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_INFRA || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; - rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en); + rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, en); } static void rtw89_mac_port_cfg_tx_sw(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (en) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, B_AX_BCNTX_EN); + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_BCNTX_EN); } static void rtw89_mac_port_cfg_tx_sw_by_nettype(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - bool en = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || - rtwvif->net_type == RTW89_NET_TYPE_AD_HOC; + bool en = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || + rtwvif_link->net_type == RTW89_NET_TYPE_AD_HOC; - rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) - rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif, en); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) + rtw89_mac_port_cfg_tx_sw(rtwdev, rtwvif_link, en); } static void rtw89_mac_port_cfg_bcn_intv(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - u16 bcn_int = vif->bss_conf.beacon_int ? vif->bss_conf.beacon_int : BCN_INTERVAL; + struct ieee80211_bss_conf *bss_conf; + u16 bcn_int; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (bss_conf->beacon_int) + bcn_int = bss_conf->beacon_int; + else + bcn_int = BCN_INTERVAL; + + rcu_read_unlock(); - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_space, B_AX_BCN_SPACE_MASK, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_space, B_AX_BCN_SPACE_MASK, bcn_int); } static void rtw89_mac_port_cfg_hiq_win(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { - u8 win = rtwvif->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; + u8 win = rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE ? 16 : 0; const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; - reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->hiq_win[port], rtwvif_link->mac_idx); rtw89_write8(rtwdev, reg, win); } static void rtw89_mac_port_cfg_hiq_dtim(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + u8 dtim_period; u32 addr; - addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif->mac_idx); + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + dtim_period = bss_conf->dtim_period; + + rcu_read_unlock(); + + addr = rtw89_mac_reg_by_idx(rtwdev, p->md_tsft, rtwvif_link->mac_idx); rtw89_write8_set(rtwdev, addr, B_AX_UPD_HGQMD | B_AX_UPD_TIMIE); - rtw89_write16_port_mask(rtwdev, rtwvif, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, - vif->bss_conf.dtim_period); + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->dtim_ctrl, B_AX_DTIM_NUM_MASK, + dtim_period); } static void rtw89_mac_port_cfg_bcn_setup_time(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_SETUP_MASK, BCN_SETUP_DEF); } static void rtw89_mac_port_cfg_bcn_hold_time(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->tbtt_prohib, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->tbtt_prohib, B_AX_TBTT_HOLD_MASK, BCN_HOLD_DEF); } static void rtw89_mac_port_cfg_bcn_mask_area(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_area, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_area, B_AX_BCN_MSK_AREA_MASK, BCN_MASK_DEF); } static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_early, + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_early, B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF); } static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); static const u32 masks[RTW89_PORT_NUM] = { B_AX_BSS_COLOB_AX_PORT_0_MASK, B_AX_BSS_COLOB_AX_PORT_1_MASK, B_AX_BSS_COLOB_AX_PORT_2_MASK, B_AX_BSS_COLOB_AX_PORT_3_MASK, B_AX_BSS_COLOB_AX_PORT_4_MASK, }; - u8 port = rtwvif->port; + struct ieee80211_bss_conf *bss_conf; + u8 port = rtwvif_link->port; u32 reg_base; u32 reg; u8 bss_color; - bss_color = vif->bss_conf.he_bss_color.color; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + bss_color = bss_conf->he_bss_color.color; + + rcu_read_unlock(); + reg_base = port >= 4 ? p->bss_color + 4 : p->bss_color; - reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, reg_base, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, masks[port], bss_color); } static void rtw89_mac_port_cfg_mbssid(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) return; if (port == 0) { - reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid, rtwvif_link->mac_idx); rtw89_write32_clr(rtwdev, reg, B_AX_P0MB_ALL_MASK); } } static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; u32 reg; u32 val; - reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->mbssid_drop, rtwvif_link->mac_idx); val = rtw89_read32(rtwdev, reg); val &= ~FIELD_PREP(B_AX_PORT_DROP_4_0_MASK, BIT(port)); if (port == 0) @@ -4419,31 +4469,31 @@ static void rtw89_mac_port_cfg_hiq_drop(struct rtw89_dev *rtwdev, } static void rtw89_mac_port_cfg_func_en(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool enable) + struct rtw89_vif_link *rtwvif_link, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; if (enable) - rtw89_write32_port_set(rtwdev, rtwvif, p->port_cfg, + rtw89_write32_port_set(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN); else - rtw89_write32_port_clr(rtwdev, rtwvif, p->port_cfg, + rtw89_write32_port_clr(rtwdev, rtwvif_link, p->port_cfg, B_AX_PORT_FUNC_EN); } static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - rtw89_write32_port_mask(rtwdev, rtwvif, p->bcn_early, B_AX_BCNERLY_MASK, + rtw89_write32_port_mask(rtwdev, rtwvif_link, p->bcn_early, B_AX_BCNERLY_MASK, BCN_ERLY_DEF); } static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; @@ -4452,20 +4502,20 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, if (rtwdev->chip->chip_id != RTL8852C) return; - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && - rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) return; val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) | B_AX_TBTT_SHIFT_OFST_SIGN; - rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift, + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift, B_AX_TBTT_SHIFT_OFST_MASK, val); } void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u16 offset_tu) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; @@ -4473,8 +4523,8 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, u32 val, reg; val = RTW89_PORT_OFFSET_TU_TO_32US(offset_tu); - reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif->port * 4, - rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, p->tsf_sync + rtwvif_link->port * 4, + rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port); rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val); @@ -4482,16 +4532,16 @@ void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, } static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u8 offset, int *n_offset) { - if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src) + if (rtwvif_link->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif_link == rtwvif_src) return; /* adjust offset randomly to avoid beacon conflict */ offset = offset - offset / 4 + get_random_u32() % (offset / 2); - rtw89_mac_port_tsf_sync(rtwdev, rtwvif, rtwvif_src, + rtw89_mac_port_tsf_sync(rtwdev, rtwvif_link, rtwvif_src, (*n_offset) * offset); (*n_offset)++; @@ -4499,15 +4549,19 @@ static void rtw89_mac_port_tsf_sync_rand(struct rtw89_dev *rtwdev, static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) { - struct rtw89_vif *src = NULL, *tmp; + struct rtw89_vif_link *src = NULL, *tmp; u8 offset = 100, vif_aps = 0; + struct rtw89_vif *rtwvif; + unsigned int link_id; int n_offset = 1; - rtw89_for_each_rtwvif(rtwdev, tmp) { - if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) - src = tmp; - if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) - vif_aps++; + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + rtw89_vif_for_each_link(rtwvif, tmp, link_id) { + if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) + src = tmp; + if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) + vif_aps++; + } } if (vif_aps == 0) @@ -4515,104 +4569,106 @@ static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) offset /= (vif_aps + 1); - rtw89_for_each_rtwvif(rtwdev, tmp) - rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, &n_offset); + rtw89_for_each_rtwvif(rtwdev, rtwvif) + rtw89_vif_for_each_link(rtwvif, tmp, link_id) + rtw89_mac_port_tsf_sync_rand(rtwdev, tmp, src, offset, + &n_offset); } -int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { int ret; - ret = rtw89_mac_port_update(rtwdev, rtwvif); + ret = rtw89_mac_port_update(rtwdev, rtwvif_link); if (ret) return ret; - rtw89_mac_dmac_tbl_init(rtwdev, rtwvif->mac_id); - rtw89_mac_cmac_tbl_init(rtwdev, rtwvif->mac_id); + rtw89_mac_dmac_tbl_init(rtwdev, rtwvif_link->mac_id); + rtw89_mac_cmac_tbl_init(rtwdev, rtwvif_link->mac_id); - ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif->mac_id, false); + ret = rtw89_mac_set_macid_pause(rtwdev, rtwvif_link->mac_id, false); if (ret) return ret; - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_CREATE); + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_CREATE); if (ret) return ret; - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); if (ret) return ret; - ret = rtw89_cam_init(rtwdev, rtwvif); + ret = rtw89_cam_init(rtwdev, rtwvif_link); if (ret) return ret; - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); if (ret) return ret; - ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif, NULL); + ret = rtw89_chip_h2c_default_cmac_tbl(rtwdev, rtwvif_link, NULL); if (ret) return ret; - ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif, NULL); + ret = rtw89_chip_h2c_default_dmac_tbl(rtwdev, rtwvif_link, NULL); if (ret) return ret; return 0; } -int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { int ret; - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_REMOVE); + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_REMOVE); if (ret) return ret; - rtw89_cam_deinit(rtwdev, rtwvif); + rtw89_cam_deinit(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); if (ret) return ret; return 0; } -int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - u8 port = rtwvif->port; + u8 port = rtwvif_link->port; if (port >= RTW89_PORT_NUM) return -EINVAL; - rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); - rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif, false); - rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif, false); - rtw89_mac_port_cfg_net_type(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif); - rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif); - rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif); - rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif); - rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif); - rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif); - rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif); - rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif); - rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif); - rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif); - rtw89_mac_port_cfg_func_en(rtwdev, rtwvif, true); + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tx_rpt(rtwdev, rtwvif_link, false); + rtw89_mac_port_cfg_rx_rpt(rtwdev, rtwvif_link, false); + rtw89_mac_port_cfg_net_type(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_prct(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_rx_sw(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_rx_sync_by_nettype(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tx_sw_by_nettype(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_intv(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_win(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_dtim(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_hiq_drop(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_setup_time(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true); rtw89_mac_port_tsf_resync_all(rtwdev); fsleep(BCN_ERLY_SET_DLY); - rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif); + rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif_link); return 0; } -int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u64 *tsf) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; @@ -4620,12 +4676,12 @@ int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 tsf_low, tsf_high; int ret; - ret = rtw89_mac_check_mac_en(rtwdev, rtwvif->mac_idx, RTW89_CMAC_SEL); + ret = rtw89_mac_check_mac_en(rtwdev, rtwvif_link->mac_idx, RTW89_CMAC_SEL); if (ret) return ret; - tsf_low = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_l); - tsf_high = rtw89_read32_port(rtwdev, rtwvif, p->tsftr_h); + tsf_low = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_l); + tsf_high = rtw89_read32_port(rtwdev, rtwvif_link, p->tsftr_h); *tsf = (u64)tsf_high << 32 | tsf_low; return 0; @@ -4651,65 +4707,57 @@ static void rtw89_mac_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, } void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; + struct ieee80211_bss_conf *bss_conf; + struct cfg80211_chan_def oper; bool tolerated = true; u32 reg; - if (!vif->bss_conf.he_support || vif->type != NL80211_IFTYPE_STATION) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (!bss_conf->he_support || vif->type != NL80211_IFTYPE_STATION) { + rcu_read_unlock(); return; + } - if (!(vif->bss_conf.chanreq.oper.chan->flags & IEEE80211_CHAN_RADAR)) + oper = bss_conf->chanreq.oper; + if (!(oper.chan->flags & IEEE80211_CHAN_RADAR)) { + rcu_read_unlock(); return; + } - cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chanreq.oper, + rcu_read_unlock(); + + cfg80211_bss_iter(hw->wiphy, &oper, rtw89_mac_check_he_obss_narrow_bw_ru_iter, &tolerated); reg = rtw89_mac_reg_by_idx(rtwdev, mac->narrow_bw_ru_dis.addr, - rtwvif->mac_idx); + rtwvif_link->mac_idx); if (tolerated) rtw89_write32_clr(rtwdev, reg, mac->narrow_bw_ru_dis.mask); else rtw89_write32_set(rtwdev, reg, mac->narrow_bw_ru_dis.mask); } -void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif); + rtw89_mac_port_cfg_func_sw(rtwdev, rtwvif_link); } -int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - int ret; - - rtwvif->mac_id = rtw89_acquire_mac_id(rtwdev); - if (rtwvif->mac_id == RTW89_MAX_MAC_ID_NUM) - return -ENOSPC; - - ret = rtw89_mac_vif_init(rtwdev, rtwvif); - if (ret) - goto release_mac_id; - - return 0; - -release_mac_id: - rtw89_release_mac_id(rtwdev, rtwvif->mac_id); - - return ret; + return rtw89_mac_vif_init(rtwdev, rtwvif_link); } -int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - int ret; - - ret = rtw89_mac_vif_deinit(rtwdev, rtwvif); - rtw89_release_mac_id(rtwdev, rtwvif->mac_id); - - return ret; + return rtw89_mac_vif_deinit(rtwdev, rtwvif_link); } static void @@ -4730,8 +4778,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, { const struct rtw89_c2h_scanofld *c2h = (const struct rtw89_c2h_scanofld *)skb->data; - struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); + struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif; + struct rtw89_vif *rtwvif; struct rtw89_chan new; u8 reason, status, tx_fail, band, actual_period, expect_period; u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf; @@ -4739,9 +4787,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, u16 chan; int ret; - if (!rtwvif) + if (!rtwvif_link) return; + rtwvif = rtwvif_link->rtwvif; + tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL); status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS); chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH); @@ -4781,28 +4831,28 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (rtwdev->scan_info.abort) return; - if (rtwvif && rtwvif->scan_req && + if (rtwvif_link && rtwvif->scan_req && last_chan < rtwvif->scan_req->n_channels) { - ret = rtw89_hw_scan_offload(rtwdev, vif, true); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); if (ret) { - rtw89_hw_scan_abort(rtwdev, vif); + rtw89_hw_scan_abort(rtwdev, rtwvif_link); rtw89_warn(rtwdev, "HW scan failed: %d\n", ret); } } else { - rtw89_hw_scan_complete(rtwdev, vif, false); + rtw89_hw_scan_complete(rtwdev, rtwvif_link, false); } break; case RTW89_SCAN_ENTER_OP_NOTIFY: case RTW89_SCAN_ENTER_CH_NOTIFY: if (rtw89_is_op_chan(rtwdev, band, chan)) { - rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, &rtwdev->scan_info.op_chan); rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); ieee80211_wake_queues(rtwdev->hw); } else { rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20); - rtw89_assign_entity_chan(rtwdev, rtwvif->chanctx_idx, + rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, &new); } break; @@ -4812,10 +4862,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, } static void -rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct sk_buff *skb) { - struct ieee80211_vif *vif = rtwvif_to_vif_safe(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; enum nl80211_cqm_rssi_threshold_event nl_event; const struct rtw89_c2h_mac_bcnfltr_rpt *c2h = (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data; @@ -4827,7 +4878,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, event = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT); mac_id = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_MACID); - if (mac_id != rtwvif->mac_id) + if (mac_id != rtwvif_link->mac_id) return; rtw89_debug(rtwdev, RTW89_DBG_FW, @@ -4839,7 +4890,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (!rtwdev->scanning && !rtwvif->offchan) ieee80211_connection_loss(vif); else - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); return; case RTW89_BCN_FLTR_NOTIFY: nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; @@ -4863,10 +4914,13 @@ static void rtw89_mac_c2h_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif, c2h); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bcn_fltr_rpt(rtwdev, rtwvif_link, c2h); } static void @@ -5490,7 +5544,8 @@ int rtw89_mac_cfg_ppdu_status_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab return 0; } -void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) +static +void __rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) { #define MAC_AX_TIME_TH_SH 5 #define MAC_AX_LEN_TH_SH 4 @@ -5520,6 +5575,13 @@ void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write16_mask(rtwdev, reg, B_AX_RTS_LEN_TH_MASK, len_th); } +void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev) +{ + __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + if (rtwdev->dbcc_en) + __rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_1); +} + void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop) { bool empty; @@ -5931,15 +5993,15 @@ static int rtw89_mac_init_bfee_ax(struct rtw89_dev *rtwdev, u8 mac_idx) } static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - u8 mac_idx = rtwvif->mac_idx; u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; - u8 port_sel = rtwvif->port; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; u8 sound_dim = 3, t; - u8 *phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + u8 *phy_cap; u32 reg; u16 val; int ret; @@ -5948,6 +6010,11 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, if (ret) return ret; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; + if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { ldpc_en &= !!(phy_cap[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD); @@ -5956,17 +6023,19 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, phy_cap[5]); sound_dim = min(sound_dim, t); } - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { - ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); t = FIELD_GET(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK, - sta->deflink.vht_cap.cap); + link_sta->vht_cap.cap); sound_dim = min(sound_dim, t); } nc = min(nc, sound_dim); nr = min(nr, sound_dim); + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); @@ -5989,34 +6058,41 @@ static int rtw89_mac_set_csi_para_reg_ax(struct rtw89_dev *rtwdev, } static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; u32 reg; - u8 mac_idx = rtwvif->mac_idx; int ret; ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) return ret; - if (sta->deflink.he_cap.has_he) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->he_cap.has_he) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); } - if (sta->deflink.ht_cap.ht_supported) { + if (link_sta->ht_cap.ht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); } + + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_AX_BFMEE_BFPARAM_SEL); rtw89_write32_clr(rtwdev, reg, B_AX_BFMEE_CSI_FORCE_RETE_EN); @@ -6028,35 +6104,53 @@ static int rtw89_mac_csi_rrsc_ax(struct rtw89_dev *rtwdev, } static void rtw89_mac_bf_assoc_ax(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; - if (rtw89_sta_has_beamformer_cap(sta)) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); + + rcu_read_unlock(); + + if (has_beamformer_cap) { rtw89_debug(rtwdev, RTW89_DBG_BF, "initialize bfee for new association\n"); - rtw89_mac_init_bfee_ax(rtwdev, rtwvif->mac_idx); - rtw89_mac_set_csi_para_reg_ax(rtwdev, vif, sta); - rtw89_mac_csi_rrsc_ax(rtwdev, vif, sta); + rtw89_mac_init_bfee_ax(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_ax(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_csi_rrsc_ax(rtwdev, rtwvif_link, rtwsta_link); } } -void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - - rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, false); + rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, false); } void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; - u8 mac_idx = rtwvif->mac_idx; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + u8 mac_idx; __le32 *p; + rtwvif_link = rtwvif->links[conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, conf->link_id); + return; + } + + mac_idx = rtwvif_link->mac_idx; + rtw89_debug(rtwdev, RTW89_DBG_BF, "update bf GID table\n"); p = (__le32 *)conf->mu_group.membership; @@ -6080,7 +6174,7 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * struct rtw89_mac_bf_monitor_iter_data { struct rtw89_dev *rtwdev; - struct ieee80211_sta *down_sta; + struct rtw89_sta_link *down_rtwsta_link; int count; }; @@ -6089,23 +6183,41 @@ void rtw89_mac_bf_monitor_calc_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_mac_bf_monitor_iter_data *iter_data = (struct rtw89_mac_bf_monitor_iter_data *)data; - struct ieee80211_sta *down_sta = iter_data->down_sta; + struct rtw89_sta_link *down_rtwsta_link = iter_data->down_rtwsta_link; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct ieee80211_link_sta *link_sta; + struct rtw89_sta_link *rtwsta_link; + bool has_beamformer_cap = false; int *count = &iter_data->count; + unsigned int link_id; - if (down_sta == sta) - return; + rcu_read_lock(); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + if (rtwsta_link == down_rtwsta_link) + continue; + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + if (rtw89_sta_has_beamformer_cap(link_sta)) { + has_beamformer_cap = true; + break; + } + } - if (rtw89_sta_has_beamformer_cap(sta)) + if (has_beamformer_cap) (*count)++; + + rcu_read_unlock(); } void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool disconnect) + struct rtw89_sta_link *rtwsta_link, + bool disconnect) { struct rtw89_mac_bf_monitor_iter_data data; data.rtwdev = rtwdev; - data.down_sta = disconnect ? sta : NULL; + data.down_rtwsta_link = disconnect ? rtwsta_link : NULL; data.count = 0; ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_mac_bf_monitor_calc_iter, @@ -6121,10 +6233,12 @@ void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) { struct rtw89_traffic_stats *stats = &rtwdev->stats; - struct rtw89_vif *rtwvif; + struct rtw89_vif_link *rtwvif_link; bool en = stats->tx_tfc_lv <= stats->rx_tfc_lv; bool old = test_bit(RTW89_FLAG_BFEE_EN, rtwdev->flags); + struct rtw89_vif *rtwvif; bool keep_timer = true; + unsigned int link_id; bool old_keep_timer; old_keep_timer = test_bit(RTW89_FLAG_BFEE_TIMER_KEEP, rtwdev->flags); @@ -6134,30 +6248,32 @@ void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) if (keep_timer != old_keep_timer) { rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bfee_standby_timer(rtwdev, rtwvif->mac_idx, - keep_timer); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bfee_standby_timer(rtwdev, rtwvif_link->mac_idx, + keep_timer); } if (en == old) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_bfee_ctrl(rtwdev, rtwvif->mac_idx, en); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_bfee_ctrl(rtwdev, rtwvif_link->mac_idx, en); } static int -__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +__rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 tx_time) { #define MAC_AX_DFLT_TX_TIME 5280 - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 max_tx_time = tx_time == 0 ? MAC_AX_DFLT_TX_TIME : tx_time; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_time) { - rtwsta->ampdu_max_time = (max_tx_time - 512) >> 9; - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); + if (rtwsta_link->cctl_tx_time) { + rtwsta_link->ampdu_max_time = (max_tx_time - 512) >> 9; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6173,31 +6289,31 @@ __rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return ret; } -int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, bool resume, u32 tx_time) { int ret = 0; if (!resume) { - rtwsta->cctl_tx_time = true; - ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); + rtwsta_link->cctl_tx_time = true; + ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); } else { - ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta, tx_time); - rtwsta->cctl_tx_time = false; + ret = __rtw89_mac_set_tx_time(rtwdev, rtwsta_link, tx_time); + rtwsta_link->cctl_tx_time = false; } return ret; } -int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 *tx_time) { - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_time) { - *tx_time = (rtwsta->ampdu_max_time + 1) << 9; + if (rtwsta_link->cctl_tx_time) { + *tx_time = (rtwsta_link->ampdu_max_time + 1) << 9; } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6213,33 +6329,33 @@ int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, } int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, bool resume, u8 tx_retry) { int ret = 0; - rtwsta->data_tx_cnt_lmt = tx_retry; + rtwsta_link->data_tx_cnt_lmt = tx_retry; if (!resume) { - rtwsta->cctl_tx_retry_limit = true; - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); + rtwsta_link->cctl_tx_retry_limit = true; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); } else { - ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta); - rtwsta->cctl_tx_retry_limit = false; + ret = rtw89_fw_h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); + rtwsta_link->cctl_tx_retry_limit = false; } return ret; } int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 *tx_retry) + struct rtw89_sta_link *rtwsta_link, u8 *tx_retry) { - u8 mac_idx = rtwsta->rtwvif->mac_idx; + u8 mac_idx = rtwsta_link->rtwvif_link->mac_idx; u32 reg; int ret = 0; - if (rtwsta->cctl_tx_retry_limit) { - *tx_retry = rtwsta->data_tx_cnt_lmt; + if (rtwsta_link->cctl_tx_retry_limit) { + *tx_retry = rtwsta_link->data_tx_cnt_lmt; } else { ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) { @@ -6255,10 +6371,10 @@ int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, } int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en) + struct rtw89_vif_link *rtwvif_link, bool en) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; - u8 mac_idx = rtwvif->mac_idx; + u8 mac_idx = rtwvif_link->mac_idx; u16 set = mac->muedca_ctrl.mask; u32 reg; u32 ret; @@ -6326,7 +6442,9 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val) } static -void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) +void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { static const enum rtw89_pkt_drop_sel sels[] = { RTW89_PKT_DROP_SEL_MACID_BE_ONCE, @@ -6334,15 +6452,14 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) RTW89_PKT_DROP_SEL_MACID_VI_ONCE, RTW89_PKT_DROP_SEL_MACID_VO_ONCE, }; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_pkt_drop_params params = {0}; int i; - params.mac_band = RTW89_MAC_0; - params.macid = rtwsta->mac_id; - params.port = rtwvif->port; + params.mac_band = rtwvif_link->mac_idx; + params.macid = rtwsta_link->mac_id; + params.port = rtwvif_link->port; params.mbssid = 0; - params.tf_trs = rtwvif->trigger; + params.tf_trs = rtwvif_link->trigger; for (i = 0; i < ARRAY_SIZE(sels); i++) { params.sel = sels[i]; @@ -6352,15 +6469,21 @@ void rtw89_mac_pkt_drop_sta(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta) static void rtw89_mac_pkt_drop_vif_iter(void *data, struct ieee80211_sta *sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; struct rtw89_vif *target = data; + unsigned int link_id; if (rtwvif != target) return; - rtw89_mac_pkt_drop_sta(rtwdev, rtwsta); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + rtw89_mac_pkt_drop_sta(rtwdev, rtwvif_link, rtwsta_link); + } } void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) @@ -6398,6 +6521,9 @@ int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable) struct rtw89_mac_c2h_info c2h_info = {}; u32 ret; + if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw)) + return 0; + h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_WOW_CPUIO_RX_CTRL; h2c_info.content_len = sizeof(h2c_info.u.hdr); h2c_info.u.hdr.w0 = u32_encode_bits(wow_enable, RTW89_H2CREG_WOW_CPUIO_RX_CTRL_EN); @@ -6434,6 +6560,9 @@ static int rtw89_wow_config_mac_ax(struct rtw89_dev *rtwdev, bool enable_wow) rtw89_write32(rtwdev, R_AX_TF_FWD, 0); rtw89_write32(rtwdev, R_AX_HW_RPT_FWD, 0); + if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw)) + return 0; + if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) rtw89_write8(rtwdev, R_BE_DBG_WOW_READY, WOWLAN_NOT_READY); else diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 67c2a4507124..e59c1fcfea46 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -951,8 +951,9 @@ struct rtw89_mac_gen_def { void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev); void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable); void (*dle_clk_en)(struct rtw89_dev *rtwdev, bool enable); - void (*bf_assoc)(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + void (*bf_assoc)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int (*typ_fltr_opt)(struct rtw89_dev *rtwdev, enum rtw89_machdr_frame_type type, @@ -1004,12 +1005,12 @@ struct rtw89_mac_gen_def { bool (*is_txq_empty)(struct rtw89_dev *rtwdev); int (*add_chan_list)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool connected); + struct rtw89_vif_link *rtwvif_link, bool connected); int (*add_chan_list_pno)(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); int (*scan_offload)(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, bool wowlan); int (*wow_config_mac)(struct rtw89_dev *rtwdev, bool enable_wow); @@ -1033,81 +1034,89 @@ u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_id } static inline u32 -rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base) +rtw89_read32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); return rtw89_read32(rtwdev, reg); } static inline u32 -rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_read32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); return rtw89_read32_mask(rtwdev, reg, mask); } static inline void -rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, u32 base, +rtw89_write32_port(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32(rtwdev, reg, data); } static inline void -rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask, u32 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, mask, data); } static inline void -rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write16_port_mask(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 mask, u16 data) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write16_mask(rtwdev, reg, mask, data); } static inline void -rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_clr(rtwdev, reg, bit); } static inline void -rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write16_port_clr(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u16 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write16_clr(rtwdev, reg, bit); } static inline void -rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u32 base, u32 bit) { u32 reg; - reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif->port, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_port(rtwdev, base, rtwvif_link->port, + rtwvif_link->mac_idx); rtw89_write32_set(rtwdev, reg, bit); } @@ -1139,21 +1148,21 @@ int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_qempty *qempty); void rtw89_mac_dump_l0_to_l1(struct rtw89_dev *rtwdev, enum mac_ax_err_info err); -int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); -int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_mac_add_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); +int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, - struct rtw89_vif *rtwvif_src, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_vif_link *rtwvif_src, u16 offset_tu); -int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_mac_port_get_tsf(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u64 *tsf); void rtw89_mac_port_cfg_rx_sync(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en); + struct rtw89_vif_link *rtwvif_link, bool en); void rtw89_mac_set_he_obss_narrow_bw_ru(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif); -void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); + struct rtw89_vif_link *rtwvif_link); +void rtw89_mac_stop_ap(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_mac_enable_beacon_for_ap_vifs(struct rtw89_dev *rtwdev, bool en); -int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *vif); +int rtw89_mac_remove_vif(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); int rtw89_mac_enable_bb_rf(struct rtw89_dev *rtwdev); int rtw89_mac_disable_bb_rf(struct rtw89_dev *rtwdev); @@ -1213,7 +1222,22 @@ int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) return mac->cfg_ppdu_status(rtwdev, mac_idx, enable); } -void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev, u8 mac_idx); +static inline +int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable) +{ + int ret; + + ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, enable); + if (ret) + return ret; + + if (!rtwdev->dbcc_en) + return 0; + + return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable); +} + +void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev); void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop); int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex); int rtw89_mac_coex_init_v1(struct rtw89_dev *rtwdev, @@ -1251,27 +1275,30 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter); void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev); static inline -void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void rtw89_mac_bf_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; if (mac->bf_assoc) - mac->bf_assoc(rtwdev, vif, sta); + mac->bf_assoc(rtwdev, rtwvif_link, rtwsta_link); } -void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); +void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf); void rtw89_mac_bf_monitor_calc(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool disconnect); + struct rtw89_sta_link *rtwsta_link, + bool disconnect); void _rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev); void rtw89_mac_bfee_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx, bool en); -int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); -int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool en); + struct rtw89_vif_link *rtwvif_link, bool en); int rtw89_mac_set_macid_pause(struct rtw89_dev *rtwdev, u8 macid, bool pause); static inline void rtw89_mac_bf_monitor_track(struct rtw89_dev *rtwdev) @@ -1376,15 +1403,15 @@ static inline bool rtw89_mac_get_power_state(struct rtw89_dev *rtwdev) return !!val; } -int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_set_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, bool resume, u32 tx_time); -int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +int rtw89_mac_get_tx_time(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link, u32 *tx_time); int rtw89_mac_set_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, bool resume, u8 tx_retry); int rtw89_mac_get_tx_retry_limit(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, u8 *tx_retry); + struct rtw89_sta_link *rtwsta_link, u8 *tx_retry); enum rtw89_mac_xtal_si_offset { XTAL0 = 0x0, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 48ad0d0f76bf..3f33c3a2ae7d 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -23,13 +23,13 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw, struct rtw89_dev *rtwdev = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct ieee80211_sta *sta = control->sta; u32 flags = IEEE80211_SKB_CB(skb)->flags; int ret, qsel; if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n"); skb_queue_tail(&rtwsta->roc_queue, skb); @@ -105,11 +105,61 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed) return 0; } +static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct ieee80211_bss_conf *bss_conf; + int ret; + + rtw89_leave_ps_mode(rtwdev); + + rtw89_vif_type_mapping(rtwvif_link, false); + + INIT_WORK(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); + INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); + + rtwvif_link->hit_rule = 0; + rtwvif_link->bcn_hit_cond = 0; + rtwvif_link->chanctx_assigned = false; + rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ether_addr_copy(rtwvif_link->mac_addr, bss_conf->addr); + + rcu_read_unlock(); + + ret = rtw89_mac_add_vif(rtwdev, rtwvif_link); + if (ret) + return ret; + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_START); + return 0; +} + +static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + mutex_unlock(&rtwdev->mutex); + cancel_work_sync(&rtwvif_link->update_beacon_work); + mutex_lock(&rtwdev->mutex); + + rtw89_leave_ps_mode(rtwdev); + + rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, NULL, BTC_ROLE_STOP); + + rtw89_mac_remove_vif(rtwdev, rtwvif_link); +} + static int rtw89_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + u8 mac_id, port; int ret = 0; rtw89_debug(rtwdev, RTW89_DBG_STATE, "add vif %pM type %d, p2p %d\n", @@ -123,49 +173,56 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_CQM_RSSI; - rtwvif->rtwdev = rtwdev; - rtwvif->roc.state = RTW89_ROC_IDLE; - rtwvif->offchan = false; + mac_id = rtw89_acquire_mac_id(rtwdev); + if (mac_id == RTW89_MAX_MAC_ID_NUM) { + ret = -ENOSPC; + goto err; + } + + port = rtw89_core_acquire_bit_map(rtwdev->hw_port, RTW89_PORT_NUM); + if (port == RTW89_PORT_NUM) { + ret = -ENOSPC; + goto release_macid; + } + + rtw89_init_vif(rtwdev, rtwvif, mac_id, port); + + rtw89_core_txq_init(rtwdev, vif->txq); + if (!rtw89_rtwvif_in_list(rtwdev, rtwvif)) list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list); - INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work); + ether_addr_copy(rtwvif->mac_addr, vif->addr); + + rtwvif->offchan = false; + rtwvif->roc.state = RTW89_ROC_IDLE; INIT_DELAYED_WORK(&rtwvif->roc.roc_work, rtw89_roc_work); - rtw89_leave_ps_mode(rtwdev); rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); - rtw89_vif_type_mapping(vif, false); - rtwvif->port = rtw89_core_acquire_bit_map(rtwdev->hw_port, - RTW89_PORT_NUM); - if (rtwvif->port == RTW89_PORT_NUM) { - ret = -ENOSPC; - list_del_init(&rtwvif->list); - goto out; - } - rtwvif->bcn_hit_cond = 0; - rtwvif->mac_idx = RTW89_MAC_0; - rtwvif->phy_idx = RTW89_PHY_0; - rtwvif->chanctx_idx = RTW89_CHANCTX_0; - rtwvif->chanctx_assigned = false; - rtwvif->hit_rule = 0; - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; - ether_addr_copy(rtwvif->mac_addr, vif->addr); - INIT_LIST_HEAD(&rtwvif->general_pkt_list); - - ret = rtw89_mac_add_vif(rtwdev, rtwvif); - if (ret) { - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); - list_del_init(&rtwvif->list); - goto out; + rtwvif_link = rtw89_vif_set_link(rtwvif, 0); + if (!rtwvif_link) { + ret = -EINVAL; + goto release_port; } - rtw89_core_txq_init(rtwdev, vif->txq); - - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START); + ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link); + if (ret) + goto unset_link; rtw89_recalc_lps(rtwdev); -out: + + mutex_unlock(&rtwdev->mutex); + return 0; + +unset_link: + rtw89_vif_unset_link(rtwvif, 0); +release_port: + list_del_init(&rtwvif->list); + rtw89_core_release_bit_map(rtwdev->hw_port, port); +release_macid: + rtw89_release_mac_id(rtwdev, mac_id); +err: mutex_unlock(&rtwdev->mutex); return ret; @@ -175,20 +232,35 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + u8 macid = rtw89_vif_get_main_macid(rtwvif); + u8 port = rtw89_vif_get_main_port(rtwvif); + struct rtw89_vif_link *rtwvif_link; rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n", vif->addr, vif->type, vif->p2p); - cancel_work_sync(&rtwvif->update_beacon_work); cancel_delayed_work_sync(&rtwvif->roc.roc_work); mutex_lock(&rtwdev->mutex); - rtw89_leave_ps_mode(rtwdev); - rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP); - rtw89_mac_remove_vif(rtwdev, rtwvif); - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); + + rtwvif_link = rtwvif->links[0]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, 0); + goto bottom; + } + + __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link); + + rtw89_vif_unset_link(rtwvif, 0); + +bottom: list_del_init(&rtwvif->list); + rtw89_core_release_bit_map(rtwdev->hw_port, port); + rtw89_release_mac_id(rtwdev, macid); + rtw89_recalc_lps(rtwdev); rtw89_enter_ips_by_hwflags(rtwdev); @@ -311,24 +383,30 @@ static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { }; static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u8 aifsn) + struct rtw89_vif_link *rtwvif_link, u8 aifsn) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); + struct ieee80211_bss_conf *bss_conf; u8 slot_time; u8 sifs; - slot_time = vif->bss_conf.use_short_slot ? 9 : 20; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + slot_time = bss_conf->use_short_slot ? 9 : 20; + + rcu_read_unlock(); + sifs = chan->band_type == RTW89_BAND_2G ? 10 : 16; return aifsn * slot_time + sifs; } static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; + struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; u32 val; u8 ecw_max, ecw_min; u8 aifs; @@ -336,12 +414,12 @@ static void ____rtw89_conf_tx_edca(struct rtw89_dev *rtwdev, /* 2^ecw - 1 = cw; ecw = log2(cw + 1) */ ecw_max = ilog2(params->cw_max + 1); ecw_min = ilog2(params->cw_min + 1); - aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif, params->aifs); + aifs = rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, params->aifs); val = FIELD_PREP(FW_EDCA_PARAM_TXOPLMT_MSK, params->txop) | FIELD_PREP(FW_EDCA_PARAM_CWMAX_MSK, ecw_max) | FIELD_PREP(FW_EDCA_PARAM_CWMIN_MSK, ecw_min) | FIELD_PREP(FW_EDCA_PARAM_AIFS_MSK, aifs); - rtw89_fw_h2c_set_edca(rtwdev, rtwvif, ac_to_fw_idx[ac], val); + rtw89_fw_h2c_set_edca(rtwdev, rtwvif_link, ac_to_fw_idx[ac], val); } #define R_MUEDCA_ACS_PARAM(acs) {R_AX_MUEDCA_ ## acs ## _PARAM_0, \ @@ -355,9 +433,9 @@ static const u32 ac_to_mu_edca_param[IEEE80211_NUM_ACS][RTW89_CHIP_GEN_NUM] = { }; static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac]; + struct ieee80211_tx_queue_params *params = &rtwvif_link->tx_params[ac]; struct ieee80211_he_mu_edca_param_ac_rec *mu_edca; int gen = rtwdev->chip->chip_gen; u8 aifs, aifsn; @@ -370,32 +448,199 @@ static void ____rtw89_conf_tx_mu_edca(struct rtw89_dev *rtwdev, mu_edca = ¶ms->mu_edca_param_rec; aifsn = FIELD_GET(GENMASK(3, 0), mu_edca->aifsn); - aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif, aifsn) : 0; + aifs = aifsn ? rtw89_aifsn_to_aifs(rtwdev, rtwvif_link, aifsn) : 0; timer_32us = mu_edca->mu_edca_timer << 8; val = FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_TIMER_MASK, timer_32us) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_CW_MASK, mu_edca->ecw_min_max) | FIELD_PREP(B_AX_MUEDCA_BE_PARAM_0_AIFS_MASK, aifs); - reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, ac_to_mu_edca_param[ac][gen], + rtwvif_link->mac_idx); rtw89_write32(rtwdev, reg, val); - rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif, true); + rtw89_mac_set_hw_muedca_ctrl(rtwdev, rtwvif_link, true); } static void __rtw89_conf_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, u16 ac) + struct rtw89_vif_link *rtwvif_link, u16 ac) { - ____rtw89_conf_tx_edca(rtwdev, rtwvif, ac); - ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif, ac); + ____rtw89_conf_tx_edca(rtwdev, rtwvif_link, ac); + ____rtw89_conf_tx_mu_edca(rtwdev, rtwvif_link, ac); } static void rtw89_conf_tx(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { u16 ac; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - __rtw89_conf_tx(rtwdev, rtwvif, ac); + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); +} + +static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + bool acquire_macid = false; + u8 macid; + int ret; + int i; + + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + /* for station mode, assign the mac_id from itself */ + macid = rtw89_vif_get_main_macid(rtwvif); + } else { + macid = rtw89_acquire_mac_id(rtwdev); + if (macid == RTW89_MAX_MAC_ID_NUM) + return -ENOSPC; + + acquire_macid = true; + } + + rtw89_init_sta(rtwdev, rtwvif, rtwsta, macid); + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) + rtw89_core_txq_init(rtwdev, sta->txq[i]); + + skb_queue_head_init(&rtwsta->roc_queue); + + rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id); + if (!rtwsta_link) { + ret = -EINVAL; + goto err; + } + + rtwvif_link = rtwsta_link->rtwvif_link; + + ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + goto unset_link; + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + + return 0; + +unset_link: + rtw89_sta_unset_link(rtwsta, sta->deflink.link_id); +err: + if (acquire_macid) + rtw89_release_mac_id(rtwdev, macid); + + return ret; +} + +static int __rtw89_ops_sta_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool station_mode) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + + if (station_mode) + rtw89_vif_type_mapping(rtwvif_link, true); + + ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + rtwdev->total_sta_assoc++; + if (sta->tdls) + rtwvif->tdls_peer++; + + return 0; +} + +static int __rtw89_ops_sta_disassoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + rtwsta->disassoc = true; + + rtwdev->total_sta_assoc--; + if (sta->tdls) + rtwvif->tdls_peer--; + + return 0; +} + +static int __rtw89_ops_sta_disconnect(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_core_free_sta_pending_ba(rtwdev, sta); + rtw89_core_free_sta_pending_forbid_ba(rtwdev, sta); + rtw89_core_free_sta_pending_roc_tx(rtwdev, sta); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + } + + return 0; +} + +static int __rtw89_ops_sta_remove(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + u8 macid = rtw89_sta_get_main_macid(rtwsta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + int ret; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + ret = rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link); + if (ret) + return ret; + + rtw89_sta_unset_link(rtwsta, link_id); + } + + if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + rtw89_release_mac_id(rtwdev, macid); + rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_REMOTE_STA_CHANGE); + } + + return 0; } static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, @@ -412,16 +657,34 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev, return; } - rtw89_vif_type_mapping(vif, true); + __rtw89_ops_sta_assoc(rtwdev, vif, sta, true); +} + +static void __rtw89_ops_bss_link_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, rtwvif_link); +} + +static void __rtw89_ops_bss_assoc(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - rtw89_core_sta_assoc(rtwdev, vif, sta); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link); } static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 changed) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); @@ -429,10 +692,7 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (vif->cfg.assoc) { rtw89_station_mode_sta_assoc(rtwdev, vif); - rtw89_phy_set_bss_color(rtwdev, vif); - rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, vif); - rtw89_mac_port_update(rtwdev, rtwvif); - rtw89_mac_set_he_obss_narrow_bw_ru(rtwdev, vif); + __rtw89_ops_bss_assoc(rtwdev, vif); rtw89_queue_chanctx_work(rtwdev); } else { @@ -459,39 +719,49 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, u64 changed) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); + rtwvif_link = rtwvif->links[conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, conf->link_id); + goto out; + } + if (changed & BSS_CHANGED_BSSID) { - ether_addr_copy(rtwvif->bssid, conf->bssid); - rtw89_cam_bssid_changed(rtwdev, rtwvif); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); - WRITE_ONCE(rtwvif->sync_bcn_tsf, 0); + ether_addr_copy(rtwvif_link->bssid, conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0); } if (changed & BSS_CHANGED_BEACON) - rtw89_chip_h2c_update_beacon(rtwdev, rtwvif); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_ERP_SLOT) - rtw89_conf_tx(rtwdev, rtwvif); + rtw89_conf_tx(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_HE_BSS_COLOR) - rtw89_phy_set_bss_color(rtwdev, vif); + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); if (changed & BSS_CHANGED_MU_GROUPS) rtw89_mac_bf_set_gid_table(rtwdev, vif, conf); if (changed & BSS_CHANGED_P2P_PS) - rtw89_core_update_p2p_ps(rtwdev, vif); + rtw89_core_update_p2p_ps(rtwdev, rtwvif_link, conf); if (changed & BSS_CHANGED_CQM) - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); if (changed & BSS_CHANGED_TPE) - rtw89_reg_6ghz_recalc(rtwdev, rtwvif, true); + rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); +out: mutex_unlock(&rtwdev->mutex); } @@ -500,12 +770,21 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, struct ieee80211_bss_conf *link_conf) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; const struct rtw89_chan *chan; mutex_lock(&rtwdev->mutex); - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + goto out; + } + + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); if (chan->band_type == RTW89_BAND_6G) { mutex_unlock(&rtwdev->mutex); return -EOPNOTSUPP; @@ -514,16 +793,18 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, if (rtwdev->scanning) rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); - ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid); - rtw89_cam_bssid_changed(rtwdev, rtwvif); - rtw89_mac_port_update(rtwdev, rtwvif); - rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); - rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, NULL, RTW89_ROLE_TYPE_CHANGE); - rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif, NULL, NULL); - rtw89_chip_rfk_channel(rtwdev, rtwvif); + ether_addr_copy(rtwvif_link->bssid, link_conf->bssid); + rtw89_cam_bssid_changed(rtwdev, rtwvif_link); + rtw89_mac_port_update(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); rtw89_queue_chanctx_work(rtwdev); + +out: mutex_unlock(&rtwdev->mutex); return 0; @@ -534,12 +815,24 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_mac_stop_ap(rtwdev, rtwvif); - rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, vif, NULL); - rtw89_fw_h2c_join_info(rtwdev, rtwvif, NULL, true); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + goto out; + } + + rtw89_mac_stop_ap(rtwdev, rtwvif_link); + rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); + rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); + +out: mutex_unlock(&rtwdev->mutex); } @@ -547,10 +840,13 @@ static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; - ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + ieee80211_queue_work(rtwdev->hw, &rtwvif_link->update_beacon_work); return 0; } @@ -561,15 +857,29 @@ static int rtw89_ops_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + int ret = 0; mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); - rtwvif->tx_params[ac] = *params; - __rtw89_conf_tx(rtwdev, rtwvif, ac); + + rtwvif_link = rtwvif->links[link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_id); + ret = -ENOLINK; + goto out; + } + + rtwvif_link->tx_params[ac] = *params; + __rtw89_conf_tx(rtwdev, rtwvif_link, ac); + +out: mutex_unlock(&rtwdev->mutex); - return 0; + return ret; } static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, @@ -582,26 +892,26 @@ static int __rtw89_ops_sta_state(struct ieee80211_hw *hw, if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) - return rtw89_core_sta_add(rtwdev, vif, sta); + return __rtw89_ops_sta_add(rtwdev, vif, sta); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) return 0; /* defer to bss_info_changed to have vif info */ - return rtw89_core_sta_assoc(rtwdev, vif, sta); + return __rtw89_ops_sta_assoc(rtwdev, vif, sta, false); } if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) - return rtw89_core_sta_disassoc(rtwdev, vif, sta); + return __rtw89_ops_sta_disassoc(rtwdev, vif, sta); if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_NONE) - return rtw89_core_sta_disconnect(rtwdev, vif, sta); + return __rtw89_ops_sta_disconnect(rtwdev, vif, sta); if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST) - return rtw89_core_sta_remove(rtwdev, vif, sta); + return __rtw89_ops_sta_remove(rtwdev, vif, sta); return 0; } @@ -667,7 +977,8 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, { struct rtw89_dev *rtwdev = hw->priv; struct ieee80211_sta *sta = params->sta; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); u16 tid = params->tid; struct ieee80211_txq *txq = sta->txq[tid]; struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv; @@ -681,7 +992,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, mutex_lock(&rtwdev->mutex); clear_bit(RTW89_TXQ_F_AMPDU, &rtwtxq->flags); clear_bit(tid, rtwsta->ampdu_map); - rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); mutex_unlock(&rtwdev->mutex); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -692,7 +1003,7 @@ static int rtw89_ops_ampdu_action(struct ieee80211_hw *hw, rtwsta->ampdu_params[tid].amsdu = params->amsdu; set_bit(tid, rtwsta->ampdu_map); rtw89_leave_ps_mode(rtwdev); - rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, vif, sta); + rtw89_chip_h2c_ampdu_cmac_tbl(rtwdev, rtwvif, rtwsta); mutex_unlock(&rtwdev->mutex); break; case IEEE80211_AMPDU_RX_START: @@ -720,7 +1031,7 @@ static int rtw89_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) - rtw89_mac_update_rts_threshold(rtwdev, RTW89_MAC_0); + rtw89_mac_update_rts_threshold(rtwdev); mutex_unlock(&rtwdev->mutex); return 0; @@ -731,9 +1042,14 @@ static void rtw89_ops_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct station_info *sinfo) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + + rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0); + if (unlikely(!rtwsta_link)) + return; - sinfo->txrate = rtwsta->ra_report.txrate; + sinfo->txrate = rtwsta_link->ra_report.txrate; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } @@ -743,7 +1059,7 @@ void __rtw89_drop_packets(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) struct rtw89_vif *rtwvif; if (vif) { - rtwvif = (struct rtw89_vif *)vif->drv_priv; + rtwvif = vif_to_rtwvif(vif); rtw89_mac_pkt_drop_vif(rtwdev, rtwvif); } else { rtw89_for_each_rtwvif(rtwdev, rtwvif) @@ -777,14 +1093,20 @@ struct rtw89_iter_bitrate_mask_data { static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_iter_bitrate_mask_data *br_data = data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; if (vif != br_data->vif || vif->p2p) return; - rtwsta->use_cfg_mask = true; - rtwsta->mask = *br_data->mask; + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwsta_link->use_cfg_mask = true; + rtwsta_link->mask = *br_data->mask; + } + rtw89_phy_ra_update_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED); } @@ -854,10 +1176,20 @@ static void rtw89_ops_sw_scan_start(struct ieee80211_hw *hw, const u8 *mac_addr) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, false); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "sw scan start: find no link on HW-0\n"); + goto out; + } + + rtw89_core_scan_start(rtwdev, rtwvif_link, mac_addr, false); + +out: mutex_unlock(&rtwdev->mutex); } @@ -865,9 +1197,20 @@ static void rtw89_ops_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_core_scan_complete(rtwdev, vif, false); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "sw scan complete: find no link on HW-0\n"); + goto out; + } + + rtw89_core_scan_complete(rtwdev, rtwvif_link, false); + +out: mutex_unlock(&rtwdev->mutex); } @@ -884,22 +1227,35 @@ static int rtw89_ops_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); - int ret = 0; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + int ret; if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) return 1; - if (rtwdev->scanning || rtwvif->offchan) - return -EBUSY; - mutex_lock(&rtwdev->mutex); - rtw89_hw_scan_start(rtwdev, vif, req); - ret = rtw89_hw_scan_offload(rtwdev, vif, true); + + if (rtwdev->scanning || rtwvif->offchan) { + ret = -EBUSY; + goto out; + } + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "hw scan: find no link on HW-0\n"); + ret = -ENOLINK; + goto out; + } + + rtw89_hw_scan_start(rtwdev, rtwvif_link, req); + ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); if (ret) { - rtw89_hw_scan_abort(rtwdev, vif); + rtw89_hw_scan_abort(rtwdev, rtwvif_link); rtw89_err(rtwdev, "HW scan failed with status: %d\n", ret); } + +out: mutex_unlock(&rtwdev->mutex); return ret; @@ -909,6 +1265,8 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; if (!RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) return; @@ -917,14 +1275,25 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw, return; mutex_lock(&rtwdev->mutex); - rtw89_hw_scan_abort(rtwdev, vif); + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, "cancel hw scan: find no link on HW-0\n"); + goto out; + } + + rtw89_hw_scan_abort(rtwdev, rtwvif_link); + +out: mutex_unlock(&rtwdev->mutex); } static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u32 changed) + struct ieee80211_link_sta *link_sta, + u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct rtw89_dev *rtwdev = hw->priv; rtw89_phy_ra_update_sta(rtwdev, sta, changed); @@ -970,11 +1339,24 @@ static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; int ret; mutex_lock(&rtwdev->mutex); - ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + ret = -ENOLINK; + goto out; + } + + ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, ctx); + +out: mutex_unlock(&rtwdev->mutex); return ret; @@ -986,10 +1368,20 @@ static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct rtw89_dev *rtwdev = hw->priv; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; mutex_lock(&rtwdev->mutex); - rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx); + + rtwvif_link = rtwvif->links[link_conf->link_id]; + if (unlikely(!rtwvif_link)) { + rtw89_err(rtwdev, + "%s: rtwvif link (link_id %u) is not active\n", + __func__, link_conf->link_id); + return; + } + + rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, ctx); mutex_unlock(&rtwdev->mutex); } @@ -1003,7 +1395,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw, struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif); struct rtw89_roc *roc = &rtwvif->roc; - if (!vif) + if (!rtwvif) return -EINVAL; mutex_lock(&rtwdev->mutex); @@ -1053,8 +1445,8 @@ static int rtw89_ops_cancel_remain_on_channel(struct ieee80211_hw *hw, static void rtw89_set_tid_config_iter(void *data, struct ieee80211_sta *sta) { struct cfg80211_tid_config *tid_config = data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwvif->rtwdev; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; rtw89_core_set_tid_config(rtwdev, sta, tid_config); } @@ -1203,7 +1595,7 @@ const struct ieee80211_ops rtw89_ops = { .remain_on_channel = rtw89_ops_remain_on_channel, .cancel_remain_on_channel = rtw89_ops_cancel_remain_on_channel, .set_sar_specs = rtw89_ops_set_sar_specs, - .sta_rc_update = rtw89_ops_sta_rc_update, + .link_sta_rc_update = rtw89_ops_sta_rc_update, .set_tid_config = rtw89_ops_set_tid_config, #ifdef CONFIG_PM .suspend = rtw89_ops_suspend, diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 31f0a5225b11..30943462640f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -773,7 +773,7 @@ static int dmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) return ret; } - ret = rtw89_mac_preload_init(rtwdev, RTW89_MAC_0, rtwdev->mac.qta_mode); + ret = rtw89_mac_preload_init(rtwdev, mac_idx, rtwdev->mac.qta_mode); if (ret) { rtw89_err(rtwdev, "[ERR]preload init %d\n", ret); return ret; @@ -2091,13 +2091,13 @@ static int rtw89_mac_init_bfee_be(struct rtw89_dev *rtwdev, u8 mac_idx) } static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u8 nc = 1, nr = 3, ng = 0, cb = 1, cs = 1, ldpc_en = 1, stbc_en = 1; - u8 mac_idx = rtwvif->mac_idx; - u8 port_sel = rtwvif->port; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; + u8 port_sel = rtwvif_link->port; u8 sound_dim = 3, t; u8 *phy_cap; u32 reg; @@ -2108,7 +2108,10 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, if (ret) return ret; - phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; if ((phy_cap[3] & IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER) || (phy_cap[4] & IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER)) { @@ -2119,11 +2122,11 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, sound_dim = min(sound_dim, t); } - if ((sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { - ldpc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); - stbc_en &= !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); - t = u32_get_bits(sta->deflink.vht_cap.cap, + if ((link_sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE) || + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) { + ldpc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC); + stbc_en &= !!(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK); + t = u32_get_bits(link_sta->vht_cap.cap, IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK); sound_dim = min(sound_dim, t); } @@ -2131,6 +2134,8 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, nc = min(nc, sound_dim); nr = min(nr, sound_dim); + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); @@ -2155,12 +2160,12 @@ static int rtw89_mac_set_csi_para_reg_be(struct rtw89_dev *rtwdev, } static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; u32 rrsc = BIT(RTW89_MAC_BF_RRSC_6M) | BIT(RTW89_MAC_BF_RRSC_24M); - u8 mac_idx = rtwvif->mac_idx; + struct ieee80211_link_sta *link_sta; + u8 mac_idx = rtwvif_link->mac_idx; int ret; u32 reg; @@ -2168,22 +2173,28 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, if (ret) return ret; - if (sta->deflink.he_cap.has_he) { + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->he_cap.has_he) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HE_MSC0) | BIT(RTW89_MAC_BF_RRSC_HE_MSC3) | BIT(RTW89_MAC_BF_RRSC_HE_MSC5)); } - if (sta->deflink.vht_cap.vht_supported) { + if (link_sta->vht_cap.vht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_VHT_MSC0) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC3) | BIT(RTW89_MAC_BF_RRSC_VHT_MSC5)); } - if (sta->deflink.ht_cap.ht_supported) { + if (link_sta->ht_cap.ht_supported) { rrsc |= (BIT(RTW89_MAC_BF_RRSC_HT_MSC0) | BIT(RTW89_MAC_BF_RRSC_HT_MSC3) | BIT(RTW89_MAC_BF_RRSC_HT_MSC5)); } + rcu_read_unlock(); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_CSI_CTRL_0, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_BFMEE_BFPARAM_SEL); rtw89_write32_clr(rtwdev, reg, B_BE_BFMEE_CSI_FORCE_RETE_EN); @@ -2195,17 +2206,25 @@ static int rtw89_mac_csi_rrsc_be(struct rtw89_dev *rtwdev, } static void rtw89_mac_bf_assoc_be(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct ieee80211_link_sta *link_sta; + bool has_beamformer_cap; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + has_beamformer_cap = rtw89_sta_has_beamformer_cap(link_sta); + + rcu_read_unlock(); - if (rtw89_sta_has_beamformer_cap(sta)) { + if (has_beamformer_cap) { rtw89_debug(rtwdev, RTW89_DBG_BF, "initialize bfee for new association\n"); - rtw89_mac_init_bfee_be(rtwdev, rtwvif->mac_idx); - rtw89_mac_set_csi_para_reg_be(rtwdev, vif, sta); - rtw89_mac_csi_rrsc_be(rtwdev, vif, sta); + rtw89_mac_init_bfee_be(rtwdev, rtwvif_link->mac_idx); + rtw89_mac_set_csi_para_reg_be(rtwdev, rtwvif_link, rtwsta_link); + rtw89_mac_csi_rrsc_be(rtwdev, rtwvif_link, rtwsta_link); } } diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 02afeb3acce4..5ed7eaa18c85 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -2358,13 +2358,15 @@ static int rtw89_pci_deglitch_setting(struct rtw89_dev *rtwdev) return 0; } -static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) +static void rtw89_pci_disable_eq_ax(struct rtw89_dev *rtwdev) { u16 g1_oobs, g2_oobs; u32 backup_aspm; u32 phy_offset; + u16 offset_cal; u16 oobs_val; int ret; + u8 gen; if (rtwdev->chip->chip_id != RTL8852C) return; @@ -2400,6 +2402,28 @@ static void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) rtw89_write16_set(rtwdev, R_RAC_DIRECT_OFFSET_G2 + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + /* offset K */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 : + R_RAC_DIRECT_OFFSET_G2; + + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_G1 + + RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_G1 : + R_RAC_DIRECT_OFFSET_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT, + MANUAL_LVL_MASK, offset_cal); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + OFFSET_CAL_MODE); + } + out: rtw89_write32(rtwdev, R_AX_PCIE_MIX_CFG_V1, backup_aspm); } @@ -3724,19 +3748,16 @@ static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev, pci_free_irq_vectors(pdev); } -static u16 gray_code_to_bin(u16 gray_code, u32 bit_num) +static u16 gray_code_to_bin(u16 gray_code) { - u16 bin = 0, gray_bit; - u32 bit_idx; + u16 binary = gray_code; - for (bit_idx = 0; bit_idx < bit_num; bit_idx++) { - gray_bit = (gray_code >> bit_idx) & 0x1; - if (bit_num - bit_idx > 1) - gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1; - bin |= (gray_bit << bit_idx); + while (gray_code) { + gray_code >>= 1; + binary ^= gray_code; } - return bin; + return binary; } static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev) @@ -3772,7 +3793,7 @@ static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev) val16 = rtw89_read16_mask(rtwdev, phy_offset + RAC_ANA1F * RAC_MULT, FILTER_OUT_EQ_MASK); - val16 = gray_code_to_bin(val16, hweight16(val16)); + val16 = gray_code_to_bin(val16); filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 * RAC_MULT); filter_out_val &= ~REG_FILTER_OUT_MASK; @@ -4188,6 +4209,17 @@ static void rtw89_pci_l2_hci_ldo(struct rtw89_dev *rtwdev) RTW89_PCIE_BIT_CFG_RST_MSTATE); } +void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume) +{ + if (resume) + rtw89_pci_cfg_dac(rtwdev); + + rtw89_pci_disable_eq(rtwdev); + rtw89_pci_filter_out(rtwdev); + rtw89_pci_link_cfg(rtwdev); + rtw89_pci_l1ss_cfg(rtwdev); +} + static int __maybe_unused rtw89_pci_resume(struct device *dev) { struct ieee80211_hw *hw = dev_get_drvdata(dev); @@ -4209,11 +4241,8 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev) B_AX_SEL_REQ_ENTR_L1); } rtw89_pci_l2_hci_ldo(rtwdev); - rtw89_pci_disable_eq(rtwdev); - rtw89_pci_cfg_dac(rtwdev); - rtw89_pci_filter_out(rtwdev); - rtw89_pci_link_cfg(rtwdev); - rtw89_pci_l1ss_cfg(rtwdev); + + rtw89_pci_basic_cfg(rtwdev, true); return 0; } @@ -4246,6 +4275,8 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = { .aspm_set = rtw89_pci_aspm_set_ax, .clkreq_set = rtw89_pci_clkreq_set_ax, .l1ss_set = rtw89_pci_l1ss_set_ax, + + .disable_eq = rtw89_pci_disable_eq_ax, }; EXPORT_SYMBOL(rtw89_pci_gen_ax); @@ -4345,10 +4376,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_clear_resource; } - rtw89_pci_disable_eq(rtwdev); - rtw89_pci_filter_out(rtwdev); - rtw89_pci_link_cfg(rtwdev); - rtw89_pci_l1ss_cfg(rtwdev); + rtw89_pci_basic_cfg(rtwdev, false); ret = rtw89_core_napi_init(rtwdev); if (ret) { diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 48c3ab735db2..796f6cd3c965 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -18,11 +18,16 @@ #define BAC_OOBS_SEL BIT(4) #define RAC_ANA0A 0x0A #define B_BAC_EQ_SEL BIT(5) +#define RAC_ANA0B 0x0B +#define MANUAL_LVL_MASK GENMASK(8, 5) #define RAC_ANA0C 0x0C #define B_PCIE_BIT_PSAVE BIT(15) #define RAC_ANA0D 0x0D +#define OFFSET_CAL_MODE BIT(13) #define BAC_RX_TEST_EN BIT(6) #define RAC_ANA10 0x10 +#define ADDR_SEL_MASK GENMASK(9, 4) +#define ADDR_SEL_VAL 0x3C #define ADDR_SEL_PINOUT_DIS_VAL 0x3C4 #define B_PCIE_BIT_PINOUT_DIS BIT(3) #define RAC_REG_REV2 0x1B @@ -38,6 +43,7 @@ #define RAC_ANA1E_G2_VAL 0x6EEA #define RAC_ANA1F 0x1F #define OOBS_LEVEL_MASK GENMASK(12, 8) +#define OFFSET_CAL_MASK GENMASK(7, 4) #define RAC_ANA24 0x24 #define B_AX_DEGLITCH GENMASK(11, 8) #define RAC_ANA26 0x26 @@ -134,6 +140,11 @@ #define REG_FILTER_OUT_MASK GENMASK(6, 2) #define RAC_MULT 2 +#define R_RAC_DIRECT_OFFSET_BE_LANE0_G1 0x3800 +#define R_RAC_DIRECT_OFFSET_BE_LANE1_G1 0x3880 +#define R_RAC_DIRECT_OFFSET_BE_LANE0_G2 0x3900 +#define R_RAC_DIRECT_OFFSET_BE_LANE1_G2 0x3980 + #define RTW89_PCI_WR_RETRY_CNT 20 /* Interrupts */ @@ -299,6 +310,7 @@ #define B_BE_L1SS_TIMEOUT_CTRL BIT(18) #define B_BE_ASPM_CTRL_L1 BIT(17) #define B_BE_ASPM_CTRL_L0 BIT(16) +#define B_BE_RTK_ASPM_CTRL_MASK GENMASK(17, 16) #define B_BE_XFER_PENDING_FW BIT(11) #define B_BE_XFER_PENDING BIT(10) #define B_BE_REQ_EXIT_L1 BIT(9) @@ -1276,6 +1288,8 @@ struct rtw89_pci_gen_def { void (*aspm_set)(struct rtw89_dev *rtwdev, bool enable); void (*clkreq_set)(struct rtw89_dev *rtwdev, bool enable); void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable); + + void (*disable_eq)(struct rtw89_dev *rtwdev); }; struct rtw89_pci_info { @@ -1600,6 +1614,7 @@ struct pci_device_id; int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); void rtw89_pci_remove(struct pci_dev *pdev); +void rtw89_pci_basic_cfg(struct rtw89_dev *rtwdev, bool resume); void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev); int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en); int rtw89_pci_ltr_set_v1(struct rtw89_dev *rtwdev, bool en); @@ -1766,4 +1781,13 @@ static inline int rtw89_pci_poll_txdma_ch_idle(struct rtw89_dev *rtwdev) return gen_def->poll_txdma_ch_idle(rtwdev); } + +static inline void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev) +{ + const struct rtw89_pci_info *info = rtwdev->pci_info; + const struct rtw89_pci_gen_def *gen_def = info->gen_def; + + gen_def->disable_eq(rtwdev); +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c index 7cc328222965..34154506f5d4 100644 --- a/drivers/net/wireless/realtek/rtw89/pci_be.c +++ b/drivers/net/wireless/realtek/rtw89/pci_be.c @@ -550,6 +550,79 @@ static int rtw89_pci_lv1rst_start_dma_be(struct rtw89_dev *rtwdev) return 0; } +static void rtw89_pci_disable_eq_be(struct rtw89_dev *rtwdev) +{ + u32 backup_aspm, phy_offset; + u16 oobs_val, offset_cal; + u16 g1_oobs, g2_oobs; + u8 gen; + + if (rtwdev->chip->chip_id != RTL8922A) + return; + + g1_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + g2_oobs = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G2 + + RAC_ANA09 * RAC_MULT, BAC_OOBS_SEL); + if (g1_oobs && g2_oobs) + return; + + backup_aspm = rtw89_read32(rtwdev, R_BE_PCIE_MIX_CFG); + rtw89_write32_clr(rtwdev, R_BE_PCIE_MIX_CFG, B_BE_RTK_ASPM_CTRL_MASK); + + /* offset K */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + offset_cal = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA1F * RAC_MULT, OFFSET_CAL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA0B * RAC_MULT, + MANUAL_LVL_MASK, offset_cal); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + OFFSET_CAL_MODE); + } + + /* OOBS */ + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0D * RAC_MULT, + BAC_RX_TEST_EN); + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, + ADDR_SEL_MASK, ADDR_SEL_VAL); + rtw89_write16_clr(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT, + B_PCIE_BIT_PINOUT_DIS); + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT, + B_PCIE_BIT_RD_SEL); + } + + oobs_val = rtw89_read16_mask(rtwdev, R_RAC_DIRECT_OFFSET_BE_LANE0_G1 + + RAC_ANA1F * RAC_MULT, OOBS_LEVEL_MASK); + + for (gen = 1; gen <= 2; gen++) { + phy_offset = gen == 1 ? R_RAC_DIRECT_OFFSET_BE_LANE0_G1 : + R_RAC_DIRECT_OFFSET_BE_LANE0_G2; + + rtw89_write16_mask(rtwdev, phy_offset + RAC_ANA03 * RAC_MULT, + OOBS_SEN_MASK, oobs_val); + rtw89_write16_set(rtwdev, phy_offset + RAC_ANA09 * RAC_MULT, + BAC_OOBS_SEL); + } + + rtw89_write32(rtwdev, R_BE_PCIE_MIX_CFG, backup_aspm); +} + static int __maybe_unused rtw89_pci_suspend_be(struct device *dev) { struct ieee80211_hw *hw = dev_get_drvdata(dev); @@ -584,6 +657,8 @@ static int __maybe_unused rtw89_pci_resume_be(struct device *dev) rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); rtw89_write32_set(rtwdev, R_BE_REG_PL1_MASK, B_BE_SER_PM_MASTER_IMR); + rtw89_pci_basic_cfg(rtwdev, true); + return 0; } @@ -614,5 +689,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_be = { .aspm_set = rtw89_pci_aspm_set_be, .clkreq_set = rtw89_pci_clkreq_set_be, .l1ss_set = rtw89_pci_l1ss_set_be, + + .disable_eq = rtw89_pci_disable_eq_be, }; EXPORT_SYMBOL(rtw89_pci_gen_be); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index c7165e757842..5a08e3d46bac 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -75,12 +75,12 @@ static u64 get_mcs_ra_mask(u16 mcs_map, u8 highest_mcs, u8 gap) return ra_mask; } -static u64 get_he_ra_mask(struct ieee80211_sta *sta) +static u64 get_he_ra_mask(struct ieee80211_link_sta *link_sta) { - struct ieee80211_sta_he_cap cap = sta->deflink.he_cap; + struct ieee80211_sta_he_cap cap = link_sta->he_cap; u16 mcs_map; - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: if (cap.he_cap_elem.phy_cap_info[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) @@ -118,14 +118,14 @@ static u64 get_eht_mcs_ra_mask(u8 *max_nss, u8 start_mcs, u8 n_nss) return mask; } -static u64 get_eht_ra_mask(struct ieee80211_sta *sta) +static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta) { - struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap; + struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; - u8 *he_phy_cap = sta->deflink.he_cap.he_cap_elem.phy_cap_info; + u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_320: mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._320; /* MCS 9, 11, 13 */ @@ -195,15 +195,16 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak) return ra_mask; } -static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, +static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, const struct rtw89_chan *chan) { - struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta); - struct cfg80211_bitrate_mask *mask = &rtwsta->mask; + struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; enum nl80211_band band; u64 cfg_mask; - if (!rtwsta->use_cfg_mask) + if (!rtwsta_link->use_cfg_mask) return -1; switch (chan->band_type) { @@ -227,17 +228,17 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw return -1; } - if (sta->deflink.he_cap.has_he) { + if (link_sta->he_cap.has_he) { cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[0], RA_MASK_HE_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].he_mcs[1], RA_MASK_HE_2SS_RATES); - } else if (sta->deflink.vht_cap.vht_supported) { + } else if (link_sta->vht_cap.vht_supported) { cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0], RA_MASK_VHT_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1], RA_MASK_VHT_2SS_RATES); - } else if (sta->deflink.ht_cap.ht_supported) { + } else if (link_sta->ht_cap.ht_supported) { cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0], RA_MASK_HT_1SS_RATES); cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1], @@ -261,17 +262,17 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES, RA_MASK_EHT_3SS_RATES, RA_MASK_EHT_4SS_RATES}; static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, - struct rtw89_sta *rtwsta, + struct rtw89_sta_link *rtwsta_link, const struct rtw89_chan *chan, bool *fix_giltf_en, u8 *fix_giltf) { - struct cfg80211_bitrate_mask *mask = &rtwsta->mask; + struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); u8 he_gi = mask->control[nl_band].he_gi; u8 he_ltf = mask->control[nl_band].he_ltf; - if (!rtwsta->use_cfg_mask) + if (!rtwsta_link->use_cfg_mask) return; if (he_ltf == 2 && he_gi == 2) { @@ -295,17 +296,17 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, } static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, - struct ieee80211_sta *sta, bool csi) + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, + bool p2p, bool csi) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; - struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern; - struct rtw89_ra_info *ra = &rtwsta->ra; + struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif_link->rate_pattern; + struct rtw89_ra_info *ra = &rtwsta_link->ra; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); - struct ieee80211_vif *vif = rtwvif_to_vif(rtwsta->rtwvif); + rtwvif_link->chanctx_idx); const u64 *high_rate_masks = rtw89_ra_mask_ht_rates; - u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi); + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi); u64 ra_mask = 0; u64 ra_mask_bak; u8 mode = 0; @@ -320,65 +321,65 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, memset(ra, 0, sizeof(*ra)); /* Set the ra mask from sta's capability */ - if (sta->deflink.eht_cap.has_eht) { + if (link_sta->eht_cap.has_eht) { mode |= RTW89_RA_MODE_EHT; - ra_mask |= get_eht_ra_mask(sta); + ra_mask |= get_eht_ra_mask(link_sta); high_rate_masks = rtw89_ra_mask_eht_rates; - } else if (sta->deflink.he_cap.has_he) { + } else if (link_sta->he_cap.has_he) { mode |= RTW89_RA_MODE_HE; csi_mode = RTW89_RA_RPT_MODE_HE; - ra_mask |= get_he_ra_mask(sta); + ra_mask |= get_he_ra_mask(link_sta); high_rate_masks = rtw89_ra_mask_he_rates; - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[2] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[2] & IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) stbc_en = 1; - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[1] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) ldpc_en = 1; - rtw89_phy_ra_gi_ltf(rtwdev, rtwsta, chan, &fix_giltf_en, &fix_giltf); - } else if (sta->deflink.vht_cap.vht_supported) { - u16 mcs_map = le16_to_cpu(sta->deflink.vht_cap.vht_mcs.rx_mcs_map); + rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf); + } else if (link_sta->vht_cap.vht_supported) { + u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map); mode |= RTW89_RA_MODE_VHT; csi_mode = RTW89_RA_RPT_MODE_VHT; /* MCS9 (non-20MHz), MCS8, MCS7 */ - if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20) + if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) ra_mask |= get_mcs_ra_mask(mcs_map, 8, 1); else ra_mask |= get_mcs_ra_mask(mcs_map, 9, 1); high_rate_masks = rtw89_ra_mask_vht_rates; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK) stbc_en = 1; - if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) + if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC) ldpc_en = 1; - } else if (sta->deflink.ht_cap.ht_supported) { + } else if (link_sta->ht_cap.ht_supported) { mode |= RTW89_RA_MODE_HT; csi_mode = RTW89_RA_RPT_MODE_HT; - ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) | - ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12); + ra_mask |= ((u64)link_sta->ht_cap.mcs.rx_mask[3] << 48) | + ((u64)link_sta->ht_cap.mcs.rx_mask[2] << 36) | + ((u64)link_sta->ht_cap.mcs.rx_mask[1] << 24) | + ((u64)link_sta->ht_cap.mcs.rx_mask[0] << 12); high_rate_masks = rtw89_ra_mask_ht_rates; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) stbc_en = 1; - if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) + if (link_sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING) ldpc_en = 1; } switch (chan->band_type) { case RTW89_BAND_2G: - ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ]; - if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xf) + ra_mask |= link_sta->supp_rates[NL80211_BAND_2GHZ]; + if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xf) mode |= RTW89_RA_MODE_CCK; - if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0xff0) + if (link_sta->supp_rates[NL80211_BAND_2GHZ] & 0xff0) mode |= RTW89_RA_MODE_OFDM; break; case RTW89_BAND_5G: - ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_5GHZ] << 4; + ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_5GHZ] << 4; mode |= RTW89_RA_MODE_OFDM; break; case RTW89_BAND_6G: - ra_mask |= (u64)sta->deflink.supp_rates[NL80211_BAND_6GHZ] << 4; + ra_mask |= (u64)link_sta->supp_rates[NL80211_BAND_6GHZ] << 4; mode |= RTW89_RA_MODE_OFDM; break; default: @@ -405,48 +406,48 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0); ra_mask = rtw89_phy_ra_mask_recover(ra_mask, ra_mask_bak); - ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); + ra_mask &= rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); - switch (sta->deflink.bandwidth) { + switch (link_sta->bandwidth) { case IEEE80211_STA_RX_BW_160: bw_mode = RTW89_CHANNEL_WIDTH_160; - sgi = sta->deflink.vht_cap.vht_supported && - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); + sgi = link_sta->vht_cap.vht_supported && + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160); break; case IEEE80211_STA_RX_BW_80: bw_mode = RTW89_CHANNEL_WIDTH_80; - sgi = sta->deflink.vht_cap.vht_supported && - (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); + sgi = link_sta->vht_cap.vht_supported && + (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80); break; case IEEE80211_STA_RX_BW_40: bw_mode = RTW89_CHANNEL_WIDTH_40; - sgi = sta->deflink.ht_cap.ht_supported && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40); + sgi = link_sta->ht_cap.ht_supported && + (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); break; default: bw_mode = RTW89_CHANNEL_WIDTH_20; - sgi = sta->deflink.ht_cap.ht_supported && - (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20); + sgi = link_sta->ht_cap.ht_supported && + (link_sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); break; } - if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[3] & + if (link_sta->he_cap.he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM) ra->dcm_cap = 1; - if (rate_pattern->enable && !vif->p2p) { - ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta, chan); + if (rate_pattern->enable && !p2p) { + ra_mask = rtw89_phy_ra_mask_cfg(rtwdev, rtwsta_link, link_sta, chan); ra_mask &= rate_pattern->ra_mask; mode = rate_pattern->ra_mode; } ra->bw_cap = bw_mode; - ra->er_cap = rtwsta->er_cap; + ra->er_cap = rtwsta_link->er_cap; ra->mode_ctrl = mode; - ra->macid = rtwsta->mac_id; + ra->macid = rtwsta_link->mac_id; ra->stbc_cap = stbc_en; ra->ldpc_cap = ldpc_en; - ra->ss_num = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1; + ra->ss_num = min(link_sta->rx_nss, rtwdev->hal.tx_nss) - 1; ra->en_sgi = sgi; ra->ra_mask = ra_mask; ra->fix_giltf_en = fix_giltf_en; @@ -458,20 +459,29 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->fixed_csi_rate_en = false; ra->ra_csi_rate_en = true; ra->cr_tbl_sel = false; - ra->band_num = rtwvif->phy_idx; + ra->band_num = rtwvif_link->phy_idx; ra->csi_bw = bw_mode; ra->csi_gi_ltf = RTW89_GILTF_LGI_4XHE32; ra->csi_mcs_ss_idx = 5; ra->csi_mode = csi_mode; } -void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, - u32 changed) +static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + u32 changed) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_ra_info *ra = &rtwsta->ra; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + struct ieee80211_link_sta *link_sta; + + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, + link_sta, vif->p2p, false); - rtw89_phy_ra_sta_update(rtwdev, sta, false); + rcu_read_unlock(); if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) ra->upd_mask = 1; @@ -489,6 +499,20 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta rtw89_fw_h2c_ra(rtwdev, ra, false); } +void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, + u32 changed) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed); + } +} + static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, u16 rate_base, u64 ra_mask, u8 ra_mode, u32 rate_ctrl, u32 ctrl_skip, bool force) @@ -523,15 +547,15 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, [RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \ } -void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif, - const struct cfg80211_bitrate_mask *mask) +static +void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + const struct cfg80211_bitrate_mask *mask) { struct ieee80211_supported_band *sband; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_phy_rate_pattern next_pattern = {0}; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), @@ -600,7 +624,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, if (!next_pattern.enable) goto out; - rtwvif->rate_pattern = next_pattern; + rtwvif_link->rate_pattern = next_pattern; rtw89_debug(rtwdev, RTW89_DBG_RA, "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", next_pattern.rate, @@ -609,10 +633,22 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, return; out: - rtwvif->rate_pattern.enable = false; + rtwvif_link->rate_pattern.enable = false; rtw89_debug(rtwdev, RTW89_DBG_RA, "unset rate pattern\n"); } +void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, + struct ieee80211_vif *vif, + const struct cfg80211_bitrate_mask *mask) +{ + struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + __rtw89_phy_rate_pattern_vif(rtwdev, rtwvif_link, mask); +} + static void rtw89_phy_ra_update_sta_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_dev *rtwdev = (struct rtw89_dev *)data; @@ -627,14 +663,24 @@ void rtw89_phy_ra_update(struct rtw89_dev *rtwdev) rtwdev); } -void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) +void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_ra_info *ra = &rtwsta->ra; - u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR; - bool csi = rtw89_sta_has_beamformer_cap(sta); + struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link; + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_ra_info *ra = &rtwsta_link->ra; + u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR; + struct ieee80211_link_sta *link_sta; + bool csi; - rtw89_phy_ra_sta_update(rtwdev, sta, csi); + rcu_read_lock(); + + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + csi = rtw89_sta_has_beamformer_cap(link_sta); + + rtw89_phy_ra_sta_update(rtwdev, rtwvif_link, rtwsta_link, + link_sta, vif->p2p, csi); + + rcu_read_unlock(); if (rssi > 40) ra->init_rate_lv = 1; @@ -1068,14 +1114,21 @@ static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev) return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1; } -static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev, - enum rtw89_phy_idx phy_idx) +static void __rtw89_phy_bb_reset(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; chip->ops->bb_reset(rtwdev, phy_idx); } +static void rtw89_phy_bb_reset(struct rtw89_dev *rtwdev) +{ + __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_phy_bb_reset(rtwdev, RTW89_PHY_1); +} + static void rtw89_phy_config_bb_reg(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, @@ -1621,13 +1674,15 @@ void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev) if (rtwdev->dbcc_en) rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg, (void *)RTW89_PHY_1); - rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + + rtw89_chip_init_txpwr_unit(rtwdev); bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table; if (bb_gain_table) rtw89_phy_init_reg(rtwdev, bb_gain_table, chip->phy_def->config_bb_gain, NULL); - rtw89_phy_bb_reset(rtwdev, RTW89_PHY_0); + + rtw89_phy_bb_reset(rtwdev); } static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev) @@ -1747,6 +1802,24 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, } EXPORT_SYMBOL(rtw89_phy_write32_idx); +void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx) +{ + if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1) + addr += rtw89_phy0_phy1_offset(rtwdev, addr); + rtw89_phy_write32_set(rtwdev, addr, bits); +} +EXPORT_SYMBOL(rtw89_phy_write32_idx_set); + +void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx) +{ + if (rtwdev->dbcc_en && phy_idx == RTW89_PHY_1) + addr += rtw89_phy0_phy1_offset(rtwdev, addr); + rtw89_phy_write32_clr(rtwdev, addr, bits); +} +EXPORT_SYMBOL(rtw89_phy_write32_idx_clr); + u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, enum rtw89_phy_idx phy_idx) { @@ -2553,14 +2626,14 @@ struct rtw89_phy_iter_ra_data { struct sk_buff *c2h; }; -static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link, + struct ieee80211_link_sta *link_sta, + struct rtw89_phy_iter_ra_data *ra_data) { - struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; struct rtw89_dev *rtwdev = ra_data->rtwdev; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; const struct rtw89_c2h_ra_rpt *c2h = (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; - struct rtw89_ra_report *ra_report = &rtwsta->ra_report; + struct rtw89_ra_report *ra_report = &rtwsta_link->ra_report; const struct rtw89_chip_info *chip = rtwdev->chip; bool format_v1 = chip->chip_gen == RTW89_CHIP_BE; u8 mode, rate, bw, giltf, mac_id; @@ -2570,7 +2643,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) u8 t; mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); - if (mac_id != rtwsta->mac_id) + if (mac_id != rtwsta_link->mac_id) return; rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS); @@ -2661,8 +2734,26 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) | u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); ra_report->might_fallback_legacy = mcs <= 2; - sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); - rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; + link_sta->agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); + rtwsta_link->max_agg_wait = link_sta->agg.max_rc_amsdu_len / 1500 - 1; +} + +static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + struct ieee80211_link_sta *link_sta; + unsigned int link_id; + + rcu_read_lock(); + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false); + __rtw89_phy_c2h_ra_rpt_iter(rtwsta_link, link_sta, ra_data); + } + + rcu_read_unlock(); } static void @@ -2692,9 +2783,85 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, struct rtw89_c2h_rf_txgapk_rpt_log *txgapk; struct rtw89_c2h_rf_rxdck_rpt_log *rxdck; struct rtw89_c2h_rf_dack_rpt_log *dack; + struct rtw89_c2h_rf_tssi_rpt_log *tssi; struct rtw89_c2h_rf_dpk_rpt_log *dpk; + struct rtw89_c2h_rf_iqk_rpt_log *iqk; + int i, j, k; switch (func) { + case RTW89_PHY_C2H_RFK_LOG_FUNC_IQK: + if (len != sizeof(*iqk)) + goto out; + + iqk = content; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_iqk_init = %x\n", iqk->is_iqk_init); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_reload = %x\n", iqk->is_reload); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_nbiqk = %x\n", iqk->is_nbiqk); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->txiqk_en = %x\n", iqk->txiqk_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rxiqk_en = %x\n", iqk->rxiqk_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->lok_en = %x\n", iqk->lok_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_xym_en = %x\n", iqk->iqk_xym_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_sram_en = %x\n", iqk->iqk_sram_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_fft_en = %x\n", iqk->iqk_fft_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_fw_iqk = %x\n", iqk->is_fw_iqk); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->is_iqk_enable = %x\n", iqk->is_iqk_enable); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->iqk_cfir_en = %x\n", iqk->iqk_cfir_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->thermal_rek_en = %x\n", iqk->thermal_rek_en); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->version = %x\n", iqk->version); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->phy = %x\n", iqk->phy); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->fwk_status = %x\n", iqk->fwk_status); + + for (i = 0; i < 2; i++) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] ======== Path %x ========\n", i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_band[%d] = %x\n", + i, iqk->iqk_band[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_ch[%d] = %x\n", + i, iqk->iqk_ch[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n", + i, iqk->iqk_bw[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n", + i, le32_to_cpu(iqk->lok_idac[i])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n", + i, le32_to_cpu(iqk->lok_vbuf[i])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_tx_fail[%d] = %x\n", + i, iqk->iqk_tx_fail[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n", + i, iqk->iqk_rx_fail[i]); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rftxgain[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rftxgain[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->tx_xym[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->tx_xym[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rfrxgain[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rfrxgain[i][j])); + for (j = 0; j < 4; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rx_xym[%d][%d] = %x\n", + i, j, le32_to_cpu(iqk->rx_xym[i][j])); + } + return; case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK: if (len != sizeof(*dpk)) goto out; @@ -2716,8 +2883,23 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack = content; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ver=0x%x 0x%x\n", - dack->fwdack_ver, dack->fwdack_rpt_ver); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]FWDACK SUMMARY!!!!!\n"); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]FWDACK ver = 0x%x, FWDACK rpt_ver = 0x%x, driver rpt_ver = 0x%x\n", + dack->fwdack_ver, dack->fwdack_info_ver, 0x2); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]timeout code = [0x%x 0x%x 0x%x 0x%x 0x%x]\n", + dack->addck_timeout, dack->cdack_timeout, dack->dadck_timeout, + dack->adgaink_timeout, dack->msbk_timeout); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]DACK fail = 0x%x\n", dack->dack_fail); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]S0 WBADCK = [0x%x]\n", dack->wbdck_d[0]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]S1 WBADCK = [0x%x]\n", dack->wbdck_d[1]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DACK]DRCK = [0x%x]\n", dack->rck_d); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK ic = [0x%x, 0x%x]\n", dack->cdack_d[0][0][0], dack->cdack_d[0][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 CDACK qc = [0x%x, 0x%x]\n", @@ -2728,13 +2910,17 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack->cdack_d[1][1][0], dack->cdack_d[1][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK ic = [0x%x, 0x%x]\n", - dack->addck2_d[0][0][0], dack->addck2_d[0][0][1]); + ((u32)dack->addck2_hd[0][0][0] << 8) | dack->addck2_ld[0][0][0], + ((u32)dack->addck2_hd[0][0][1] << 8) | dack->addck2_ld[0][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_DCK qc = [0x%x, 0x%x]\n", - dack->addck2_d[0][1][0], dack->addck2_d[0][1][1]); + ((u32)dack->addck2_hd[0][1][0] << 8) | dack->addck2_ld[0][1][0], + ((u32)dack->addck2_hd[0][1][1] << 8) | dack->addck2_ld[0][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK ic = [0x%x, 0x%x]\n", - dack->addck2_d[1][0][0], dack->addck2_d[1][0][1]); + ((u32)dack->addck2_hd[1][0][0] << 8) | dack->addck2_ld[1][0][0], + ((u32)dack->addck2_hd[1][0][1] << 8) | dack->addck2_ld[1][0][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADC_DCK qc = [0x%x, 0x%x]\n", - dack->addck2_d[1][1][0], dack->addck2_d[1][1][1]); + ((u32)dack->addck2_hd[1][1][0] << 8) | dack->addck2_ld[1][1][0], + ((u32)dack->addck2_hd[1][1][1] << 8) | dack->addck2_ld[1][1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADC_GAINK ic = 0x%x, qc = 0x%x\n", dack->adgaink_d[0][0], dack->adgaink_d[0][1]); @@ -2747,18 +2933,29 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, dack->dadck_d[1][0], dack->dadck_d[1][1]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 biask iqc = 0x%x\n", - dack->biask_d[0][0]); + ((u32)dack->biask_hd[0][0] << 8) | dack->biask_ld[0][0]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 biask iqc = 0x%x\n", - dack->biask_d[1][0]); - - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic: %*ph\n", - (int)sizeof(dack->msbk_d[0][0]), dack->msbk_d[0][0]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc: %*ph\n", - (int)sizeof(dack->msbk_d[0][1]), dack->msbk_d[0][1]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic: %*ph\n", - (int)sizeof(dack->msbk_d[1][0]), dack->msbk_d[1][0]); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc: %*ph\n", - (int)sizeof(dack->msbk_d[1][1]), dack->msbk_d[1][1]); + ((u32)dack->biask_hd[1][0] << 8) | dack->biask_ld[1][0]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[0][0][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[0][1][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[1][0][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc:\n"); + for (i = 0; i < 0x10; i++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", + dack->msbk_d[1][1][i]); return; case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK: if (len != sizeof(*rxdck)) @@ -2770,6 +2967,39 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, rxdck->ver, rxdck->band, rxdck->bw, rxdck->ch, rxdck->timeout); return; + case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI: + if (len != sizeof(*tssi)) + goto out; + + tssi = content; + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 4; k++) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw_h[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power_cw_h[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw_l[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power_cw_l[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power[%d][%d][%d]=%d\n", + i, j, k, tssi->alignment_power[i][j][k]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] alignment_power_cw[%d][%d][%d]=%d\n", + i, j, k, + (tssi->alignment_power_cw_h[i][j][k] << 8) + + tssi->alignment_power_cw_l[i][j][k]); + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] tssi_alimk_state[%d][%d]=%d\n", + i, j, tssi->tssi_alimk_state[i][j]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI] default_txagc_offset[%d]=%d\n", + j, tssi->default_txagc_offset[0][j]); + } + } + return; case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK: if (len != sizeof(*txgapk)) goto out; @@ -3171,13 +3401,13 @@ EXPORT_SYMBOL(rtw89_phy_rfk_dack_and_wait); int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, - unsigned int ms) + bool is_chl_k, unsigned int ms) { int ret; rtw89_phy_rfk_report_prep(rtwdev); - ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan); + ret = rtw89_fw_h2c_rf_rxdck(rtwdev, phy_idx, chan, is_chl_k); if (ret) return ret; @@ -4290,33 +4520,33 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val, cfo->packet_count++; } -void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, - rtwvif->chanctx_idx); + rtwvif_link->chanctx_idx); struct rtw89_phy_ul_tb_info *ul_tb_info = &rtwdev->ul_tb_info; if (!chip->ul_tb_waveform_ctrl) return; - rtwvif->def_tri_idx = + rtwvif_link->def_tri_idx = rtw89_phy_read32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG); if (chip->chip_id == RTL8852B && rtwdev->hal.cv > CHIP_CBV) - rtwvif->dyn_tb_bedge_en = false; + rtwvif_link->dyn_tb_bedge_en = false; else if (chan->band_type >= RTW89_BAND_5G && chan->band_width >= RTW89_CHANNEL_WIDTH_40) - rtwvif->dyn_tb_bedge_en = true; + rtwvif_link->dyn_tb_bedge_en = true; else - rtwvif->dyn_tb_bedge_en = false; + rtwvif_link->dyn_tb_bedge_en = false; rtw89_debug(rtwdev, RTW89_DBG_UL_TB, "[ULTB] def_if_bandedge=%d, def_tri_idx=%d\n", - ul_tb_info->def_if_bandedge, rtwvif->def_tri_idx); + ul_tb_info->def_if_bandedge, rtwvif_link->def_tri_idx); rtw89_debug(rtwdev, RTW89_DBG_UL_TB, "[ULTB] dyn_tb_begde_en=%d, dyn_tb_tri_en=%d\n", - rtwvif->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); + rtwvif_link->dyn_tb_bedge_en, ul_tb_info->dyn_tb_tri_en); } struct rtw89_phy_ul_tb_check_data { @@ -4338,7 +4568,7 @@ struct rtw89_phy_power_diff { }; static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { static const struct rtw89_phy_power_diff table[2] = { {0x0, 0x0, 0x0, 0x0, 0xf4, 0x3, 0x3}, @@ -4350,13 +4580,13 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, if (!rtwdev->chip->ul_tb_pwr_diff) return; - if (rtwvif->pwr_diff_en == rtwvif->pre_pwr_diff_en) { - rtwvif->pwr_diff_en = false; + if (rtwvif_link->pwr_diff_en == rtwvif_link->pre_pwr_diff_en) { + rtwvif_link->pwr_diff_en = false; return; } - rtwvif->pre_pwr_diff_en = rtwvif->pwr_diff_en; - param = &table[rtwvif->pwr_diff_en]; + rtwvif_link->pre_pwr_diff_en = rtwvif_link->pwr_diff_en; + param = &table[rtwvif_link->pwr_diff_en]; rtw89_phy_write32_mask(rtwdev, R_Q_MATRIX_00, B_Q_MATRIX_00_REAL, param->q_00); @@ -4365,32 +4595,32 @@ static void rtw89_phy_ofdma_power_diff(struct rtw89_dev *rtwdev, rtw89_phy_write32_mask(rtwdev, R_CUSTOMIZE_Q_MATRIX, B_CUSTOMIZE_Q_MATRIX_EN, param->q_matrix_en); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_1T, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_NORM_BW160, param->ultb_1t_norm_160); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PWR_UL_TB_2T, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_NORM_BW160, param->ultb_2t_norm_160); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM1, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM1_NORM_1STS, param->com1_norm_1sts); - reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif->mac_idx); + reg = rtw89_mac_reg_by_idx(rtwdev, R_AX_PATH_COM2, rtwvif_link->mac_idx); rtw89_write32_mask(rtwdev, reg, B_AX_PATH_COM2_RESP_1STS_PATH, param->com2_resp_1sts_path); } static void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_phy_ul_tb_check_data *ul_tb_data) { struct rtw89_traffic_stats *stats = &rtwdev->stats; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) return; if (!vif->cfg.assoc) @@ -4403,11 +4633,11 @@ void rtw89_phy_ul_tb_ctrl_check(struct rtw89_dev *rtwdev, ul_tb_data->low_tf_client = true; ul_tb_data->valid = true; - ul_tb_data->def_tri_idx = rtwvif->def_tri_idx; - ul_tb_data->dyn_tb_bedge_en = rtwvif->dyn_tb_bedge_en; + ul_tb_data->def_tri_idx = rtwvif_link->def_tri_idx; + ul_tb_data->dyn_tb_bedge_en = rtwvif_link->dyn_tb_bedge_en; } - rtw89_phy_ofdma_power_diff(rtwdev, rtwvif); + rtw89_phy_ofdma_power_diff(rtwdev, rtwvif_link); } static void rtw89_phy_ul_tb_waveform_ctrl(struct rtw89_dev *rtwdev, @@ -4453,7 +4683,9 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_phy_ul_tb_check_data ul_tb_data = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; if (!chip->ul_tb_waveform_ctrl && !chip->ul_tb_pwr_diff) return; @@ -4462,7 +4694,8 @@ void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif, &ul_tb_data); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_phy_ul_tb_ctrl_check(rtwdev, rtwvif_link, &ul_tb_data); if (!ul_tb_data.valid) return; @@ -4626,30 +4859,42 @@ struct rtw89_phy_iter_rssi_data { bool rssi_changed; }; -static void rtw89_phy_stat_rssi_update_iter(void *data, - struct ieee80211_sta *sta) +static +void __rtw89_phy_stat_rssi_update_iter(struct rtw89_sta_link *rtwsta_link, + struct rtw89_phy_iter_rssi_data *rssi_data) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_phy_iter_rssi_data *rssi_data = - (struct rtw89_phy_iter_rssi_data *)data; struct rtw89_phy_ch_info *ch_info = rssi_data->ch_info; unsigned long rssi_curr; - rssi_curr = ewma_rssi_read(&rtwsta->avg_rssi); + rssi_curr = ewma_rssi_read(&rtwsta_link->avg_rssi); if (rssi_curr < ch_info->rssi_min) { ch_info->rssi_min = rssi_curr; - ch_info->rssi_min_macid = rtwsta->mac_id; + ch_info->rssi_min_macid = rtwsta_link->mac_id; } - if (rtwsta->prev_rssi == 0) { - rtwsta->prev_rssi = rssi_curr; - } else if (abs((int)rtwsta->prev_rssi - (int)rssi_curr) > (3 << RSSI_FACTOR)) { - rtwsta->prev_rssi = rssi_curr; + if (rtwsta_link->prev_rssi == 0) { + rtwsta_link->prev_rssi = rssi_curr; + } else if (abs((int)rtwsta_link->prev_rssi - (int)rssi_curr) > + (3 << RSSI_FACTOR)) { + rtwsta_link->prev_rssi = rssi_curr; rssi_data->rssi_changed = true; } } +static void rtw89_phy_stat_rssi_update_iter(void *data, + struct ieee80211_sta *sta) +{ + struct rtw89_phy_iter_rssi_data *rssi_data = + (struct rtw89_phy_iter_rssi_data *)data; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) + __rtw89_phy_stat_rssi_update_iter(rtwsta_link, rssi_data); +} + static void rtw89_phy_stat_rssi_update(struct rtw89_dev *rtwdev) { struct rtw89_phy_iter_rssi_data rssi_data = {0}; @@ -4676,6 +4921,8 @@ static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev) memset(&phystat->cur_pkt_stat, 0, sizeof(phystat->cur_pkt_stat)); memset(&phystat->last_pkt_stat, 0, sizeof(phystat->last_pkt_stat)); + + ewma_rssi_init(&phystat->bcn_rssi); } void rtw89_phy_stat_track(struct rtw89_dev *rtwdev) @@ -5188,7 +5435,8 @@ static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page) } static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, - enum rtw89_phy_status_bitmap ie_page) + enum rtw89_phy_status_bitmap ie_page, + enum rtw89_phy_idx phy_idx) { u32 addr; @@ -5197,12 +5445,12 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, addr = rtw89_phy_get_ie_bitmap_addr(ie_page); - return rtw89_phy_read32(rtwdev, addr); + return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx); } static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, enum rtw89_phy_status_bitmap ie_page, - u32 val) + u32 val, enum rtw89_phy_idx phy_idx) { const struct rtw89_chip_info *chip = rtwdev->chip; u32 addr; @@ -5214,22 +5462,22 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, val &= B_PHY_STS_BITMAP_MSK_52A; addr = rtw89_phy_get_ie_bitmap_addr(ie_page); - rtw89_phy_write32(rtwdev, addr, val); + rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx); } static void rtw89_physts_enable_ie_bitmap(struct rtw89_dev *rtwdev, enum rtw89_phy_status_bitmap bitmap, enum rtw89_phy_status_ie_type ie, - bool enable) + bool enable, enum rtw89_phy_idx phy_idx) { - u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap); + u32 val = rtw89_physts_get_ie_bitmap(rtwdev, bitmap, phy_idx); if (enable) val |= BIT(ie); else val &= ~BIT(ie); - rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val); + rtw89_physts_set_ie_bitmap(rtwdev, bitmap, val, phy_idx); } static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, @@ -5240,44 +5488,52 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, const struct rtw89_physts_regs *physts = phy->physts; if (enable) { - rtw89_phy_write32_clr(rtwdev, physts->setting_addr, - physts->dis_trigger_fail_mask); - rtw89_phy_write32_clr(rtwdev, physts->setting_addr, - physts->dis_trigger_brk_mask); + rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask, phy_idx); + rtw89_phy_write32_idx_clr(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask, phy_idx); } else { - rtw89_phy_write32_set(rtwdev, physts->setting_addr, - physts->dis_trigger_fail_mask); - rtw89_phy_write32_set(rtwdev, physts->setting_addr, - physts->dis_trigger_brk_mask); + rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr, + physts->dis_trigger_fail_mask, phy_idx); + rtw89_phy_write32_idx_set(rtwdev, physts->setting_addr, + physts->dis_trigger_brk_mask, phy_idx); } } -static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev) +static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) { u8 i; - rtw89_physts_enable_fail_report(rtwdev, false, RTW89_PHY_0); + rtw89_physts_enable_fail_report(rtwdev, false, phy_idx); for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) { if (i >= RTW89_CCK_PKT) rtw89_physts_enable_ie_bitmap(rtwdev, i, RTW89_PHYSTS_IE09_FTR_0, - true); + true, phy_idx); if ((i >= RTW89_CCK_BRK && i <= RTW89_VHT_MU) || (i >= RTW89_RSVD_9 && i <= RTW89_CCK_PKT)) continue; rtw89_physts_enable_ie_bitmap(rtwdev, i, RTW89_PHYSTS_IE24_OFDM_TD_PATH_A, - true); + true, phy_idx); } rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_VHT_PKT, - RTW89_PHYSTS_IE13_DL_MU_DEF, true); + RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx); rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_HE_PKT, - RTW89_PHYSTS_IE13_DL_MU_DEF, true); + RTW89_PHYSTS_IE13_DL_MU_DEF, true, phy_idx); /* force IE01 for channel index, only channel field is valid */ rtw89_physts_enable_ie_bitmap(rtwdev, RTW89_CCK_PKT, - RTW89_PHYSTS_IE01_CMN_OFDM, true); + RTW89_PHYSTS_IE01_CMN_OFDM, true, phy_idx); +} + +static void rtw89_physts_parsing_init(struct rtw89_dev *rtwdev) +{ + __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_0); + if (rtwdev->dbcc_en) + __rtw89_physts_parsing_init(rtwdev, RTW89_PHY_1); } static void rtw89_phy_dig_read_gain_table(struct rtw89_dev *rtwdev, int type) @@ -5753,26 +6009,15 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev) rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false); } -static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) +static void __rtw89_phy_tx_path_div_sta_iter(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) { - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; - struct rtw89_dev *rtwdev = rtwsta->rtwdev; - struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_hal *hal = &rtwdev->hal; - bool *done = data; u8 rssi_a, rssi_b; u32 candidate; - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls) - return; - - if (*done) - return; - - *done = true; - - rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]); - rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]); + rssi_a = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_A]); + rssi_b = ewma_rssi_read(&rtwsta_link->rssi[RF_PATH_B]); if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH) candidate = RF_A; @@ -5785,7 +6030,7 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta return; hal->antenna_tx = candidate; - rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta); + rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta_link); if (hal->antenna_tx == RF_A) { rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12); @@ -5796,6 +6041,37 @@ static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta } } +static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_dev *rtwdev = rtwsta->rtwdev; + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; + bool *done = data; + + if (WARN(ieee80211_vif_is_mld(vif), "MLD mix path_div\n")) + return; + + if (sta->tdls) + return; + + if (*done) + return; + + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) + continue; + + *done = true; + __rtw89_phy_tx_path_div_sta_iter(rtwdev, rtwsta_link); + return; + } +} + void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; @@ -6002,17 +6278,27 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_chip_cfg_txrx_path(rtwdev); } -void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_reg_def *bss_clr_vld = &chip->bss_clr_vld; - enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + struct ieee80211_bss_conf *bss_conf; u8 bss_color; - if (!vif->bss_conf.he_support || !vif->cfg.assoc) + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (!bss_conf->he_support || !vif->cfg.assoc) { + rcu_read_unlock(); return; + } + + bss_color = bss_conf->he_bss_color.color; - bss_color = vif->bss_conf.he_bss_color.color; + rcu_read_unlock(); rtw89_phy_write32_idx(rtwdev, bss_clr_vld->addr, bss_clr_vld->mask, 0x1, phy_idx); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 6dd8ec46939a..c683f4d7d29b 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -815,6 +815,10 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, void rtw89_phy_dm_init(struct rtw89_dev *rtwdev); void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, enum rtw89_phy_idx phy_idx); +void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx); +void rtw89_phy_write32_idx_clr(struct rtw89_dev *rtwdev, u32 addr, u32 bits, + enum rtw89_phy_idx phy_idx); u32 rtw89_phy_read32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, enum rtw89_phy_idx phy_idx); s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev, @@ -892,7 +896,7 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev, phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx); } -void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta); +void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); void rtw89_phy_ra_update(struct rtw89_dev *rtwdev); void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta, u32 changed); @@ -929,7 +933,7 @@ int rtw89_phy_rfk_dack_and_wait(struct rtw89_dev *rtwdev, int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, - unsigned int ms); + bool is_chl_k, unsigned int ms); void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, const struct rtw89_chan *chan, @@ -953,11 +957,12 @@ void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); void rtw89_phy_antdiv_track(struct rtw89_dev *rtwdev); void rtw89_phy_antdiv_work(struct work_struct *work); -void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); void rtw89_phy_tssi_ctrl_set_bandedge_cfg(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx, enum rtw89_tssi_bandedge_cfg bandedge_cfg); -void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +void rtw89_phy_ul_tb_assoc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_phy_ul_tb_ctrl_track(struct rtw89_dev *rtwdev); u8 rtw89_encode_chan_idx(struct rtw89_dev *rtwdev, u8 central_ch, u8 band); void rtw89_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx, diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index 72eda9bbd3ae..37d8f254ae32 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -398,10 +398,9 @@ static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev) } } -static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) +static void __rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) { - enum rtw89_mac_idx mac_idx = RTW89_MAC_0; - rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev); rtw89_phy_bb_wrap_tx_path_by_macid_init(rtwdev); rtw89_phy_bb_wrap_listen_path_en_init(rtwdev); @@ -411,6 +410,13 @@ static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) rtw89_phy_bb_wrap_ul_pwr(rtwdev); } +static void rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev) +{ + __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_0); + if (rtwdev->dbcc_en) + __rtw89_phy_bb_wrap_init_be(rtwdev, RTW89_MAC_1); +} + static void rtw89_phy_ch_info_init_be(struct rtw89_dev *rtwdev) { rtw89_phy_write32_mask(rtwdev, R_CHINFO_SEG, B_CHINFO_SEG_LEN, 0x0); diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index aebd6404f802..c1c12abc2ea9 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -62,9 +62,9 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter) rtw89_mac_power_mode_change(rtwdev, enter); } -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { - if (rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) + if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) return; if (!rtwdev->ps_mode) @@ -85,23 +85,25 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) rtw89_ps_power_mode_change(rtwdev, false); } -static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { - .macid = rtwvif->mac_id, + .macid = rtwvif_link->mac_id, .psmode = RTW89_MAC_AX_PS_MODE_LEGACY, .lastrpwm = RTW89_LAST_RPWM_PS, }; rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL); rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); - rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); + rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link); } -static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_lps_parm lps_param = { - .macid = rtwvif->mac_id, + .macid = rtwvif_link->mac_id, .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE, .lastrpwm = RTW89_LAST_RPWM_ACTIVE, }; @@ -109,7 +111,7 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); rtw89_fw_leave_lps_check(rtwdev, 0); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); - rtw89_chip_digital_pwr_comp(rtwdev, rtwvif->phy_idx); + rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx); } void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) @@ -119,7 +121,7 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); } -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool ps_mode) { lockdep_assert_held(&rtwdev->mutex); @@ -127,23 +129,26 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) return; - __rtw89_enter_lps(rtwdev, rtwvif); + __rtw89_enter_lps(rtwdev, rtwvif_link); if (ps_mode) - __rtw89_enter_ps_mode(rtwdev, rtwvif); + __rtw89_enter_ps_mode(rtwdev, rtwvif_link); } -static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION && - rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) + if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && + rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) return; - __rtw89_leave_lps(rtwdev, rtwvif); + __rtw89_leave_lps(rtwdev, rtwvif_link); } void rtw89_leave_lps(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; lockdep_assert_held(&rtwdev->mutex); @@ -153,12 +158,15 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev) __rtw89_leave_ps_mode(rtwdev); rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_leave_lps_vif(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_leave_lps_vif(rtwdev, rtwvif_link); } void rtw89_enter_ips(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); @@ -166,14 +174,17 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev) return; rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_vif_deinit(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_vif_deinit(rtwdev, rtwvif_link); rtw89_core_stop(rtwdev); } void rtw89_leave_ips(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; int ret; if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) @@ -186,7 +197,8 @@ void rtw89_leave_ips(struct rtw89_dev *rtwdev) rtw89_set_channel(rtwdev); rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_mac_vif_init(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_mac_vif_init(rtwdev, rtwvif_link); clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags); } @@ -197,48 +209,50 @@ void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl) rtw89_leave_lps(rtwdev); } -static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, enum rtw89_p2pps_action act) { if (act == RTW89_P2P_ACT_UPDATE || act == RTW89_P2P_ACT_REMOVE) return; if (act == RTW89_P2P_ACT_INIT) - rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, true); + rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, true); else if (act == RTW89_P2P_ACT_TERMINATE) - rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif, false); + rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false); } static void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; enum rtw89_p2pps_action act; u8 noa_id; - if (rtwvif->last_noa_nr == 0) + if (rtwvif_link->last_noa_nr == 0) return; - for (noa_id = 0; noa_id < rtwvif->last_noa_nr; noa_id++) { - if (noa_id == rtwvif->last_noa_nr - 1) + for (noa_id = 0; noa_id < rtwvif_link->last_noa_nr; noa_id++) { + if (noa_id == rtwvif_link->last_noa_nr - 1) act = RTW89_P2P_ACT_TERMINATE; else act = RTW89_P2P_ACT_REMOVE; - rtw89_tsf32_toggle(rtwdev, rtwvif, act); - rtw89_fw_h2c_p2p_act(rtwdev, vif, NULL, act, noa_id); + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, + NULL, act, noa_id); } } static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, - struct ieee80211_vif *vif) + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct ieee80211_p2p_noa_desc *desc; enum rtw89_p2pps_action act; u8 noa_id; for (noa_id = 0; noa_id < RTW89_P2P_MAX_NOA_NUM; noa_id++) { - desc = &vif->bss_conf.p2p_noa_attr.desc[noa_id]; + desc = &bss_conf->p2p_noa_attr.desc[noa_id]; if (!desc->count || !desc->duration) break; @@ -246,16 +260,19 @@ static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev, act = RTW89_P2P_ACT_INIT; else act = RTW89_P2P_ACT_UPDATE; - rtw89_tsf32_toggle(rtwdev, rtwvif, act); - rtw89_fw_h2c_p2p_act(rtwdev, vif, desc, act, noa_id); + rtw89_tsf32_toggle(rtwdev, rtwvif_link, act); + rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, bss_conf, + desc, act, noa_id); } - rtwvif->last_noa_nr = noa_id; + rtwvif_link->last_noa_nr = noa_id; } -void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) +void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf) { - rtw89_p2p_disable_all_noa(rtwdev, vif); - rtw89_p2p_update_noa(rtwdev, vif); + rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, bss_conf); + rtw89_p2p_update_noa(rtwdev, rtwvif_link, bss_conf); } void rtw89_recalc_lps(struct rtw89_dev *rtwdev) @@ -265,6 +282,12 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev) enum rtw89_entity_mode mode; int count = 0; + /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode() + * to take MLO cases into account before doing the following. + */ + if (rtwdev->support_mlo) + goto disable_lps; + mode = rtw89_get_entity_mode(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) goto disable_lps; @@ -291,9 +314,9 @@ disable_lps: rtwdev->lps_enabled = false; } -void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) +void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; struct rtw89_noa_attr_head *noa_head = &ie->noa_head; @@ -318,10 +341,10 @@ void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif) noa_head->oppps_ctwindow = 0; } -void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, +void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, const struct ieee80211_p2p_noa_desc *desc) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head; struct rtw89_noa_attr_head *noa_head = &ie->noa_head; @@ -338,9 +361,9 @@ void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, ie->noa_desc[setter->noa_count++] = *desc; } -u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data) +u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data) { - struct rtw89_p2p_noa_setter *setter = &rtwvif->p2p_noa; + struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa; struct rtw89_p2p_noa_ie *ie = &setter->ie; void *tail; diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index 54486e4550b6..cdd712966b09 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -5,21 +5,23 @@ #ifndef __RTW89_PS_H_ #define __RTW89_PS_H_ -void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool ps_mode); void rtw89_leave_lps(struct rtw89_dev *rtwdev); void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); -void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev); void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); -void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct ieee80211_bss_conf *bss_conf); void rtw89_recalc_lps(struct rtw89_dev *rtwdev); -void rtw89_p2p_noa_renew(struct rtw89_vif *rtwvif); -void rtw89_p2p_noa_append(struct rtw89_vif *rtwvif, +void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link); +void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link, const struct ieee80211_p2p_noa_desc *desc); -u8 rtw89_p2p_noa_fetch(struct rtw89_vif *rtwvif, void **data); +u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data); static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) { diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index a7720a1f17a7..bb064a086970 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -793,22 +793,26 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) { struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; struct rtw89_reg_6ghz_tpe new = {}; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; bool changed = false; rtw89_for_each_rtwvif(rtwdev, rtwvif) { const struct rtw89_reg_6ghz_tpe *tmp; const struct rtw89_chan *chan; - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - if (chan->band_type != RTW89_BAND_6G) - continue; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; - tmp = &rtwvif->reg_6ghz_tpe; - if (!tmp->valid) - continue; + tmp = &rtwvif_link->reg_6ghz_tpe; + if (!tmp->valid) + continue; - tpe_intersect_constraint(&new, tmp->constraint); + tpe_intersect_constraint(&new, tmp->constraint); + } } if (memcmp(®ulatory->reg_6ghz_tpe, &new, @@ -831,19 +835,24 @@ static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev) } static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool active, + struct rtw89_vif_link *rtwvif_link, bool active, unsigned int *changed) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe; + struct rtw89_reg_6ghz_tpe *tpe = &rtwvif_link->reg_6ghz_tpe; + struct ieee80211_bss_conf *bss_conf; memset(tpe, 0, sizeof(*tpe)); - if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) + if (!active || rtwvif_link->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD) goto bottom; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe); + + rcu_read_unlock(); + if (!tpe->valid) goto bottom; @@ -867,20 +876,24 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) const struct rtw89_regd *regd = regulatory->regd; enum rtw89_reg_6ghz_power sel; const struct rtw89_chan *chan; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; + unsigned int link_id; int count = 0; u8 index; rtw89_for_each_rtwvif(rtwdev, rtwvif) { - chan = rtw89_chan_get(rtwdev, rtwvif->chanctx_idx); - if (chan->band_type != RTW89_BAND_6G) - continue; + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; - if (count != 0 && rtwvif->reg_6ghz_power == sel) - continue; + if (count != 0 && rtwvif_link->reg_6ghz_power == sel) + continue; - sel = rtwvif->reg_6ghz_power; - count++; + sel = rtwvif_link->reg_6ghz_power; + count++; + } } if (count != 1) @@ -908,35 +921,41 @@ static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) } static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, bool active, + struct rtw89_vif_link *rtwvif_link, bool active, unsigned int *changed) { - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf; + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); if (active) { - switch (vif->bss_conf.power_type) { + switch (bss_conf->power_type) { case IEEE80211_REG_VLP_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; break; case IEEE80211_REG_LPI_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; break; case IEEE80211_REG_SP_AP: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; break; default: - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; break; } } else { - rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; } + rcu_read_unlock(); + *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); return 0; } -int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool active) { unsigned int changed = 0; @@ -948,11 +967,11 @@ int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc(). */ - ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed); + ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif_link, active, &changed); if (ret) return ret; - ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed); + ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif_link, active, &changed); if (ret) return ret; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 1679bd408ef3..f9766bf30e71 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -1590,10 +1590,11 @@ static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev) rtw8851b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx); @@ -1608,10 +1609,12 @@ static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8851b_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8851b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index dde96bd63021..42d369d2e916 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -1350,10 +1350,11 @@ static void rtw8852a_rfk_init(struct rtw89_dev *rtwdev) rtw8852a_rx_dck(rtwdev, RTW89_PHY_0, true, RTW89_CHANCTX_0); } -static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx); rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx); @@ -1368,10 +1369,11 @@ static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852a_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); + rtw8852a_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); } static void rtw8852a_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 12be52f76427..364aa21cbd44 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -562,10 +562,11 @@ static void rtw8852b_rfk_init(struct rtw89_dev *rtwdev) rtw8852b_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx); @@ -580,10 +581,12 @@ static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852b_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852b_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8852b_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8852b_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index 7dfdcb5964e1..dab7e71ec6a1 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -535,10 +535,11 @@ static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev) rtw8852bt_rx_dck(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); } -static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx); rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx); @@ -553,10 +554,12 @@ static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852bt_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852bt_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx, rtwvif->chanctx_idx); + rtw8852bt_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx, + rtwvif_link->chanctx_idx); } static void rtw8852bt_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 1c6e89ab0f4b..dbe77abb2c48 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -1846,10 +1846,11 @@ static void rtw8852c_rfk_init(struct rtw89_dev *rtwdev) rtw8852c_rx_dck(rtwdev, RTW89_PHY_0, false); } -static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; rtw8852c_mcc_get_ch_info(rtwdev, phy_idx); rtw8852c_rx_dck(rtwdev, phy_idx, false); @@ -1866,10 +1867,11 @@ static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev, rtw8852c_tssi_scan(rtwdev, phy_idx, chan); } -static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { - rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif->phy_idx); + rtw8852c_wifi_scan_notify(rtwdev, start, rtwvif_link->phy_idx); } static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index 211c051c2967..3281ee9d7523 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -2350,7 +2350,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, if (dgain > 0x5fc || dgain < 0x556) { _dpk_one_shot(rtwdev, phy, path, D_SYNC); - dgain = _dpk_dgain_read(rtwdev); + _dpk_dgain_read(rtwdev); } if (agc_cnt == 0) { diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 63b1ff2f98ed..58c9721ac3ab 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -13,7 +13,7 @@ #include "rtw8922a_rfk.h" #include "util.h" -#define RTW8922A_FW_FORMAT_MAX 1 +#define RTW8922A_FW_FORMAT_MAX 2 #define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw" #define RTW8922A_MODULE_FIRMWARE \ RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin" @@ -1991,14 +1991,23 @@ static void rtw8922a_rfk_init(struct rtw89_dev *rtwdev) memset(rfk_mcc, 0, sizeof(*rfk_mcc)); } +static void __rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan) +{ + rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5); + + rtw89_phy_rfk_dack_and_wait(rtwdev, phy_idx, chan, 58); + rtw89_phy_rfk_rxdck_and_wait(rtwdev, phy_idx, chan, false, 32); +} + static void rtw8922a_rfk_init_late(struct rtw89_dev *rtwdev) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); - rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, RTW89_PHY_0, 5); - - rtw89_phy_rfk_dack_and_wait(rtwdev, RTW89_PHY_0, chan, 58); - rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32); + __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_0, chan); + if (rtwdev->dbcc_en) + __rtw8922a_rfk_init_late(rtwdev, RTW89_PHY_1, chan); } static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) @@ -2020,11 +2029,12 @@ static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) } } -static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { - enum rtw89_chanctx_idx chanctx_idx = rtwvif->chanctx_idx; + enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); - enum rtw89_phy_idx phy_idx = rtwvif->phy_idx; + enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx); u32 tx_en; @@ -2035,9 +2045,9 @@ static void rtw8922a_rfk_channel(struct rtw89_dev *rtwdev, struct rtw89_vif *rtw rtw89_phy_rfk_pre_ntfy_and_wait(rtwdev, phy_idx, 5); rtw89_phy_rfk_txgapk_and_wait(rtwdev, phy_idx, chan, 54); rtw89_phy_rfk_iqk_and_wait(rtwdev, phy_idx, chan, 84); - rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 6); + rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_NORMAL, 20); rtw89_phy_rfk_dpk_and_wait(rtwdev, phy_idx, chan, 34); - rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, 32); + rtw89_phy_rfk_rxdck_and_wait(rtwdev, RTW89_PHY_0, chan, true, 32); rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_CHLK, BTC_WRFK_STOP); @@ -2050,7 +2060,8 @@ static void rtw8922a_rfk_band_changed(struct rtw89_dev *rtwdev, rtw89_phy_rfk_tssi_and_wait(rtwdev, phy_idx, chan, RTW89_TSSI_SCAN, 6); } -static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, +static void rtw8922a_rfk_scan(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, bool start) { } diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 5fc2faa9ba5a..7b203bb7f151 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -300,37 +300,54 @@ static void drv_resume_rx(struct rtw89_ser *ser) static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { - rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); - rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; - rtwvif->trigger = false; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + rtwvif->tdls_peer = 0; + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif_link->port); + rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK; + rtwvif_link->trigger = false; + } } static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) { struct rtw89_vif *target_rtwvif = (struct rtw89_vif *)data; - struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); struct rtw89_vif *rtwvif = rtwsta->rtwvif; struct rtw89_dev *rtwdev = rtwvif->rtwdev; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_sta_link *rtwsta_link; + unsigned int link_id; if (rtwvif != target_rtwvif) return; - if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) - rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam); - if (sta->tdls) - rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam); + rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) { + rtwvif_link = rtwsta_link->rtwvif_link; - INIT_LIST_HEAD(&rtwsta->ba_cam_list); + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE || sta->tdls) + rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta_link->addr_cam); + if (sta->tdls) + rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta_link->bssid_cam); + + INIT_LIST_HEAD(&rtwsta_link->ba_cam_list); + } } static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + ieee80211_iterate_stations_atomic(rtwdev->hw, ser_sta_deinit_cam_iter, rtwvif); - rtw89_cam_deinit(rtwdev, rtwvif); + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) + rtw89_cam_deinit(rtwdev, rtwvif_link); bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM); } diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 86e24e07780d..3e81fd974ec1 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -421,7 +421,8 @@ static void rtw89_wow_construct_key_info(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_key_info *key_info = &rtw_wow->key_info; - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); bool err = false; rcu_read_lock(); @@ -596,7 +597,8 @@ static int rtw89_wow_get_aoac_rpt(struct rtw89_dev *rtwdev, bool rx_ready) static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, u32 cipher, u8 keyidx, u8 *gtk) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); const struct rtw89_cipher_info *cipher_info; struct ieee80211_key_conf *rekey_conf; struct ieee80211_key_conf *key; @@ -632,11 +634,13 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev, static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct rtw89_set_key_info_iter_data data = {.error = false, .rx_ready = rx_ready}; + struct ieee80211_bss_conf *bss_conf; struct ieee80211_key_conf *key; rcu_read_lock(); @@ -669,9 +673,15 @@ static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) return; rtw89_rx_pn_set_pmf(rtwdev, key, aoac_rpt->igtk_ipn); - ieee80211_gtk_rekey_notify(wow_vif, wow_vif->bss_conf.bssid, + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + ieee80211_gtk_rekey_notify(wow_vif, bss_conf->bssid, aoac_rpt->eapol_key_replay_count, - GFP_KERNEL); + GFP_ATOMIC); + + rcu_read_unlock(); } static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) @@ -681,27 +691,24 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev) static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - __rtw89_enter_ps_mode(rtwdev, rtwvif); + __rtw89_enter_ps_mode(rtwdev, rtwvif_link); } static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) - rtw89_enter_lps(rtwdev, rtwvif, false); + rtw89_enter_lps(rtwdev, rtwvif_link, false); else if (rtw89_wow_no_link(rtwdev)) - rtw89_fw_h2c_fwips(rtwdev, rtwvif, true); + rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true); } static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; if (rtw89_wow_mgd_linked(rtwdev)) { rtw89_leave_lps(rtwdev); @@ -709,7 +716,7 @@ static void rtw89_wow_leave_ps(struct rtw89_dev *rtwdev, bool enable_wow) if (enable_wow) rtw89_leave_ips(rtwdev); else - rtw89_fw_h2c_fwips(rtwdev, rtwvif, false); + rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, false); } } @@ -734,6 +741,8 @@ static void rtw89_wow_set_rx_filter(struct rtw89_dev *rtwdev, bool enable) static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) { + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct cfg80211_wowlan_nd_info nd_info; @@ -780,35 +789,34 @@ static void rtw89_wow_show_wakeup_reason(struct rtw89_dev *rtwdev) break; default: rtw89_warn(rtwdev, "Unknown wakeup reason %x\n", reason); - ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, NULL, - GFP_KERNEL); + ieee80211_report_wowlan_wakeup(wow_vif, NULL, GFP_KERNEL); return; } - ieee80211_report_wowlan_wakeup(rtwdev->wow.wow_vif, &wakeup, - GFP_KERNEL); + ieee80211_report_wowlan_wakeup(wow_vif, &wakeup, GFP_KERNEL); } -static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) +static void rtw89_wow_vif_iter(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); /* Current WoWLAN function support setting of only vif in * infra mode or no link mode. When one suitable vif is found, * stop the iteration. */ - if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION) + if (rtw_wow->rtwvif_link || vif->type != NL80211_IFTYPE_STATION) return; - switch (rtwvif->net_type) { + switch (rtwvif_link->net_type) { case RTW89_NET_TYPE_INFRA: if (rtw_wow_has_mgd_features(rtwdev)) - rtw_wow->wow_vif = vif; + rtw_wow->rtwvif_link = rtwvif_link; break; case RTW89_NET_TYPE_NO_LINK: if (rtw_wow->pno_inited) - rtw_wow->wow_vif = vif; + rtw_wow->rtwvif_link = rtwvif_link; break; default: break; @@ -865,7 +873,7 @@ static u16 rtw89_calc_crc(u8 *pdata, int length) return ~crc; } -static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, +static int rtw89_wow_pattern_get_type(struct rtw89_vif_link *rtwvif_link, struct rtw89_wow_cam_info *rtw_pattern, const u8 *pattern, u8 da_mask) { @@ -885,7 +893,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, rtw_pattern->bc = true; else if (is_multicast_ether_addr(da)) rtw_pattern->mc = true; - else if (ether_addr_equal(da, rtwvif->mac_addr) && + else if (ether_addr_equal(da, rtwvif_link->mac_addr) && da_mask == GENMASK(5, 0)) rtw_pattern->uc = true; else if (!da_mask) /*da_mask == 0 mean wildcard*/ @@ -897,7 +905,7 @@ static int rtw89_wow_pattern_get_type(struct rtw89_vif *rtwvif, } static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, const struct cfg80211_pkt_pattern *pkt_pattern, struct rtw89_wow_cam_info *rtw_pattern) { @@ -916,7 +924,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, mask_len = DIV_ROUND_UP(len, 8); memset(rtw_pattern, 0, sizeof(*rtw_pattern)); - ret = rtw89_wow_pattern_get_type(rtwvif, rtw_pattern, pattern, + ret = rtw89_wow_pattern_get_type(rtwvif_link, rtw_pattern, pattern, mask[0] & GENMASK(5, 0)); if (ret) return ret; @@ -970,7 +978,7 @@ static int rtw89_wow_pattern_generate(struct rtw89_dev *rtwdev, } static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif, + struct rtw89_vif_link *rtwvif_link, struct cfg80211_wowlan *wowlan) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; @@ -983,7 +991,7 @@ static int rtw89_wow_parse_patterns(struct rtw89_dev *rtwdev, for (i = 0; i < wowlan->n_patterns; i++) { rtw_pattern = &rtw_wow->patterns[i]; - ret = rtw89_wow_pattern_generate(rtwdev, rtwvif, + ret = rtw89_wow_pattern_generate(rtwdev, rtwvif_link, &wowlan->patterns[i], rtw_pattern); if (ret) { @@ -1040,7 +1048,7 @@ static void rtw89_wow_clear_wakeups(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - rtw_wow->wow_vif = NULL; + rtw_wow->rtwvif_link = NULL; rtw89_core_release_all_bits_map(rtw_wow->flags, RTW89_WOW_FLAG_NUM); rtw_wow->pattern_cnt = 0; rtw_wow->pno_inited = false; @@ -1066,6 +1074,7 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *rtwvif; if (wowlan->disconnect) @@ -1078,36 +1087,40 @@ static int rtw89_wow_set_wakeups(struct rtw89_dev *rtwdev, if (wowlan->nd_config) rtw89_wow_init_pno(rtwdev, wowlan->nd_config); - rtw89_for_each_rtwvif(rtwdev, rtwvif) - rtw89_wow_vif_iter(rtwdev, rtwvif); + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + /* use the link on HW-0 to do wow flow */ + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + if (!rtwvif_link) + continue; + + rtw89_wow_vif_iter(rtwdev, rtwvif_link); + } - if (!rtw_wow->wow_vif) + rtwvif_link = rtw_wow->rtwvif_link; + if (!rtwvif_link) return -EPERM; - rtwvif = (struct rtw89_vif *)rtw_wow->wow_vif->drv_priv; - return rtw89_wow_parse_patterns(rtwdev, rtwvif, wowlan); + return rtw89_wow_parse_patterns(rtwdev, rtwvif_link, wowlan); } static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) { - struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int ret; - ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "failed to config pno\n"); return ret; } - ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); return ret; } - ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow global\n"); return ret; @@ -1119,34 +1132,39 @@ static int rtw89_wow_cfg_wake_pno(struct rtw89_dev *rtwdev, bool wow) static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); struct ieee80211_sta *wow_sta; - struct rtw89_sta *rtwsta = NULL; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_sta *rtwsta; int ret; - wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); - if (wow_sta) - rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; + wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); + if (wow_sta) { + rtwsta = sta_to_rtwsta(wow_sta); + rtwsta_link = rtwsta->links[rtwvif_link->link_id]; + if (!rtwsta_link) + return -ENOLINK; + } if (wow) { if (rtw_wow->pattern_cnt) - rtwvif->wowlan_pattern = true; + rtwvif_link->wowlan_pattern = true; if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags)) - rtwvif->wowlan_magic = true; + rtwvif_link->wowlan_magic = true; } else { - rtwvif->wowlan_pattern = false; - rtwvif->wowlan_magic = false; + rtwvif_link->wowlan_pattern = false; + rtwvif_link->wowlan_magic = false; } - ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_wakeup_ctrl(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow wakeup ctrl\n"); return ret; } if (wow) { - ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif, rtwsta); + ret = rtw89_chip_h2c_dctl_sec_cam(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_err(rtwdev, "failed to update dctl cam sec entry: %d\n", ret); @@ -1154,13 +1172,13 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) } } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } - ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif, wow); + ret = rtw89_fw_h2c_wow_global(rtwdev, rtwvif_link, wow); if (ret) { rtw89_err(rtwdev, "failed to fw wow global\n"); return ret; @@ -1190,25 +1208,30 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) enum rtw89_fw_type fw_type = wow ? RTW89_FW_WOWLAN : RTW89_FW_NORMAL; enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; + struct ieee80211_vif *wow_vif = rtwvif_link_to_vif(rtwvif_link); enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; const struct rtw89_chip_info *chip = rtwdev->chip; bool include_bb = !!chip->bbmcu_nr; bool disable_intr_for_dlfw = false; struct ieee80211_sta *wow_sta; - struct rtw89_sta *rtwsta = NULL; + struct rtw89_sta_link *rtwsta_link = NULL; + struct rtw89_sta *rtwsta; bool is_conn = true; int ret; if (chip_id == RTL8852C || chip_id == RTL8922A) disable_intr_for_dlfw = true; - wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid); - if (wow_sta) - rtwsta = (struct rtw89_sta *)wow_sta->drv_priv; - else + wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); + if (wow_sta) { + rtwsta = sta_to_rtwsta(wow_sta); + rtwsta_link = rtwsta->links[rtwvif_link->link_id]; + if (!rtwsta_link) + return -ENOLINK; + } else { is_conn = false; + } if (disable_intr_for_dlfw) rtw89_hci_disable_intr(rtwdev); @@ -1224,14 +1247,14 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) rtw89_phy_init_rf_reg(rtwdev, true); - ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, + ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, rtwsta_link, RTW89_ROLE_FW_RESTORE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c role maintain\n"); return ret; } - ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, wow_vif, wow_sta); + ret = rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, rtwsta_link); if (ret) { rtw89_warn(rtwdev, "failed to send h2c assoc cmac tbl\n"); return ret; @@ -1240,27 +1263,27 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) if (!is_conn) rtw89_cam_reset_keys(rtwdev); - ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif, rtwsta, !is_conn); + ret = rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, rtwsta_link, !is_conn); if (ret) { rtw89_warn(rtwdev, "failed to send h2c join info\n"); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif, rtwsta, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; } if (is_conn) { - ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif, rtwsta->mac_id); + ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); if (ret) { rtw89_warn(rtwdev, "failed to send h2c general packet\n"); return ret; } - rtw89_phy_ra_assoc(rtwdev, wow_sta); - rtw89_phy_set_bss_color(rtwdev, wow_vif); - rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, wow_vif); + rtw89_phy_ra_assoc(rtwdev, rtwsta_link); + rtw89_phy_set_bss_color(rtwdev, rtwvif_link); + rtw89_chip_cfg_txpwr_ul_tb_offset(rtwdev, rtwvif_link); } if (chip_gen == RTW89_CHIP_BE) @@ -1363,21 +1386,20 @@ static int rtw89_wow_disable_trx_pre(struct rtw89_dev *rtwdev) static int rtw89_wow_disable_trx_post(struct rtw89_dev *rtwdev) { - struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *vif = rtw_wow->wow_vif; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int ret; ret = rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); if (ret) rtw89_err(rtwdev, "cfg ppdu status\n"); - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); return ret; } static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct list_head *pkt_list = &rtw_wow->pno_pkt_list; @@ -1391,7 +1413,7 @@ static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, } static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif *rtwvif) + struct rtw89_vif_link *rtwvif_link) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; @@ -1401,7 +1423,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, int ret; for (i = 0; i < num; i++) { - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif->mac_addr, + skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, nd_config->match_sets[i].ssid.ssid, nd_config->match_sets[i].ssid.ssid_len, nd_config->ie_len); @@ -1413,7 +1435,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { kfree_skb(skb); - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); return -ENOMEM; } @@ -1421,7 +1443,7 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, if (ret) { kfree_skb(skb); kfree(info); - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); return ret; } @@ -1436,20 +1458,19 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; int interval = rtw_wow->nd_config->scan_plans[0].interval; struct rtw89_scan_option opt = {}; int ret; if (enable) { - ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif); + ret = rtw89_pno_scan_update_probe_req(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update probe request failed\n"); return ret; } - ret = mac->add_chan_list_pno(rtwdev, rtwvif); + ret = mac->add_chan_list_pno(rtwdev, rtwvif_link); if (ret) { rtw89_err(rtwdev, "Update channel list failed\n"); return ret; @@ -1471,7 +1492,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) opt.opch_end = RTW89_CHAN_INVALID; } - mac->scan_offload(rtwdev, &opt, rtwvif, true); + mac->scan_offload(rtwdev, &opt, rtwvif_link, true); return 0; } @@ -1479,8 +1500,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; int ret; if (rtw89_wow_no_link(rtwdev)) { @@ -1499,25 +1519,25 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) rtw89_wow_pattern_write(rtwdev); rtw89_wow_construct_key_info(rtwdev); - ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable keep alive\n"); return ret; } - ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable disconnect detect\n"); return ret; } - ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, true); if (ret) { rtw89_err(rtwdev, "wow: failed to enable GTK offload\n"); return ret; } - ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true); + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, true); if (ret) rtw89_warn(rtwdev, "wow: failed to enable arp offload\n"); } @@ -1548,8 +1568,7 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) { struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct ieee80211_vif *wow_vif = rtw_wow->wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtw_wow->rtwvif_link; int ret; if (rtw89_wow_no_link(rtwdev)) { @@ -1559,35 +1578,35 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) return ret; } - ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_cfg_pno(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable pno\n"); return ret; } - rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif); + rtw89_fw_release_pno_pkt_list(rtwdev, rtwvif_link); } else { rtw89_wow_pattern_clear(rtwdev); - ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_keep_alive(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable keep alive\n"); return ret; } - ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_disconnect_detect(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable disconnect detect\n"); return ret; } - ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_wow_gtk_ofld(rtwdev, rtwvif_link, false); if (ret) { rtw89_err(rtwdev, "wow: failed to disable GTK offload\n"); return ret; } - ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false); + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif_link, false); if (ret) rtw89_warn(rtwdev, "wow: failed to disable arp offload\n"); diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h index 3fbc2b87c058..f91991e8f2e3 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.h +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -97,18 +97,16 @@ static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) #ifdef CONFIG_PM static inline bool rtw89_wow_mgd_linked(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - return rtwvif->net_type == RTW89_NET_TYPE_INFRA; + return rtwvif_link->net_type == RTW89_NET_TYPE_INFRA; } static inline bool rtw89_wow_no_link(struct rtw89_dev *rtwdev) { - struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif; - struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv; + struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link; - return rtwvif->net_type == RTW89_NET_TYPE_NO_LINK; + return rtwvif_link->net_type == RTW89_NET_TYPE_NO_LINK; } static inline bool rtw_wow_has_mgd_features(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c index 805a3c1bf8fe..259739e53fc1 100644 --- a/drivers/net/wireless/st/cw1200/queue.c +++ b/drivers/net/wireless/st/cw1200/queue.c @@ -411,33 +411,6 @@ int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id) return ret; } -int cw1200_queue_requeue_all(struct cw1200_queue *queue) -{ - struct cw1200_queue_item *item, *tmp; - struct cw1200_queue_stats *stats = queue->stats; - spin_lock_bh(&queue->lock); - - list_for_each_entry_safe_reverse(item, tmp, &queue->pending, head) { - --queue->num_pending; - ++queue->link_map_cache[item->txpriv.link_id]; - - spin_lock_bh(&stats->lock); - ++stats->num_queued; - ++stats->link_map_cache[item->txpriv.link_id]; - spin_unlock_bh(&stats->lock); - - ++item->generation; - item->packet_id = cw1200_queue_mk_packet_id(queue->generation, - queue->queue_id, - item->generation, - item - queue->pool); - list_move(&item->head, &queue->queue); - } - spin_unlock_bh(&queue->lock); - - return 0; -} - int cw1200_queue_remove(struct cw1200_queue *queue, u32 packet_id) { int ret = 0; diff --git a/drivers/net/wireless/st/cw1200/queue.h b/drivers/net/wireless/st/cw1200/queue.h index 96ac69ae97de..d46304b58747 100644 --- a/drivers/net/wireless/st/cw1200/queue.h +++ b/drivers/net/wireless/st/cw1200/queue.h @@ -85,7 +85,6 @@ int cw1200_queue_get(struct cw1200_queue *queue, struct ieee80211_tx_info **tx_info, const struct cw1200_txpriv **txpriv); int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id); -int cw1200_queue_requeue_all(struct cw1200_queue *queue); int cw1200_queue_remove(struct cw1200_queue *queue, u32 packet_id); int cw1200_queue_get_skb(struct cw1200_queue *queue, u32 packet_id, diff --git a/drivers/net/wireless/ti/wl1251/sdio.c b/drivers/net/wireless/ti/wl1251/sdio.c index c705081249d6..b45050243129 100644 --- a/drivers/net/wireless/ti/wl1251/sdio.c +++ b/drivers/net/wireless/ti/wl1251/sdio.c @@ -233,8 +233,8 @@ static int wl1251_sdio_probe(struct sdio_func *func, } if (wl->irq) { - irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); - ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); + ret = request_irq(wl->irq, wl1251_line_irq, IRQF_NO_AUTOEN, + "wl1251", wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); goto disable; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 0c77b8524160..986b07bfa0ee 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5789,9 +5789,10 @@ static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw, static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { + struct ieee80211_sta *sta = link_sta->sta; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update"); @@ -6052,7 +6053,7 @@ static const struct ieee80211_ops wl1271_ops = { .assign_vif_chanctx = wlcore_op_assign_vif_chanctx, .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx, .switch_vif_chanctx = wlcore_op_switch_vif_chanctx, - .sta_rc_update = wlcore_op_sta_rc_update, + .link_sta_rc_update = wlcore_op_sta_rc_update, .sta_statistics = wlcore_op_sta_statistics, .get_expected_throughput = wlcore_op_get_expected_throughput, CFG80211_TESTMODE_CMD(wl1271_tm_cmd) diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 92fb5b8dcdae..a73207bbe5d7 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -323,17 +323,12 @@ static int wl1271_probe(struct sdio_func *func, memset(res, 0x00, sizeof(res)); - res[0].start = irq; - res[0].flags = IORESOURCE_IRQ | - irqd_get_trigger_type(irq_get_irq_data(irq)); - res[0].name = "irq"; - + res[0] = DEFINE_RES_IRQ_NAMED(irq, "irq"); + res[0].flags |= irq_get_trigger_type(irq); if (wakeirq > 0) { - res[1].start = wakeirq; - res[1].flags = IORESOURCE_IRQ | - irqd_get_trigger_type(irq_get_irq_data(wakeirq)); - res[1].name = "wakeirq"; + res[1] = DEFINE_RES_IRQ_NAMED(wakeirq, "wakeirq"); + res[1].flags |= irq_get_trigger_type(wakeirq); num_irqs = 2; } else { num_irqs = 1; diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index f0e528abb1b4..2a36b58f7a15 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -2442,7 +2442,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) if (!data->started || !link_data->beacon_int) { hrtimer_cancel(&link_data->beacon_timer); - } else if (!hrtimer_is_queued(&link_data->beacon_timer)) { + } else if (!hrtimer_active(&link_data->beacon_timer)) { u64 tsf = mac80211_hwsim_get_tsf(hw, NULL); u32 bcn_int = link_data->beacon_int; u64 until_tbtt = bcn_int - do_div(tsf, bcn_int); @@ -2537,7 +2537,7 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, info->enable_beacon, info->beacon_int); vp->bcn_en = info->enable_beacon; if (data->started && - !hrtimer_is_queued(&link_data->beacon_timer) && + !hrtimer_active(&link_data->beacon_timer) && info->enable_beacon) { u64 tsf, until_tbtt; u32 bcn_int; @@ -2594,10 +2594,11 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, static void mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed) { struct mac80211_hwsim_data *data = hw->priv; + struct ieee80211_sta *sta = link_sta->sta; u32 bw = U32_MAX; int link_id; @@ -2607,7 +2608,6 @@ mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw, link_id++) { enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT; struct ieee80211_bss_conf *vif_conf; - struct ieee80211_link_sta *link_sta; link_sta = rcu_dereference(sta->link[link_id]); @@ -2659,7 +2659,7 @@ static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, hwsim_check_magic(vif); hwsim_set_sta_magic(sta); - mac80211_hwsim_sta_rc_update(hw, vif, sta, 0); + mac80211_hwsim_sta_rc_update(hw, vif, &sta->deflink, 0); if (sta->valid_links) { WARN(hweight16(sta->valid_links) > 1, @@ -3961,7 +3961,7 @@ out: .link_info_changed = mac80211_hwsim_link_info_changed, \ .tx_last_beacon = mac80211_hwsim_tx_last_beacon, \ .sta_notify = mac80211_hwsim_sta_notify, \ - .sta_rc_update = mac80211_hwsim_sta_rc_update, \ + .link_sta_rc_update = mac80211_hwsim_sta_rc_update, \ .conf_tx = mac80211_hwsim_conf_tx, \ .get_survey = mac80211_hwsim_get_survey, \ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3fb68d60dfc1..fcdd559a8acf 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -26,8 +26,6 @@ if STAGING source "drivers/staging/olpc_dcon/Kconfig" -source "drivers/staging/rtl8192e/Kconfig" - source "drivers/staging/rtl8723bs/Kconfig" source "drivers/staging/rtl8712/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c977aa13fad4..4a84c4848664 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -3,7 +3,6 @@ obj-y += media/ obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ -obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_RTL8723BS) += rtl8723bs/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_RTS5208) += rts5208/ diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig deleted file mode 100644 index e06c189b4ce4..000000000000 --- a/drivers/staging/rtl8192e/Kconfig +++ /dev/null @@ -1,61 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config RTLLIB - tristate "Support for rtllib wireless devices" - depends on WLAN && m - select LIB80211 - select CRC32 - help - If you have a wireless card that uses rtllib, say - Y. Currently the only card is the rtl8192e. - - If unsure, say N. - - This driver adds support for rtllib wireless cards. - Only the rtl8192e is supported as of now. - -if RTLLIB - -config RTLLIB_CRYPTO_CCMP - tristate "Support for rtllib CCMP crypto" - depends on RTLLIB - select CRYPTO - select CRYPTO_AES - select CRYPTO_CCM - default y - help - CCMP crypto driver for rtllib. - - If you enabled RTLLIB, you want this. - Adds support for the CCM mode Protocol crypto driver for - use in wireless cards (including rtllib cards). - -config RTLLIB_CRYPTO_TKIP - tristate "Support for rtllib TKIP crypto" - depends on RTLLIB - select CRYPTO - select CRYPTO_LIB_ARC4 - select CRYPTO_MICHAEL_MIC - default y - help - TKIP crypto driver for rtllib. - - If you enabled RTLLIB, you want this. - Adds support for the Temporal Key Integrity Protocol for - the IEEE 802.11i standard for use on wireless cards. - -config RTLLIB_CRYPTO_WEP - tristate "Support for rtllib WEP crypto" - select CRYPTO_LIB_ARC4 - depends on RTLLIB - default y - help - WEP crypto driver for rtllib. - - If you enabled RTLLIB, you want this. - Adds support for the (now weak) Wired Equivalent Privacy - (WEP) crypto protocol for wireless cards. - NOTE: This protocol is now considered insecure. - -source "drivers/staging/rtl8192e/rtl8192e/Kconfig" - -endif diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile deleted file mode 100644 index a1492215dab1..000000000000 --- a/drivers/staging/rtl8192e/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -rtllib-objs := \ - rtllib_module.o \ - rtllib_rx.o \ - rtllib_tx.o \ - rtllib_wx.o \ - rtllib_softmac.o \ - rtllib_softmac_wx.o \ - rtl819x_BAProc.o \ - rtl819x_HTProc.o \ - rtl819x_TSProc.o - -obj-$(CONFIG_RTLLIB) += rtllib.o - -obj-$(CONFIG_RTLLIB_CRYPTO_CCMP) += rtllib_crypt_ccmp.o -obj-$(CONFIG_RTLLIB_CRYPTO_TKIP) += rtllib_crypt_tkip.o -obj-$(CONFIG_RTLLIB_CRYPTO_WEP) += rtllib_crypt_wep.o - -obj-$(CONFIG_RTL8192E) += rtl8192e/ diff --git a/drivers/staging/rtl8192e/TODO b/drivers/staging/rtl8192e/TODO deleted file mode 100644 index 7221ae65d63e..000000000000 --- a/drivers/staging/rtl8192e/TODO +++ /dev/null @@ -1,18 +0,0 @@ -To-do list: - -* merge into drivers/net/wireless/realtek/rtlwifi/rtl8192* -* clean up function naming -* Correct the coding style according to Linux guidelines; please read the document - at https://www.kernel.org/doc/html/latest/process/coding-style.html. -* Remove unnecessary debugging/printing macros; for those that are still needed - use the proper kernel API (pr_debug(), dev_dbg(), netdev_dbg()). -* Remove dead code such as unusued functions, variables, fields, etc.. -* Use in-kernel API and remove unnecessary wrappers where possible. -* Fix bugs due to code that sleeps in atomic context. -* Remove the HAL layer and migrate its functionality into the relevant parts of - the driver. -* Switch to use LIB80211. -* Switch to use MAC80211. -* Switch to use CFG80211. -* Improve the error handling of various functions, particularly those that use - existing kernel APIs. diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig deleted file mode 100644 index f8f774a16295..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config RTL8192E - tristate "RealTek RTL8192E Wireless LAN NIC driver" - depends on PCI && WLAN && RTLLIB - depends on m - select CFG80211 - select WIRELESS_EXT - select WEXT_PRIV - select CRYPTO - select FW_LOADER diff --git a/drivers/staging/rtl8192e/rtl8192e/Makefile b/drivers/staging/rtl8192e/rtl8192e/Makefile deleted file mode 100644 index a442d79ea71e..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -r8192e_pci-objs := \ - r8192E_dev.o \ - r8192E_phy.o \ - r8192E_firmware.o \ - r8192E_cmdpkt.o \ - table.o \ - r8190P_rtl8256.o \ - rtl_cam.o \ - rtl_core.o \ - rtl_dm.o \ - rtl_eeprom.o \ - rtl_ethtool.o \ - rtl_pci.o \ - rtl_pm.o \ - rtl_ps.o \ - rtl_wx.o \ - -obj-$(CONFIG_RTL8192E) += r8192e_pci.o diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h deleted file mode 100644 index 552fd9b6e3e5..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h +++ /dev/null @@ -1,266 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef R8190P_DEF_H -#define R8190P_DEF_H - -#include <linux/types.h> -#include "r8192E_phy.h" - -#define MAX_SILENT_RESET_RX_SLOT_NUM 10 - -enum rtl819x_loopback { - RTL819X_NO_LOOPBACK = 0, - RTL819X_MAC_LOOPBACK = 1, - RTL819X_DMA_LOOPBACK = 2, - RTL819X_CCK_LOOPBACK = 3, -}; - -#define DESC90_RATE1M 0x00 -#define DESC90_RATE2M 0x01 -#define DESC90_RATE5_5M 0x02 -#define DESC90_RATE11M 0x03 -#define DESC90_RATE6M 0x04 -#define DESC90_RATE9M 0x05 -#define DESC90_RATE12M 0x06 -#define DESC90_RATE18M 0x07 -#define DESC90_RATE24M 0x08 -#define DESC90_RATE36M 0x09 -#define DESC90_RATE48M 0x0a -#define DESC90_RATE54M 0x0b -#define DESC90_RATEMCS0 0x00 -#define DESC90_RATEMCS1 0x01 -#define DESC90_RATEMCS2 0x02 -#define DESC90_RATEMCS3 0x03 -#define DESC90_RATEMCS4 0x04 -#define DESC90_RATEMCS5 0x05 -#define DESC90_RATEMCS6 0x06 -#define DESC90_RATEMCS7 0x07 -#define DESC90_RATEMCS8 0x08 -#define DESC90_RATEMCS9 0x09 -#define DESC90_RATEMCS10 0x0a -#define DESC90_RATEMCS11 0x0b -#define DESC90_RATEMCS12 0x0c -#define DESC90_RATEMCS13 0x0d -#define DESC90_RATEMCS14 0x0e -#define DESC90_RATEMCS15 0x0f -#define DESC90_RATEMCS32 0x20 - -#define SHORT_SLOT_TIME 9 -#define NON_SHORT_SLOT_TIME 20 - -#define RX_SMOOTH 20 - -#define QSLT_BK 0x1 -#define QSLT_BE 0x0 -#define QSLT_VI 0x4 -#define QSLT_VO 0x6 -#define QSLT_BEACON 0x10 -#define QSLT_HIGH 0x11 -#define QSLT_MGNT 0x12 -#define QSLT_CMD 0x13 - -#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x007 -#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x0aa -#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x024 -#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x007 -#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x10 -#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4 -#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xd - -#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000 -#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00 -#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08 -#define RSVD_FW_QUEUE_PAGE_VI_SHIFT 0x10 -#define RSVD_FW_QUEUE_PAGE_VO_SHIFT 0x18 -#define RSVD_FW_QUEUE_PAGE_MGNT_SHIFT 0x10 -#define RSVD_FW_QUEUE_PAGE_BCN_SHIFT 0x00 -#define RSVD_FW_QUEUE_PAGE_PUB_SHIFT 0x08 - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -enum version_8190_loopback { - VERSION_8190_BD = 0x3, - VERSION_8190_BE -}; - -#define IC_VersionCut_D 0x3 - -enum rf_optype { - RF_OP_By_SW_3wire = 0, - RF_OP_By_FW, - RF_OP_MAX -}; - -struct bb_reg_definition { - u32 rfintfs; - u32 rfintfo; - u32 rfintfe; - u32 rf3wireOffset; - u32 rfHSSIPara2; - u32 rfLSSIReadBack; - u32 rfLSSIReadBackPi; -}; - -struct tx_fwinfo_8190pci { - u8 TxRate:7; - u8 CtsEnable:1; - u8 RtsRate:7; - u8 RtsEnable:1; - u8 TxHT:1; - u8 Short:1; - u8 TxBandwidth:1; - u8 TxSubCarrier:2; - u8 STBC:2; - u8 AllowAggregation:1; - u8 RtsHT:1; - u8 RtsShort:1; - u8 RtsBandwidth:1; - u8 RtsSubcarrier:2; - u8 RtsSTBC:2; - u8 EnableCPUDur:1; - - u32 RxMF:2; - u32 RxAMD:3; - u32 TxPerPktInfoFeedback:1; - u32 Reserved1:2; - u32 TxAGCOffset:4; - u32 TxAGCSign:1; - u32 RAW_TXD:1; - u32 Retry_Limit:4; - u32 Reserved2:1; - u32 PacketID:13; -}; - -struct phy_sts_ofdm_819xpci { - u8 trsw_gain_X[RF90_PATH_MAX]; - u8 pwdb_all; - u8 cfosho_X[4]; - u8 cfotail_X[4]; - u8 rxevm_X[2]; - u8 rxsnr_X[4]; - u8 pdsnr_X[2]; - u8 csi_current_X[2]; - u8 csi_target_X[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 sgi_en; - u8 rxsc_sgien_exflg; -}; - -struct phy_sts_cck_819xpci { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_Beacon_RSSI_SLID_WIN_MAX 10 - -struct tx_desc { - u16 PktSize; - u8 Offset; - u8 Reserved1:3; - u8 CmdInit:1; - u8 LastSeg:1; - u8 FirstSeg:1; - u8 LINIP:1; - u8 OWN:1; - - u8 TxFWInfoSize; - u8 RATid:3; - u8 DISFB:1; - u8 USERATE:1; - u8 MOREFRAG:1; - u8 NoEnc:1; - u8 PIFS:1; - u8 QueueSelect:5; - u8 NoACM:1; - u8 Resv:2; - u8 SecCAMID:5; - u8 SecDescAssign:1; - u8 SecType:2; - - u16 TxBufferSize; - u8 PktId:7; - u8 Resv1:1; - u8 Reserved2; - - u32 TxBuffAddr; - - u32 NextDescAddress; - - u32 Reserved5; - u32 Reserved6; - u32 Reserved7; -}; - -struct tx_desc_cmd { - u16 PktSize; - u8 Reserved1; - u8 CmdType:3; - u8 CmdInit:1; - u8 LastSeg:1; - u8 FirstSeg:1; - u8 LINIP:1; - u8 OWN:1; - - u16 ElementReport; - u16 Reserved2; - - u16 TxBufferSize; - u16 Reserved3; - - u32 TxBuffAddr; - u32 NextDescAddress; - u32 Reserved4; - u32 Reserved5; - u32 Reserved6; -}; - -struct rx_desc { - u16 Length:14; - u16 CRC32:1; - u16 ICV:1; - u8 rx_drv_info_size; - u8 Shift:2; - u8 PHYStatus:1; - u8 SWDec:1; - u8 LastSeg:1; - u8 FirstSeg:1; - u8 EOR:1; - u8 OWN:1; - - u32 Reserved2; - - u32 Reserved3; - - u32 BufferAddress; -}; - -struct rx_fwinfo { - u16 Reserved1:12; - u16 PartAggr:1; - u16 FirstAGGR:1; - u16 Reserved2:2; - - u8 RxRate:7; - u8 RxHT:1; - - u8 BW:1; - u8 SPLCP:1; - u8 Reserved3:2; - u8 PAM:1; - u8 Mcast:1; - u8 Bcast:1; - u8 Reserved4:1; - - u32 TSFL; -}; - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c deleted file mode 100644 index 7061f1cf4d3a..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_phyreg.h" -#include "r8192E_phy.h" -#include "r8190P_rtl8256.h" - -void rtl92e_set_bandwidth(struct net_device *dev, - enum ht_channel_width bandwidth) -{ - u8 eRFPath; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->card_8192_version != VERSION_8190_BD && - priv->card_8192_version != VERSION_8190_BE) { - netdev_warn(dev, "%s(): Unknown HW version.\n", __func__); - return; - } - - for (eRFPath = 0; eRFPath < priv->num_total_rf_path; eRFPath++) { - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x0b, bMask12Bits, 0x100); - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x2c, bMask12Bits, 0x3d7); - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x0e, bMask12Bits, 0x021); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x0b, bMask12Bits, 0x300); - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x2c, bMask12Bits, 0x3ff); - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, - 0x0e, bMask12Bits, 0x0e1); - break; - default: - netdev_err(dev, "%s(): Unknown bandwidth: %#X\n", - __func__, bandwidth); - break; - } - } -} - -bool rtl92e_config_rf(struct net_device *dev) -{ - u32 u4RegValue = 0; - u8 eRFPath; - bool rtStatus = true; - struct bb_reg_definition *pPhyReg; - struct r8192_priv *priv = rtllib_priv(dev); - u32 RegOffSetToBeCheck = 0x3; - u32 RegValueToBeCheck = 0x7f1; - u32 RF3_Final_Value = 0; - u8 ConstRetryTimes = 5, RetryTimes = 5; - u8 ret = 0; - - priv->num_total_rf_path = RTL819X_TOTAL_RF_PATH; - - for (eRFPath = (enum rf90_radio_path)RF90_PATH_A; - eRFPath < priv->num_total_rf_path; eRFPath++) { - pPhyReg = &priv->phy_reg_def[eRFPath]; - - switch (eRFPath) { - case RF90_PATH_A: - u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs, - bRFSI_RFENV); - break; - case RF90_PATH_B: - u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs, - bRFSI_RFENV << 16); - break; - } - - rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); - - rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); - - rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, - b3WireAddressLength, 0x0); - rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, - b3WireDataLength, 0x0); - - rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, 0x0, - bMask12Bits, 0xbf); - - rtStatus = rtl92e_check_bb_and_rf(dev, HW90_BLOCK_RF, - (enum rf90_radio_path)eRFPath); - if (!rtStatus) { - netdev_err(dev, "%s(): Failed to check RF Path %d.\n", - __func__, eRFPath); - goto fail; - } - - RetryTimes = ConstRetryTimes; - RF3_Final_Value = 0; - while (RF3_Final_Value != RegValueToBeCheck && - RetryTimes != 0) { - ret = rtl92e_config_rf_path(dev, - (enum rf90_radio_path)eRFPath); - RF3_Final_Value = rtl92e_get_rf_reg(dev, - (enum rf90_radio_path)eRFPath, - RegOffSetToBeCheck, - bMask12Bits); - RetryTimes--; - } - - switch (eRFPath) { - case RF90_PATH_A: - rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, bRFSI_RFENV, - u4RegValue); - break; - case RF90_PATH_B: - rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, - bRFSI_RFENV << 16, u4RegValue); - break; - } - - if (ret) { - netdev_err(dev, - "%s(): Failed to initialize RF Path %d.\n", - __func__, eRFPath); - goto fail; - } - } - return true; - -fail: - return false; -} - -void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel) -{ - u32 TxAGC = 0; - struct r8192_priv *priv = rtllib_priv(dev); - - TxAGC = powerlevel; - if (priv->dynamic_tx_low_pwr) { - if (priv->customer_id == RT_CID_819X_NETCORE) - TxAGC = 0x22; - else - TxAGC += priv->cck_pwr_enl; - } - if (TxAGC > 0x24) - TxAGC = 0x24; - rtl92e_set_bb_reg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); -} - -void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 writeVal, powerBase0, powerBase1, writeVal_tmp; - u8 index = 0; - u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; - u8 byte0, byte1, byte2, byte3; - - powerBase0 = powerlevel + priv->legacy_ht_tx_pwr_diff; - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | - (powerBase0 << 8) | powerBase0; - powerBase1 = powerlevel; - powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | - (powerBase1 << 8) | powerBase1; - - for (index = 0; index < 6; index++) { - writeVal = (u32)(priv->mcs_tx_pwr_level_org_offset[index] + - ((index < 2) ? powerBase0 : powerBase1)); - byte0 = writeVal & 0x7f; - byte1 = (writeVal & 0x7f00) >> 8; - byte2 = (writeVal & 0x7f0000) >> 16; - byte3 = (writeVal & 0x7f000000) >> 24; - if (byte0 > 0x24) - byte0 = 0x24; - if (byte1 > 0x24) - byte1 = 0x24; - if (byte2 > 0x24) - byte2 = 0x24; - if (byte3 > 0x24) - byte3 = 0x24; - - if (index == 3) { - writeVal_tmp = (byte3 << 24) | (byte2 << 16) | - (byte1 << 8) | byte0; - priv->pwr_track = writeVal_tmp; - } - - if (priv->dynamic_tx_high_pwr) - writeVal = 0x03030303; - else - writeVal = (byte3 << 24) | (byte2 << 16) | - (byte1 << 8) | byte0; - rtl92e_set_bb_reg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); - } -} diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h deleted file mode 100644 index 3c52e2b43095..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef RTL8225H -#define RTL8225H - -#define RTL819X_TOTAL_RF_PATH 2 -void rtl92e_set_bandwidth(struct net_device *dev, - enum ht_channel_width bandwidth); -bool rtl92e_config_rf(struct net_device *dev); -void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel); -void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c deleted file mode 100644 index 533cc4e723f6..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_hw.h" -#include "r8192E_cmdpkt.h" - -bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data, - u32 len) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u16 frag_length = 0, frag_offset = 0; - struct sk_buff *skb; - unsigned char *seg_ptr; - struct cb_desc *tcb_desc; - u8 last_ini_pkt; - - struct tx_fwinfo_8190pci *pTxFwInfo = NULL; - - do { - if ((len - frag_offset) > CMDPACKET_FRAG_SIZE) { - frag_length = CMDPACKET_FRAG_SIZE; - last_ini_pkt = 0; - - } else { - frag_length = (u16)(len - frag_offset); - last_ini_pkt = 1; - } - - if (type == DESC_PACKET_TYPE_NORMAL) - skb = dev_alloc_skb(frag_length + - priv->rtllib->tx_headroom + 4); - else - skb = dev_alloc_skb(frag_length + 4); - - if (!skb) - return false; - - memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); - tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - tcb_desc->queue_index = TXCMD_QUEUE; - tcb_desc->cmd_or_init = type; - tcb_desc->last_ini_pkt = last_ini_pkt; - - if (type == DESC_PACKET_TYPE_NORMAL) { - tcb_desc->pkt_size = frag_length; - - seg_ptr = skb_put(skb, priv->rtllib->tx_headroom); - pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr; - memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci)); - memset(pTxFwInfo, 0x12, 8); - } else { - tcb_desc->txbuf_size = frag_length; - } - - skb_put_data(skb, data, frag_length); - - if (type == DESC_PACKET_TYPE_INIT && - (!priv->rtllib->check_nic_enough_desc(dev, TXCMD_QUEUE) || - (!skb_queue_empty(&priv->rtllib->skb_waitq[TXCMD_QUEUE])) || - (priv->rtllib->queue_stop))) { - skb_queue_tail(&priv->rtllib->skb_waitq[TXCMD_QUEUE], - skb); - } else { - priv->rtllib->softmac_hard_start_xmit(skb, dev); - } - - data += frag_length; - frag_offset += frag_length; - - } while (frag_offset < len); - - rtl92e_writeb(dev, TP_POLL, TP_POLL_CQ); - - return true; -} diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h deleted file mode 100644 index c63909199e93..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef R819XUSB_CMDPKT_H -#define R819XUSB_CMDPKT_H - -bool rtl92e_send_cmd_pkt(struct net_device *dev, u32 type, const void *data, - u32 len); -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c deleted file mode 100644 index 2672b1ddf88e..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ /dev/null @@ -1,1915 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_phy.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" -#include "r8192E_cmdpkt.h" -#include "rtl_dm.h" -#include "rtl_wx.h" - -static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, - EDCAPARA_VO}; - -static void _rtl92e_update_msr(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 msr; - - msr = rtl92e_readb(dev, MSR); - msr &= ~MSR_LINK_MASK; - - switch (priv->rtllib->iw_mode) { - case IW_MODE_INFRA: - if (priv->rtllib->link_state == MAC80211_LINKED) - msr |= MSR_LINK_MANAGED; - break; - default: - break; - } - - rtl92e_writeb(dev, MSR, msr); -} - -void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - switch (variable) { - case HW_VAR_BSSID: - /* BSSIDR 2 byte alignment */ - rtl92e_writew(dev, BSSIDR, *(u16 *)val); - rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2)); - break; - - case HW_VAR_MEDIA_STATUS: - { - enum rt_op_mode op_mode = *((enum rt_op_mode *)(val)); - u8 btMsr = rtl92e_readb(dev, MSR); - - btMsr &= 0xfc; - - switch (op_mode) { - case RT_OP_MODE_INFRASTRUCTURE: - btMsr |= MSR_INFRA; - break; - - case RT_OP_MODE_IBSS: - btMsr |= MSR_ADHOC; - break; - - case RT_OP_MODE_AP: - btMsr |= MSR_AP; - break; - - default: - btMsr |= MSR_NOLINK; - break; - } - - rtl92e_writeb(dev, MSR, btMsr); - } - break; - - case HW_VAR_CECHK_BSSID: - { - u32 RegRCR, Type; - - Type = val[0]; - RegRCR = rtl92e_readl(dev, RCR); - priv->receive_config = RegRCR; - - if (Type) - RegRCR |= (RCR_CBSSID); - else - RegRCR &= (~RCR_CBSSID); - - rtl92e_writel(dev, RCR, RegRCR); - priv->receive_config = RegRCR; - } - break; - - case HW_VAR_SLOT_TIME: - - priv->slot_time = val[0]; - rtl92e_writeb(dev, SLOT_TIME, val[0]); - - break; - - case HW_VAR_ACK_PREAMBLE: - { - u32 regTmp; - - priv->short_preamble = (bool)*val; - regTmp = priv->basic_rate; - if (priv->short_preamble) - regTmp |= BRSR_AckShortPmb; - rtl92e_writel(dev, RRSR, regTmp); - break; - } - - case HW_VAR_CPU_RST: - rtl92e_writel(dev, CPU_GEN, ((u32 *)(val))[0]); - break; - - case HW_VAR_AC_PARAM: - { - u8 pAcParam = *val; - u32 eACI = pAcParam; - u8 u1bAIFS; - u32 u4bAcParam; - u8 mode = priv->rtllib->mode; - struct rtllib_qos_parameters *qop = - &priv->rtllib->current_network.qos_data.parameters; - - u1bAIFS = qop->aifs[pAcParam] * - ((mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) ? 9 : 20) + asifs_time; - - rtl92e_dm_init_edca_turbo(dev); - - u4bAcParam = (le16_to_cpu(qop->tx_op_limit[pAcParam]) << - AC_PARAM_TXOP_LIMIT_OFFSET) | - ((le16_to_cpu(qop->cw_max[pAcParam])) << - AC_PARAM_ECW_MAX_OFFSET) | - ((le16_to_cpu(qop->cw_min[pAcParam])) << - AC_PARAM_ECW_MIN_OFFSET) | - (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET); - - switch (eACI) { - case AC1_BK: - rtl92e_writel(dev, EDCAPARA_BK, u4bAcParam); - break; - - case AC0_BE: - rtl92e_writel(dev, EDCAPARA_BE, u4bAcParam); - break; - - case AC2_VI: - rtl92e_writel(dev, EDCAPARA_VI, u4bAcParam); - break; - - case AC3_VO: - rtl92e_writel(dev, EDCAPARA_VO, u4bAcParam); - break; - - default: - netdev_info(dev, "SetHwReg8185(): invalid ACI: %d !\n", - eACI); - break; - } - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_ACM_CTRL, - &pAcParam); - break; - } - - case HW_VAR_ACM_CTRL: - { - struct rtllib_qos_parameters *qos_parameters = - &priv->rtllib->current_network.qos_data.parameters; - u8 pAcParam = *val; - u32 eACI = pAcParam; - union aci_aifsn *pAciAifsn = (union aci_aifsn *)& - (qos_parameters->aifs[0]); - u8 acm = pAciAifsn->f.acm; - u8 AcmCtrl = rtl92e_readb(dev, ACM_HW_CTRL); - - if (acm) { - switch (eACI) { - case AC0_BE: - AcmCtrl |= ACM_HW_BEQ_EN; - break; - - case AC2_VI: - AcmCtrl |= ACM_HW_VIQ_EN; - break; - - case AC3_VO: - AcmCtrl |= ACM_HW_VOQ_EN; - break; - } - } else { - switch (eACI) { - case AC0_BE: - AcmCtrl &= (~ACM_HW_BEQ_EN); - break; - - case AC2_VI: - AcmCtrl &= (~ACM_HW_VIQ_EN); - break; - - case AC3_VO: - AcmCtrl &= (~ACM_HW_BEQ_EN); - break; - - default: - break; - } - } - rtl92e_writeb(dev, ACM_HW_CTRL, AcmCtrl); - break; - } - - case HW_VAR_SIFS: - rtl92e_writeb(dev, SIFS, val[0]); - rtl92e_writeb(dev, SIFS + 1, val[0]); - break; - - case HW_VAR_RF_TIMING: - { - u8 Rf_Timing = *val; - - rtl92e_writeb(dev, rFPGA0_RFTiming1, Rf_Timing); - break; - } - - default: - break; - } -} - -static void _rtl92e_read_eeprom_info(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - const u8 bMac_Tmp_Addr[ETH_ALEN] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x01}; - u8 tempval; - u8 ICVer8192, ICVer8256; - u16 i, usValue, IC_Version; - u16 EEPROMId; - - EEPROMId = rtl92e_eeprom_read(dev, 0); - if (EEPROMId != RTL8190_EEPROM_ID) { - netdev_err(dev, "%s(): Invalid EEPROM ID: %x\n", __func__, - EEPROMId); - priv->autoload_fail_flag = true; - } else { - priv->autoload_fail_flag = false; - } - - if (!priv->autoload_fail_flag) { - priv->eeprom_vid = rtl92e_eeprom_read(dev, EEPROM_VID >> 1); - priv->eeprom_did = rtl92e_eeprom_read(dev, EEPROM_DID >> 1); - - usValue = rtl92e_eeprom_read(dev, - (EEPROM_Customer_ID >> 1)) >> 8; - priv->eeprom_customer_id = usValue & 0xff; - usValue = rtl92e_eeprom_read(dev, - EEPROM_ICVersion_ChannelPlan >> 1); - IC_Version = (usValue & 0xff00) >> 8; - - ICVer8192 = IC_Version & 0xf; - ICVer8256 = (IC_Version & 0xf0) >> 4; - if (ICVer8192 == 0x2) { - if (ICVer8256 == 0x5) - priv->card_8192_version = VERSION_8190_BE; - } - switch (priv->card_8192_version) { - case VERSION_8190_BD: - case VERSION_8190_BE: - break; - default: - priv->card_8192_version = VERSION_8190_BD; - break; - } - } else { - priv->card_8192_version = VERSION_8190_BD; - priv->eeprom_vid = 0; - priv->eeprom_did = 0; - priv->eeprom_customer_id = 0; - } - - if (!priv->autoload_fail_flag) { - u8 addr[ETH_ALEN]; - - for (i = 0; i < 6; i += 2) { - usValue = rtl92e_eeprom_read(dev, - (EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1); - *(u16 *)(&addr[i]) = usValue; - } - eth_hw_addr_set(dev, addr); - } else { - eth_hw_addr_set(dev, bMac_Tmp_Addr); - } - - if (priv->card_8192_version > VERSION_8190_BD) - priv->tx_pwr_data_read_from_eeprom = true; - else - priv->tx_pwr_data_read_from_eeprom = false; - - if (priv->card_8192_version > VERSION_8190_BD) { - if (!priv->autoload_fail_flag) { - tempval = (rtl92e_eeprom_read(dev, - (EEPROM_RFInd_PowerDiff >> 1))) & 0xff; - priv->eeprom_legacy_ht_tx_pwr_diff = tempval & 0xf; - } else { - priv->eeprom_legacy_ht_tx_pwr_diff = 0x04; - } - - if (!priv->autoload_fail_flag) - priv->eeprom_thermal_meter = ((rtl92e_eeprom_read(dev, - (EEPROM_ThermalMeter >> 1))) & - 0xff00) >> 8; - else - priv->eeprom_thermal_meter = EEPROM_Default_ThermalMeter; - priv->tssi_13dBm = priv->eeprom_thermal_meter * 100; - - if (priv->epromtype == EEPROM_93C46) { - if (!priv->autoload_fail_flag) { - usValue = rtl92e_eeprom_read(dev, - EEPROM_TxPwDiff_CrystalCap >> 1); - priv->eeprom_ant_pwr_diff = usValue & 0x0fff; - priv->eeprom_crystal_cap = (usValue & 0xf000) - >> 12; - } else { - priv->eeprom_ant_pwr_diff = - EEPROM_Default_AntTxPowerDiff; - priv->eeprom_crystal_cap = - EEPROM_Default_TxPwDiff_CrystalCap; - } - - for (i = 0; i < 14; i += 2) { - if (!priv->autoload_fail_flag) - usValue = rtl92e_eeprom_read(dev, - (EEPROM_TxPwIndex_CCK + i) >> 1); - else - usValue = EEPROM_Default_TxPower; - *((u16 *)(&priv->eeprom_tx_pwr_level_cck[i])) = - usValue; - } - for (i = 0; i < 14; i += 2) { - if (!priv->autoload_fail_flag) - usValue = rtl92e_eeprom_read(dev, - (EEPROM_TxPwIndex_OFDM_24G + i) >> 1); - else - usValue = EEPROM_Default_TxPower; - *((u16 *)(&priv->eeprom_tx_pwr_level_ofdm24g[i])) - = usValue; - } - } - if (priv->epromtype == EEPROM_93C46) { - for (i = 0; i < 14; i++) { - priv->tx_pwr_level_cck[i] = - priv->eeprom_tx_pwr_level_cck[i]; - priv->tx_pwr_level_ofdm_24g[i] = - priv->eeprom_tx_pwr_level_ofdm24g[i]; - } - priv->legacy_ht_tx_pwr_diff = - priv->eeprom_legacy_ht_tx_pwr_diff; - priv->antenna_tx_pwr_diff[0] = priv->eeprom_ant_pwr_diff & 0xf; - priv->antenna_tx_pwr_diff[1] = (priv->eeprom_ant_pwr_diff & - 0xf0) >> 4; - priv->antenna_tx_pwr_diff[2] = (priv->eeprom_ant_pwr_diff & - 0xf00) >> 8; - priv->crystal_cap = priv->eeprom_crystal_cap; - priv->thermal_meter[0] = priv->eeprom_thermal_meter & 0xf; - priv->thermal_meter[1] = (priv->eeprom_thermal_meter & - 0xf0) >> 4; - } else if (priv->epromtype == EEPROM_93C56) { - priv->legacy_ht_tx_pwr_diff = - priv->eeprom_legacy_ht_tx_pwr_diff; - priv->antenna_tx_pwr_diff[0] = 0; - priv->antenna_tx_pwr_diff[1] = 0; - priv->antenna_tx_pwr_diff[2] = 0; - priv->crystal_cap = priv->eeprom_crystal_cap; - priv->thermal_meter[0] = priv->eeprom_thermal_meter & 0xf; - priv->thermal_meter[1] = (priv->eeprom_thermal_meter & - 0xf0) >> 4; - } - } - - rtl92e_init_adaptive_rate(dev); - - switch (priv->eeprom_customer_id) { - case EEPROM_CID_NetCore: - priv->customer_id = RT_CID_819X_NETCORE; - break; - case EEPROM_CID_TOSHIBA: - priv->customer_id = RT_CID_TOSHIBA; - break; - } - - if (priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304) - priv->rtllib->bSupportRemoteWakeUp = true; - else - priv->rtllib->bSupportRemoteWakeUp = false; -} - -void rtl92e_get_eeprom_size(struct net_device *dev) -{ - u16 curCR; - struct r8192_priv *priv = rtllib_priv(dev); - - curCR = rtl92e_readw(dev, EPROM_CMD); - priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 : - EEPROM_93C46; - _rtl92e_read_eeprom_info(dev); -} - -static void _rtl92e_hwconfig(struct net_device *dev) -{ - u32 regRATR = 0, regRRSR = 0; - u8 regBwOpMode = 0, regTmp = 0; - struct r8192_priv *priv = rtllib_priv(dev); - - switch (priv->rtllib->mode) { - case WIRELESS_MODE_B: - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK; - regRRSR = RATE_ALL_CCK; - break; - case WIRELESS_MODE_AUTO: - case WIRELESS_MODE_N_24G: - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - break; - case WIRELESS_MODE_G: - default: - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - break; - } - - rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); - { - u32 ratr_value; - - ratr_value = regRATR; - ratr_value &= ~(RATE_ALL_OFDM_2SS); - rtl92e_writel(dev, RATR0, ratr_value); - rtl92e_writeb(dev, UFWP, 1); - } - regTmp = rtl92e_readb(dev, 0x313); - regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff); - rtl92e_writel(dev, RRSR, regRRSR); - - rtl92e_writew(dev, RETRY_LIMIT, - priv->short_retry_limit << RETRY_LIMIT_SHORT_SHIFT | - priv->long_retry_limit << RETRY_LIMIT_LONG_SHIFT); -} - -bool rtl92e_start_adapter(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 ulRegRead; - bool rtStatus = true; - u8 tmpvalue; - u8 ICVersion, SwitchingRegulatorOutput; - bool bfirmwareok = true; - u32 tmpRegA, TempCCk; - int i = 0; - u32 retry_times = 0; - - priv->being_init_adapter = true; - -start: - rtl92e_reset_desc_ring(dev); - priv->rf_mode = RF_OP_By_SW_3wire; - - rtl92e_writeb(dev, ANAPAR, 0x37); - mdelay(500); - - priv->fw_info->status = FW_STATUS_0_INIT; - - ulRegRead = rtl92e_readl(dev, CPU_GEN); - if (priv->fw_info->status == FW_STATUS_0_INIT) - ulRegRead |= CPU_GEN_SYSTEM_RESET; - else if (priv->fw_info->status == FW_STATUS_5_READY) - ulRegRead |= CPU_GEN_FIRMWARE_RESET; - else - netdev_err(dev, "%s(): undefined firmware state: %d.\n", - __func__, priv->fw_info->status); - - rtl92e_writel(dev, CPU_GEN, ulRegRead); - - ICVersion = rtl92e_readb(dev, IC_VERRSION); - if (ICVersion >= 0x4) { - SwitchingRegulatorOutput = rtl92e_readb(dev, SWREGULATOR); - if (SwitchingRegulatorOutput != 0xb8) { - rtl92e_writeb(dev, SWREGULATOR, 0xa8); - mdelay(1); - rtl92e_writeb(dev, SWREGULATOR, 0xb8); - } - } - rtStatus = rtl92e_config_bb(dev); - if (!rtStatus) { - netdev_warn(dev, "%s(): Failed to configure BB\n", __func__); - return rtStatus; - } - - priv->loopback_mode = RTL819X_NO_LOOPBACK; - ulRegRead = rtl92e_readl(dev, CPU_GEN); - if (priv->loopback_mode == RTL819X_NO_LOOPBACK) - ulRegRead = (ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) | - CPU_GEN_NO_LOOPBACK_SET; - else if (priv->loopback_mode == RTL819X_MAC_LOOPBACK) - ulRegRead |= CPU_CCK_LOOPBACK; - else - netdev_err(dev, "%s: Invalid loopback mode setting.\n", - __func__); - - rtl92e_writel(dev, CPU_GEN, ulRegRead); - - udelay(500); - - _rtl92e_hwconfig(dev); - rtl92e_writeb(dev, CMDR, CR_RE | CR_TE); - - rtl92e_writeb(dev, PCIF, ((MXDMA2_NO_LIMIT << MXDMA2_RX_SHIFT) | - (MXDMA2_NO_LIMIT << MXDMA2_TX_SHIFT))); - rtl92e_writel(dev, MAC0, ((u32 *)dev->dev_addr)[0]); - rtl92e_writew(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]); - rtl92e_writel(dev, RCR, priv->receive_config); - - rtl92e_writel(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << - RSVD_FW_QUEUE_PAGE_BK_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_BE << - RSVD_FW_QUEUE_PAGE_BE_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_VI << - RSVD_FW_QUEUE_PAGE_VI_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_VO << - RSVD_FW_QUEUE_PAGE_VO_SHIFT); - rtl92e_writel(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << - RSVD_FW_QUEUE_PAGE_MGNT_SHIFT); - rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW | - NUM_OF_PAGE_IN_FW_QUEUE_BCN << - RSVD_FW_QUEUE_PAGE_BCN_SHIFT | - NUM_OF_PAGE_IN_FW_QUEUE_PUB << - RSVD_FW_QUEUE_PAGE_PUB_SHIFT); - - rtl92e_tx_enable(dev); - rtl92e_rx_enable(dev); - ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR)) | - RATE_ALL_OFDM_AG | RATE_ALL_CCK; - rtl92e_writel(dev, RRSR, ulRegRead); - rtl92e_writel(dev, RATR0 + 4 * 7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK)); - - rtl92e_writeb(dev, ACK_TIMEOUT, 0x30); - - rtl92e_set_wireless_mode(dev, priv->rtllib->mode); - rtl92e_cam_reset(dev); - { - u8 SECR_value = 0x0; - - SECR_value |= SCR_TxEncEnable; - SECR_value |= SCR_RxDecEnable; - SECR_value |= SCR_NoSKMC; - rtl92e_writeb(dev, SECR, SECR_value); - } - rtl92e_writew(dev, ATIMWND, 2); - rtl92e_writew(dev, BCN_INTERVAL, 100); - - for (i = 0; i < QOS_QUEUE_NUM; i++) - rtl92e_writel(dev, WDCAPARA_ADD[i], 0x005e4332); - - rtl92e_writeb(dev, 0xbe, 0xc0); - - rtl92e_config_mac(dev); - - if (priv->card_8192_version > VERSION_8190_BD) { - rtl92e_get_tx_power(dev); - rtl92e_set_tx_power(dev, priv->chan); - } - - tmpvalue = rtl92e_readb(dev, IC_VERRSION); - priv->ic_cut = tmpvalue; - - bfirmwareok = rtl92e_init_fw(dev); - if (!bfirmwareok) { - if (retry_times < 10) { - retry_times++; - goto start; - } else { - rtStatus = false; - goto end; - } - } - - rtStatus = rtl92e_config_rf(dev); - if (!rtStatus) { - netdev_info(dev, "RF Config failed\n"); - return rtStatus; - } - - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); - - rtl92e_writeb(dev, 0x87, 0x0); - - if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_PS) { - rtl92e_set_rf_state(dev, rf_off, priv->rtllib->rf_off_reason); - } else if (priv->rtllib->rf_off_reason >= RF_CHANGE_BY_IPS) { - rtl92e_set_rf_state(dev, rf_off, priv->rtllib->rf_off_reason); - } else { - priv->rtllib->rf_power_state = rf_on; - priv->rtllib->rf_off_reason = 0; - } - - if (priv->rtllib->FwRWRF) - priv->rf_mode = RF_OP_By_FW; - else - priv->rf_mode = RF_OP_By_SW_3wire; - - rtl92e_dm_init_txpower_tracking(dev); - - if (priv->ic_cut >= IC_VersionCut_D) { - tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord); - rtl92e_get_bb_reg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord); - - for (i = 0; i < TX_BB_GAIN_TABLE_LEN; i++) { - if (tmpRegA == dm_tx_bb_gain[i]) { - priv->rfa_txpowertrackingindex = i; - priv->rfa_txpowertrackingindex_real = i; - priv->rfa_txpowertracking_default = - priv->rfa_txpowertrackingindex; - break; - } - } - - TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, - bMaskByte2); - - for (i = 0; i < CCK_TX_BB_GAIN_TABLE_LEN; i++) { - if (TempCCk == dm_cck_tx_bb_gain[i][0]) { - priv->cck_present_attn_20m_def = i; - break; - } - } - priv->cck_present_attn_40m_def = 0; - priv->cck_present_attn_diff = 0; - priv->cck_present_attn = - priv->cck_present_attn_20m_def; - priv->btxpower_tracking = false; - } - rtl92e_irq_enable(dev); -end: - priv->being_init_adapter = false; - return rtStatus; -} - -static void _rtl92e_net_update(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_network *net; - u16 rate_config = 0; - - net = &priv->rtllib->current_network; - rtl92e_config_rate(dev, &rate_config); - priv->dot11_current_preamble_mode = PREAMBLE_AUTO; - priv->basic_rate = rate_config &= 0x15f; - rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid); - rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2)); -} - -void rtl92e_link_change(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - if (!priv->up) - return; - - if (ieee->link_state == MAC80211_LINKED) { - _rtl92e_net_update(dev); - rtl92e_update_ratr_table(dev); - if ((ieee->pairwise_key_type == KEY_TYPE_WEP40) || - (ieee->pairwise_key_type == KEY_TYPE_WEP104)) - rtl92e_enable_hw_security_config(dev); - } else { - rtl92e_writeb(dev, 0x173, 0); - } - _rtl92e_update_msr(dev); - - if (ieee->iw_mode == IW_MODE_INFRA) { - u32 reg; - - reg = rtl92e_readl(dev, RCR); - if (priv->rtllib->link_state == MAC80211_LINKED) - priv->receive_config = reg |= RCR_CBSSID; - else - priv->receive_config = reg &= ~RCR_CBSSID; - - rtl92e_writel(dev, RCR, reg); - } -} - -void rtl92e_set_monitor_mode(struct net_device *dev, bool allow_all_da, - bool write_into_reg) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (allow_all_da) - priv->receive_config |= RCR_AAP; - else - priv->receive_config &= ~RCR_AAP; - - if (write_into_reg) - rtl92e_writel(dev, RCR, priv->receive_config); -} - -static u8 _rtl92e_rate_mgn_to_hw(u8 rate) -{ - u8 ret = DESC90_RATE1M; - - switch (rate) { - case MGN_1M: - ret = DESC90_RATE1M; - break; - case MGN_2M: - ret = DESC90_RATE2M; - break; - case MGN_5_5M: - ret = DESC90_RATE5_5M; - break; - case MGN_11M: - ret = DESC90_RATE11M; - break; - case MGN_6M: - ret = DESC90_RATE6M; - break; - case MGN_9M: - ret = DESC90_RATE9M; - break; - case MGN_12M: - ret = DESC90_RATE12M; - break; - case MGN_18M: - ret = DESC90_RATE18M; - break; - case MGN_24M: - ret = DESC90_RATE24M; - break; - case MGN_36M: - ret = DESC90_RATE36M; - break; - case MGN_48M: - ret = DESC90_RATE48M; - break; - case MGN_54M: - ret = DESC90_RATE54M; - break; - case MGN_MCS0: - ret = DESC90_RATEMCS0; - break; - case MGN_MCS1: - ret = DESC90_RATEMCS1; - break; - case MGN_MCS2: - ret = DESC90_RATEMCS2; - break; - case MGN_MCS3: - ret = DESC90_RATEMCS3; - break; - case MGN_MCS4: - ret = DESC90_RATEMCS4; - break; - case MGN_MCS5: - ret = DESC90_RATEMCS5; - break; - case MGN_MCS6: - ret = DESC90_RATEMCS6; - break; - case MGN_MCS7: - ret = DESC90_RATEMCS7; - break; - case MGN_MCS8: - ret = DESC90_RATEMCS8; - break; - case MGN_MCS9: - ret = DESC90_RATEMCS9; - break; - case MGN_MCS10: - ret = DESC90_RATEMCS10; - break; - case MGN_MCS11: - ret = DESC90_RATEMCS11; - break; - case MGN_MCS12: - ret = DESC90_RATEMCS12; - break; - case MGN_MCS13: - ret = DESC90_RATEMCS13; - break; - case MGN_MCS14: - ret = DESC90_RATEMCS14; - break; - case MGN_MCS15: - ret = DESC90_RATEMCS15; - break; - case (0x80 | 0x20): - ret = DESC90_RATEMCS32; - break; - default: - break; - } - return ret; -} - -static u8 _rtl92e_hw_queue_to_fw_queue(struct net_device *dev, u8 QueueID, - u8 priority) -{ - u8 QueueSelect = 0x0; - - switch (QueueID) { - case BE_QUEUE: - QueueSelect = QSLT_BE; - break; - - case BK_QUEUE: - QueueSelect = QSLT_BK; - break; - - case VO_QUEUE: - QueueSelect = QSLT_VO; - break; - - case VI_QUEUE: - QueueSelect = QSLT_VI; - break; - case MGNT_QUEUE: - QueueSelect = QSLT_MGNT; - break; - case BEACON_QUEUE: - QueueSelect = QSLT_BEACON; - break; - case TXCMD_QUEUE: - QueueSelect = QSLT_CMD; - break; - case HIGH_QUEUE: - QueueSelect = QSLT_HIGH; - break; - default: - netdev_warn(dev, "%s(): Impossible Queue Selection: %d\n", - __func__, QueueID); - break; - } - return QueueSelect; -} - -static u8 _rtl92e_query_is_short(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc) -{ - u8 tmp_Short; - - tmp_Short = (TxHT == 1) ? ((tcb_desc->use_short_gi) ? 1 : 0) : - ((tcb_desc->use_short_preamble) ? 1 : 0); - if (TxHT == 1 && TxRate != DESC90_RATEMCS15) - tmp_Short = 0; - - return tmp_Short; -} - -void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, - struct cb_desc *cb_desc, struct sk_buff *skb) -{ - struct r8192_priv *priv = rtllib_priv(dev); - dma_addr_t mapping; - struct tx_fwinfo_8190pci *pTxFwInfo; - - pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data; - memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci)); - pTxFwInfo->TxHT = (cb_desc->data_rate & 0x80) ? 1 : 0; - pTxFwInfo->TxRate = _rtl92e_rate_mgn_to_hw(cb_desc->data_rate); - pTxFwInfo->EnableCPUDur = cb_desc->tx_enable_fw_calc_dur; - pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT, - pTxFwInfo->TxRate, cb_desc); - - if (cb_desc->ampdu_enable) { - pTxFwInfo->AllowAggregation = 1; - pTxFwInfo->RxMF = cb_desc->ampdu_factor; - pTxFwInfo->RxAMD = cb_desc->ampdu_density; - } else { - pTxFwInfo->AllowAggregation = 0; - pTxFwInfo->RxMF = 0; - pTxFwInfo->RxAMD = 0; - } - - pTxFwInfo->RtsEnable = (cb_desc->rts_enable) ? 1 : 0; - pTxFwInfo->CtsEnable = (cb_desc->cts_enable) ? 1 : 0; - pTxFwInfo->RtsSTBC = (cb_desc->rtsstbc) ? 1 : 0; - pTxFwInfo->RtsHT = (cb_desc->rts_rate & 0x80) ? 1 : 0; - pTxFwInfo->RtsRate = _rtl92e_rate_mgn_to_hw(cb_desc->rts_rate); - pTxFwInfo->RtsBandwidth = 0; - pTxFwInfo->RtsSubcarrier = cb_desc->RTSSC; - pTxFwInfo->RtsShort = (pTxFwInfo->RtsHT == 0) ? - (cb_desc->rts_use_short_preamble ? 1 : 0) : - (cb_desc->rts_use_short_gi ? 1 : 0); - if (priv->current_chnl_bw == HT_CHANNEL_WIDTH_20_40) { - if (cb_desc->packet_bw) { - pTxFwInfo->TxBandwidth = 1; - pTxFwInfo->TxSubCarrier = 0; - } else { - pTxFwInfo->TxBandwidth = 0; - pTxFwInfo->TxSubCarrier = priv->n_cur_40mhz_prime_sc; - } - } else { - pTxFwInfo->TxBandwidth = 0; - pTxFwInfo->TxSubCarrier = 0; - } - - memset((u8 *)pdesc, 0, 12); - - mapping = dma_map_single(&priv->pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(&priv->pdev->dev, mapping)) { - netdev_err(dev, "%s(): DMA Mapping error\n", __func__); - return; - } - - pdesc->LINIP = 0; - pdesc->CmdInit = 1; - pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; - pdesc->PktSize = skb->len - sizeof(struct tx_fwinfo_8190pci); - - pdesc->SecCAMID = 0; - pdesc->RATid = cb_desc->ratr_index; - - pdesc->NoEnc = 1; - pdesc->SecType = 0x0; - if (cb_desc->hw_sec) { - static u8 tmp; - - if (!tmp) - tmp = 1; - switch (priv->rtllib->pairwise_key_type) { - case KEY_TYPE_WEP40: - case KEY_TYPE_WEP104: - pdesc->SecType = 0x1; - pdesc->NoEnc = 0; - break; - case KEY_TYPE_TKIP: - pdesc->SecType = 0x2; - pdesc->NoEnc = 0; - break; - case KEY_TYPE_CCMP: - pdesc->SecType = 0x3; - pdesc->NoEnc = 0; - break; - case KEY_TYPE_NA: - pdesc->SecType = 0x0; - pdesc->NoEnc = 1; - break; - } - } - - pdesc->PktId = 0x0; - - pdesc->QueueSelect = _rtl92e_hw_queue_to_fw_queue(dev, - cb_desc->queue_index, - cb_desc->priority); - pdesc->TxFWInfoSize = sizeof(struct tx_fwinfo_8190pci); - - pdesc->DISFB = cb_desc->tx_dis_rate_fallback; - pdesc->USERATE = cb_desc->tx_use_drv_assinged_rate; - - pdesc->FirstSeg = 1; - pdesc->LastSeg = 1; - pdesc->TxBufferSize = skb->len; - - pdesc->TxBuffAddr = mapping; -} - -void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry, - struct cb_desc *cb_desc, struct sk_buff *skb) -{ - struct r8192_priv *priv = rtllib_priv(dev); - dma_addr_t mapping = dma_map_single(&priv->pdev->dev, skb->data, - skb->len, DMA_TO_DEVICE); - - if (dma_mapping_error(&priv->pdev->dev, mapping)) - netdev_err(dev, "%s(): DMA Mapping error\n", __func__); - memset(entry, 0, 12); - entry->LINIP = cb_desc->last_ini_pkt; - entry->FirstSeg = 1; - entry->LastSeg = 1; - if (cb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { - entry->CmdInit = DESC_PACKET_TYPE_INIT; - } else { - struct tx_desc *entry_tmp = (struct tx_desc *)entry; - - entry_tmp->CmdInit = DESC_PACKET_TYPE_NORMAL; - entry_tmp->Offset = sizeof(struct tx_fwinfo_8190pci) + 8; - entry_tmp->PktSize = cb_desc->pkt_size + entry_tmp->Offset; - entry_tmp->QueueSelect = QSLT_CMD; - entry_tmp->TxFWInfoSize = 0x08; - entry_tmp->RATid = DESC_PACKET_TYPE_INIT; - } - entry->TxBufferSize = skb->len; - entry->TxBuffAddr = mapping; - entry->OWN = 1; -} - -static u8 _rtl92e_rate_hw_to_mgn(bool bIsHT, u8 rate) -{ - u8 ret_rate = 0x02; - - if (!bIsHT) { - switch (rate) { - case DESC90_RATE1M: - ret_rate = MGN_1M; - break; - case DESC90_RATE2M: - ret_rate = MGN_2M; - break; - case DESC90_RATE5_5M: - ret_rate = MGN_5_5M; - break; - case DESC90_RATE11M: - ret_rate = MGN_11M; - break; - case DESC90_RATE6M: - ret_rate = MGN_6M; - break; - case DESC90_RATE9M: - ret_rate = MGN_9M; - break; - case DESC90_RATE12M: - ret_rate = MGN_12M; - break; - case DESC90_RATE18M: - ret_rate = MGN_18M; - break; - case DESC90_RATE24M: - ret_rate = MGN_24M; - break; - case DESC90_RATE36M: - ret_rate = MGN_36M; - break; - case DESC90_RATE48M: - ret_rate = MGN_48M; - break; - case DESC90_RATE54M: - ret_rate = MGN_54M; - break; - } - - } else { - switch (rate) { - case DESC90_RATEMCS0: - ret_rate = MGN_MCS0; - break; - case DESC90_RATEMCS1: - ret_rate = MGN_MCS1; - break; - case DESC90_RATEMCS2: - ret_rate = MGN_MCS2; - break; - case DESC90_RATEMCS3: - ret_rate = MGN_MCS3; - break; - case DESC90_RATEMCS4: - ret_rate = MGN_MCS4; - break; - case DESC90_RATEMCS5: - ret_rate = MGN_MCS5; - break; - case DESC90_RATEMCS6: - ret_rate = MGN_MCS6; - break; - case DESC90_RATEMCS7: - ret_rate = MGN_MCS7; - break; - case DESC90_RATEMCS8: - ret_rate = MGN_MCS8; - break; - case DESC90_RATEMCS9: - ret_rate = MGN_MCS9; - break; - case DESC90_RATEMCS10: - ret_rate = MGN_MCS10; - break; - case DESC90_RATEMCS11: - ret_rate = MGN_MCS11; - break; - case DESC90_RATEMCS12: - ret_rate = MGN_MCS12; - break; - case DESC90_RATEMCS13: - ret_rate = MGN_MCS13; - break; - case DESC90_RATEMCS14: - ret_rate = MGN_MCS14; - break; - case DESC90_RATEMCS15: - ret_rate = MGN_MCS15; - break; - case DESC90_RATEMCS32: - ret_rate = 0x80 | 0x20; - break; - } - } - - return ret_rate; -} - -static long _rtl92e_signal_scale_mapping(struct r8192_priv *priv, long currsig) -{ - long retsig; - - if (currsig >= 61 && currsig <= 100) - retsig = 90 + ((currsig - 60) / 4); - else if (currsig >= 41 && currsig <= 60) - retsig = 78 + ((currsig - 40) / 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 5 && currsig <= 20) - retsig = 42 + (((currsig - 5) * 2) / 3); - else if (currsig == 4) - retsig = 36; - else if (currsig == 3) - retsig = 27; - else if (currsig == 2) - retsig = 18; - else if (currsig == 1) - retsig = 9; - else - retsig = currsig; - - return retsig; -} - -#define rx_hal_is_cck_rate(_pdrvinfo)\ - ((_pdrvinfo->RxRate == DESC90_RATE1M ||\ - _pdrvinfo->RxRate == DESC90_RATE2M ||\ - _pdrvinfo->RxRate == DESC90_RATE5_5M ||\ - _pdrvinfo->RxRate == DESC90_RATE11M) &&\ - !_pdrvinfo->RxHT) - -static void _rtl92e_query_rxphystatus(struct r8192_priv *priv, - struct rtllib_rx_stats *pstats, - struct rx_desc *pdesc, - struct rx_fwinfo *pdrvinfo, - struct rtllib_rx_stats *precord_stats, - bool bpacket_match_bssid, - bool bpacket_toself, - bool bPacketBeacon, - bool bToSelfBA) -{ - struct phy_sts_ofdm_819xpci *pofdm_buf; - struct phy_sts_cck_819xpci *pcck_buf; - u8 *prxpkt; - u8 i, max_spatial_stream, tmp_rxevm; - s8 rx_pwr[RF90_PATH_MAX], rx_pwr_all = 0; - s8 rx_evmX; - u8 evm, pwdb_all; - u32 RSSI, total_rssi = 0; - u8 is_cck_rate = 0; - u8 rf_rx_num = 0; - static u8 check_reg824; - static u32 reg824_bit9; - - is_cck_rate = rx_hal_is_cck_rate(pdrvinfo); - memset(precord_stats, 0, sizeof(struct rtllib_rx_stats)); - pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = - bpacket_match_bssid; - pstats->packet_to_self = precord_stats->packet_to_self = bpacket_toself; - pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate; - pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon; - pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA; - if (check_reg824 == 0) { - reg824_bit9 = rtl92e_get_bb_reg(priv->rtllib->dev, - rFPGA0_XA_HSSIParameter2, - 0x200); - check_reg824 = 1; - } - - prxpkt = (u8 *)pdrvinfo; - - prxpkt += sizeof(struct rx_fwinfo); - - pcck_buf = (struct phy_sts_cck_819xpci *)prxpkt; - pofdm_buf = (struct phy_sts_ofdm_819xpci *)prxpkt; - - pstats->RxMIMOSignalQuality[0] = -1; - pstats->RxMIMOSignalQuality[1] = -1; - precord_stats->RxMIMOSignalQuality[0] = -1; - precord_stats->RxMIMOSignalQuality[1] = -1; - - if (is_cck_rate) { - u8 report; - - if (!reg824_bit9) { - report = pcck_buf->cck_agc_rpt & 0xc0; - report >>= 6; - switch (report) { - case 0x3: - rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x2: - rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x1: - rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x0: - rx_pwr_all = 8 - (pcck_buf->cck_agc_rpt & 0x3e); - break; - } - } else { - report = pcck_buf->cck_agc_rpt & 0x60; - report >>= 5; - switch (report) { - case 0x3: - rx_pwr_all = -35 - - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -23 - - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -11 - - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = -8 - - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - } - } - - pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all); - pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; - pstats->RecvSignalPower = rx_pwr_all; - - if (bpacket_match_bssid) { - u8 sq; - - if (pstats->RxPWDBAll > 40) { - sq = 100; - } else { - sq = pcck_buf->sq_rpt; - - if (pcck_buf->sq_rpt > 64) - sq = 0; - else if (pcck_buf->sq_rpt < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - pstats->signal_quality = sq; - precord_stats->signal_quality = sq; - pstats->RxMIMOSignalQuality[0] = sq; - precord_stats->RxMIMOSignalQuality[0] = sq; - pstats->RxMIMOSignalQuality[1] = -1; - precord_stats->RxMIMOSignalQuality[1] = -1; - } - } else { - for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { - if (priv->brfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i] & 0x3F) * - 2) - 110; - - RSSI = rtl92e_rx_db_to_percent(rx_pwr[i]); - if (priv->brfpath_rxenable[i]) - total_rssi += RSSI; - - if (bpacket_match_bssid) { - pstats->RxMIMOSignalStrength[i] = RSSI; - precord_stats->RxMIMOSignalStrength[i] = RSSI; - } - } - - rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106; - pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all); - - pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all; - pstats->RecvSignalPower = rx_pwr_all; - if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 && - pdrvinfo->RxRate <= DESC90_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - tmp_rxevm = pofdm_buf->rxevm_X[i]; - rx_evmX = (s8)(tmp_rxevm); - - rx_evmX /= 2; - - evm = rtl92e_evm_db_to_percent(rx_evmX); - if (bpacket_match_bssid) { - if (i == 0) { - pstats->signal_quality = evm & 0xff; - precord_stats->signal_quality = evm & 0xff; - } - pstats->RxMIMOSignalQuality[i] = evm & 0xff; - precord_stats->RxMIMOSignalQuality[i] = evm & 0xff; - } - } - } - - if (is_cck_rate) { - pstats->signal_strength = precord_stats->signal_strength = - _rtl92e_signal_scale_mapping(priv, (long)pwdb_all); - - } else { - if (rf_rx_num != 0) - pstats->signal_strength = precord_stats->signal_strength = - _rtl92e_signal_scale_mapping(priv, - (long)(total_rssi /= rf_rx_num)); - } -} - -static void _rtl92e_process_phyinfo(struct r8192_priv *priv, u8 *buffer, - struct rtllib_rx_stats *prev_st, - struct rtllib_rx_stats *curr_st) -{ - bool bcheck = false; - u8 rfpath; - u32 ij, tmp_val; - static u32 slide_rssi_index, slide_rssi_statistics; - static u32 slide_evm_index, slide_evm_statistics; - static u32 last_rssi, last_evm; - static u32 slide_beacon_adc_pwdb_index; - static u32 slide_beacon_adc_pwdb_statistics; - static u32 last_beacon_adc_pwdb; - - if (!prev_st->bIsAMPDU) - bcheck = true; - - if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) { - slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX; - last_rssi = priv->stats.slide_signal_strength[slide_rssi_index]; - priv->stats.slide_rssi_total -= last_rssi; - } - priv->stats.slide_rssi_total += prev_st->signal_strength; - - priv->stats.slide_signal_strength[slide_rssi_index++] = - prev_st->signal_strength; - if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX) - slide_rssi_index = 0; - - tmp_val = priv->stats.slide_rssi_total / slide_rssi_statistics; - priv->stats.signal_strength = rtl92e_translate_to_dbm(priv, tmp_val); - curr_st->rssi = priv->stats.signal_strength; - if (!prev_st->bPacketMatchBSSID) { - if (!prev_st->bToSelfBA) - return; - } - - if (!bcheck) - return; - - if (!prev_st->bIsCCK && prev_st->packet_to_self) { - for (rfpath = RF90_PATH_A; rfpath < priv->num_total_rf_path; rfpath++) { - if (priv->stats.rx_rssi_percentage[rfpath] == 0) { - priv->stats.rx_rssi_percentage[rfpath] = - prev_st->RxMIMOSignalStrength[rfpath]; - } - if (prev_st->RxMIMOSignalStrength[rfpath] > - priv->stats.rx_rssi_percentage[rfpath]) { - priv->stats.rx_rssi_percentage[rfpath] = - ((priv->stats.rx_rssi_percentage[rfpath] - * (RX_SMOOTH - 1)) + - (prev_st->RxMIMOSignalStrength - [rfpath])) / (RX_SMOOTH); - priv->stats.rx_rssi_percentage[rfpath] = - priv->stats.rx_rssi_percentage[rfpath] - + 1; - } else { - priv->stats.rx_rssi_percentage[rfpath] = - ((priv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH - 1)) + - (prev_st->RxMIMOSignalStrength[rfpath])) / - (RX_SMOOTH); - } - } - } - - if (prev_st->bPacketBeacon) { - if (slide_beacon_adc_pwdb_statistics++ >= - PHY_Beacon_RSSI_SLID_WIN_MAX) { - slide_beacon_adc_pwdb_statistics = - PHY_Beacon_RSSI_SLID_WIN_MAX; - last_beacon_adc_pwdb = priv->stats.slide_beacon_pwdb - [slide_beacon_adc_pwdb_index]; - priv->stats.slide_beacon_total -= last_beacon_adc_pwdb; - } - priv->stats.slide_beacon_total += prev_st->RxPWDBAll; - priv->stats.slide_beacon_pwdb[slide_beacon_adc_pwdb_index] = - prev_st->RxPWDBAll; - slide_beacon_adc_pwdb_index++; - if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX) - slide_beacon_adc_pwdb_index = 0; - prev_st->RxPWDBAll = priv->stats.slide_beacon_total / - slide_beacon_adc_pwdb_statistics; - if (prev_st->RxPWDBAll >= 3) - prev_st->RxPWDBAll -= 3; - } - if (prev_st->packet_to_self || prev_st->bPacketBeacon || - prev_st->bToSelfBA) { - if (priv->undecorated_smoothed_pwdb < 0) - priv->undecorated_smoothed_pwdb = prev_st->RxPWDBAll; - if (prev_st->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) { - priv->undecorated_smoothed_pwdb = - (((priv->undecorated_smoothed_pwdb) * - (RX_SMOOTH - 1)) + - (prev_st->RxPWDBAll)) / (RX_SMOOTH); - priv->undecorated_smoothed_pwdb = - priv->undecorated_smoothed_pwdb + 1; - } else { - priv->undecorated_smoothed_pwdb = - (((priv->undecorated_smoothed_pwdb) * - (RX_SMOOTH - 1)) + - (prev_st->RxPWDBAll)) / (RX_SMOOTH); - } - rtl92e_update_rx_statistics(priv, prev_st); - } - - if (prev_st->signal_quality != 0) { - if (prev_st->packet_to_self || prev_st->bPacketBeacon || - prev_st->bToSelfBA) { - if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) { - slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX; - last_evm = - priv->stats.slide_evm[slide_evm_index]; - priv->stats.slide_evm_total -= last_evm; - } - - priv->stats.slide_evm_total += prev_st->signal_quality; - - priv->stats.slide_evm[slide_evm_index++] = - prev_st->signal_quality; - if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX) - slide_evm_index = 0; - - tmp_val = priv->stats.slide_evm_total / - slide_evm_statistics; - priv->stats.last_signal_strength_inpercent = tmp_val; - } - - if (prev_st->packet_to_self || - prev_st->bPacketBeacon || - prev_st->bToSelfBA) { - for (ij = 0; ij < 2; ij++) { - if (prev_st->RxMIMOSignalQuality[ij] != -1) { - if (priv->stats.rx_evm_percentage[ij] == 0) - priv->stats.rx_evm_percentage[ij] = - prev_st->RxMIMOSignalQuality[ij]; - priv->stats.rx_evm_percentage[ij] = - ((priv->stats.rx_evm_percentage[ij] * - (RX_SMOOTH - 1)) + - (prev_st->RxMIMOSignalQuality[ij])) / - (RX_SMOOTH); - } - } - } - } -} - -static void _rtl92e_translate_rx_signal_stats(struct net_device *dev, - struct sk_buff *skb, - struct rtllib_rx_stats *pstats, - struct rx_desc *pdesc, - struct rx_fwinfo *pdrvinfo) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - bool bpacket_match_bssid, bpacket_toself; - bool bPacketBeacon = false; - struct ieee80211_hdr_3addr *hdr; - bool bToSelfBA = false; - static struct rtllib_rx_stats previous_stats; - u16 fc, type; - u8 *tmp_buf; - u8 *praddr; - - tmp_buf = skb->data + pstats->rx_drv_info_size + pstats->rx_buf_shift; - - hdr = (struct ieee80211_hdr_3addr *)tmp_buf; - fc = le16_to_cpu(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - praddr = hdr->addr1; - - bpacket_match_bssid = - ((type != RTLLIB_FTYPE_CTL) && - ether_addr_equal(priv->rtllib->current_network.bssid, - (fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : - (fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : - hdr->addr3) && - (!pstats->hw_error) && (!pstats->bCRC) && (!pstats->bICV)); - bpacket_toself = bpacket_match_bssid && /* check this */ - ether_addr_equal(praddr, priv->rtllib->dev->dev_addr); - if (ieee80211_is_beacon(hdr->frame_control)) - bPacketBeacon = true; - _rtl92e_process_phyinfo(priv, tmp_buf, &previous_stats, pstats); - _rtl92e_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, - &previous_stats, bpacket_match_bssid, - bpacket_toself, bPacketBeacon, bToSelfBA); - rtl92e_copy_mpdu_stats(pstats, &previous_stats); -} - -static void _rtl92e_update_received_rate_histogram_stats(struct net_device *dev, - struct rtllib_rx_stats *pstats) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - u32 rcvType = 1; - u32 rate_index; - - if (pstats->bCRC) - rcvType = 2; - else if (pstats->bICV) - rcvType = 3; - - switch (pstats->rate) { - case MGN_1M: - rate_index = 0; - break; - case MGN_2M: - rate_index = 1; - break; - case MGN_5_5M: - rate_index = 2; - break; - case MGN_11M: - rate_index = 3; - break; - case MGN_6M: - rate_index = 4; - break; - case MGN_9M: - rate_index = 5; - break; - case MGN_12M: - rate_index = 6; - break; - case MGN_18M: - rate_index = 7; - break; - case MGN_24M: - rate_index = 8; - break; - case MGN_36M: - rate_index = 9; - break; - case MGN_48M: - rate_index = 10; - break; - case MGN_54M: - rate_index = 11; - break; - case MGN_MCS0: - rate_index = 12; - break; - case MGN_MCS1: - rate_index = 13; - break; - case MGN_MCS2: - rate_index = 14; - break; - case MGN_MCS3: - rate_index = 15; - break; - case MGN_MCS4: - rate_index = 16; - break; - case MGN_MCS5: - rate_index = 17; - break; - case MGN_MCS6: - rate_index = 18; - break; - case MGN_MCS7: - rate_index = 19; - break; - case MGN_MCS8: - rate_index = 20; - break; - case MGN_MCS9: - rate_index = 21; - break; - case MGN_MCS10: - rate_index = 22; - break; - case MGN_MCS11: - rate_index = 23; - break; - case MGN_MCS12: - rate_index = 24; - break; - case MGN_MCS13: - rate_index = 25; - break; - case MGN_MCS14: - rate_index = 26; - break; - case MGN_MCS15: - rate_index = 27; - break; - default: - rate_index = 28; - break; - } - priv->stats.received_rate_histogram[0][rate_index]++; - priv->stats.received_rate_histogram[rcvType][rate_index]++; -} - -bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, - struct rx_desc *pdesc, struct sk_buff *skb) -{ - struct rx_fwinfo *pDrvInfo = NULL; - - stats->bICV = pdesc->ICV; - stats->bCRC = pdesc->CRC32; - stats->hw_error = pdesc->CRC32 | pdesc->ICV; - - stats->Length = pdesc->Length; - if (stats->Length < 24) - stats->hw_error |= 1; - - if (stats->hw_error) - return false; - - stats->rx_drv_info_size = pdesc->rx_drv_info_size; - stats->rx_buf_shift = (pdesc->Shift) & 0x03; - stats->decrypted = !pdesc->SWDec; - - pDrvInfo = (struct rx_fwinfo *)(skb->data + stats->rx_buf_shift); - - stats->rate = _rtl92e_rate_hw_to_mgn((bool)pDrvInfo->RxHT, - pDrvInfo->RxRate); - - _rtl92e_update_received_rate_histogram_stats(dev, stats); - - stats->bIsAMPDU = (pDrvInfo->PartAggr == 1); - stats->bFirstMPDU = (pDrvInfo->PartAggr == 1) && - (pDrvInfo->FirstAGGR == 1); - - stats->time_stamp_low = pDrvInfo->TSFL; - stats->time_stamp_high = rtl92e_readl(dev, TSFR + 4); - - _rtl92e_translate_rx_signal_stats(dev, skb, stats, pdesc, pDrvInfo); - skb_trim(skb, skb->len - S_CRC_LEN); - - return true; -} - -void rtl92e_stop_adapter(struct net_device *dev, bool reset) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int i; - u8 op_mode; - u8 u1bTmp; - u32 ulRegRead; - - op_mode = RT_OP_MODE_NO_LINK; - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_MEDIA_STATUS, &op_mode); - - if (!priv->rtllib->bSupportRemoteWakeUp) { - u1bTmp = 0x0; - rtl92e_writeb(dev, CMDR, u1bTmp); - } - - mdelay(20); - - if (!reset) { - mdelay(150); - - priv->hw_rf_off_action = 2; - - if (!priv->rtllib->bSupportRemoteWakeUp) { - rtl92e_set_rf_off(dev); - ulRegRead = rtl92e_readl(dev, CPU_GEN); - ulRegRead |= CPU_GEN_SYSTEM_RESET; - rtl92e_writel(dev, CPU_GEN, ulRegRead); - } else { - rtl92e_writel(dev, WFCRC0, 0xffffffff); - rtl92e_writel(dev, WFCRC1, 0xffffffff); - rtl92e_writel(dev, WFCRC2, 0xffffffff); - - rtl92e_writeb(dev, PMR, 0x5); - rtl92e_writeb(dev, MAC_BLK_CTRL, 0xa); - } - } - - for (i = 0; i < MAX_QUEUE_SIZE; i++) - skb_queue_purge(&priv->rtllib->skb_waitq[i]); - - skb_queue_purge(&priv->skb_queue); -} - -void rtl92e_update_ratr_table(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - u8 *pMcsRate = ieee->dot11ht_oper_rate_set; - u32 ratr_value = 0; - u16 rate_config = 0; - u8 rate_index = 0; - - rtl92e_config_rate(dev, &rate_config); - ratr_value = rate_config | *pMcsRate << 12; - switch (ieee->mode) { - case WIRELESS_MODE_B: - ratr_value &= 0x0000000F; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_G | WIRELESS_MODE_B: - ratr_value &= 0x00000FF7; - break; - case WIRELESS_MODE_N_24G: - ratr_value &= 0x000FF007; - break; - default: - break; - } - ratr_value &= 0x0FFFFFFF; - if (ieee->ht_info->cur_tx_bw40mhz && - ieee->ht_info->cur_short_gi_40mhz) - ratr_value |= 0x80000000; - else if (!ieee->ht_info->cur_tx_bw40mhz && - ieee->ht_info->cur_short_gi_20mhz) - ratr_value |= 0x80000000; - rtl92e_writel(dev, RATR0 + rate_index * 4, ratr_value); - rtl92e_writeb(dev, UFWP, 1); -} - -void -rtl92e_init_variables(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - strscpy(priv->nick, "rtl8192E", sizeof(priv->nick)); - - priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN | - IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | - IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE; - - priv->rtllib->tx_headroom = sizeof(struct tx_fwinfo_8190pci); - - priv->short_retry_limit = 0x30; - priv->long_retry_limit = 0x30; - - priv->receive_config = RCR_ADD3 | - RCR_AMF | RCR_ADF | - RCR_AICV | - RCR_AB | RCR_AM | RCR_APM | - RCR_AAP | ((u32)7 << RCR_MXDMA_OFFSET) | - ((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT; - - priv->irq_mask[0] = (u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK | - IMR_BEDOK | IMR_BKDOK | IMR_HCCADOK | - IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | - IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 | - IMR_RDU | IMR_RXFOVW | IMR_TXFOVW | - IMR_TBDOK | IMR_TBDER); - - priv->bfirst_after_down = false; -} - -void rtl92e_irq_enable(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - priv->irq_enabled = 1; - - rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]); -} - -void rtl92e_irq_disable(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - rtl92e_writel(dev, INTA_MASK, 0); - - priv->irq_enabled = 0; -} - -void rtl92e_enable_rx(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - rtl92e_writel(dev, RDQDA, priv->rx_ring_dma); -} - -static const u32 TX_DESC_BASE[] = { - BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA -}; - -void rtl92e_enable_tx(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - u32 i; - - for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) - rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma); -} - -void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta) -{ - *p_inta = rtl92e_readl(dev, ISR); - rtl92e_writel(dev, ISR, *p_inta); -} - -bool rtl92e_is_rx_stuck(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u16 RegRxCounter = rtl92e_readw(dev, 0x130); - bool bStuck = false; - static u8 rx_chk_cnt; - u32 slot_index = 0, TotalRxStuckCount = 0; - u8 i; - u8 SilentResetRxSoltNum = 4; - - rx_chk_cnt++; - if (priv->undecorated_smoothed_pwdb >= (RATE_ADAPTIVE_TH_HIGH + 5)) { - rx_chk_cnt = 0; - } else if ((priv->undecorated_smoothed_pwdb < (RATE_ADAPTIVE_TH_HIGH + 5)) && - (((priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) && - (priv->undecorated_smoothed_pwdb >= RATE_ADAPTIVE_TH_LOW_40M)) - || ((priv->current_chnl_bw == HT_CHANNEL_WIDTH_20) && - (priv->undecorated_smoothed_pwdb >= RATE_ADAPTIVE_TH_LOW_20M)))) { - if (rx_chk_cnt < 2) - return bStuck; - rx_chk_cnt = 0; - } else if ((((priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) && - (priv->undecorated_smoothed_pwdb < RATE_ADAPTIVE_TH_LOW_40M)) || - ((priv->current_chnl_bw == HT_CHANNEL_WIDTH_20) && - (priv->undecorated_smoothed_pwdb < RATE_ADAPTIVE_TH_LOW_20M))) && - priv->undecorated_smoothed_pwdb >= VERY_LOW_RSSI) { - if (rx_chk_cnt < 4) - return bStuck; - rx_chk_cnt = 0; - } else { - if (rx_chk_cnt < 8) - return bStuck; - rx_chk_cnt = 0; - } - - slot_index = (priv->silent_reset_rx_slot_index++) % SilentResetRxSoltNum; - - if (priv->rx_ctr == RegRxCounter) { - priv->silent_reset_rx_stuck_event[slot_index] = 1; - - for (i = 0; i < SilentResetRxSoltNum; i++) - TotalRxStuckCount += priv->silent_reset_rx_stuck_event[i]; - - if (TotalRxStuckCount == SilentResetRxSoltNum) { - bStuck = true; - for (i = 0; i < SilentResetRxSoltNum; i++) - TotalRxStuckCount += - priv->silent_reset_rx_stuck_event[i]; - } - } else { - priv->silent_reset_rx_stuck_event[slot_index] = 0; - } - - priv->rx_ctr = RegRxCounter; - - return bStuck; -} - -bool rtl92e_is_tx_stuck(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - bool bStuck = false; - u16 RegTxCounter = rtl92e_readw(dev, 0x128); - - if (priv->tx_counter == RegTxCounter) - bStuck = true; - - priv->tx_counter = RegTxCounter; - - return bStuck; -} - -bool rtl92e_get_nmode_support_by_sec(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - if (ieee->rtllib_ap_sec_type && - (ieee->rtllib_ap_sec_type(priv->rtllib) & (SEC_ALG_WEP | - SEC_ALG_TKIP))) { - return false; - } else { - return true; - } -} - -bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - return ieee->half_wireless_n24g_mode; -} diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h deleted file mode 100644 index 9d9c5051c7fe..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL8192E_H -#define _RTL8192E_H - -#include "r8190P_def.h" - -bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev); -bool rtl92e_get_nmode_support_by_sec(struct net_device *dev); -bool rtl92e_is_tx_stuck(struct net_device *dev); -bool rtl92e_is_rx_stuck(struct net_device *dev); -void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta); -void rtl92e_enable_rx(struct net_device *dev); -void rtl92e_enable_tx(struct net_device *dev); -void rtl92e_init_variables(struct net_device *dev); -void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val); -void rtl92e_get_eeprom_size(struct net_device *dev); -bool rtl92e_start_adapter(struct net_device *dev); -void rtl92e_link_change(struct net_device *dev); -void rtl92e_set_monitor_mode(struct net_device *dev, bool allow_all_da, - bool write_into_reg); -void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc, - struct cb_desc *cb_desc, struct sk_buff *skb); -void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry, - struct cb_desc *cb_desc, struct sk_buff *skb); -bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats, - struct rx_desc *pdesc, struct sk_buff *skb); -void rtl92e_stop_adapter(struct net_device *dev, bool reset); -void rtl92e_update_ratr_table(struct net_device *dev); -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c deleted file mode 100644 index ddf998cf2041..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_hw.h" -#include "table.h" -#include "r8192E_firmware.h" -#include "r8192E_cmdpkt.h" -#include <linux/firmware.h> - -static bool _rtl92e_wait_for_fw(struct net_device *dev, u32 mask, u32 timeout) -{ - unsigned long deadline = jiffies + msecs_to_jiffies(timeout); - - while (time_before(jiffies, deadline)) { - if (rtl92e_readl(dev, CPU_GEN) & mask) - return true; - mdelay(2); - } - return false; -} - -static bool _rtl92e_fw_boot_cpu(struct net_device *dev) -{ - u32 CPU_status = 0; - - if (!_rtl92e_wait_for_fw(dev, CPU_GEN_PUT_CODE_OK, 200)) { - netdev_err(dev, "Firmware download failed.\n"); - return false; - } - netdev_dbg(dev, "Download Firmware: Put code ok!\n"); - - CPU_status = rtl92e_readl(dev, CPU_GEN); - rtl92e_writeb(dev, CPU_GEN, (CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff); - mdelay(1); - - if (!_rtl92e_wait_for_fw(dev, CPU_GEN_BOOT_RDY, 200)) { - netdev_err(dev, "Firmware boot failed.\n"); - return false; - } - - netdev_dbg(dev, "Download Firmware: Boot ready!\n"); - - return true; -} - -static bool _rtl92e_fw_check_ready(struct net_device *dev, - u8 load_fw_status) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_firmware *pfirmware = priv->fw_info; - bool rt_status = true; - - switch (load_fw_status) { - case FW_INIT_STEP0_BOOT: - pfirmware->status = FW_STATUS_1_MOVE_BOOT_CODE; - break; - - case FW_INIT_STEP1_MAIN: - pfirmware->status = FW_STATUS_2_MOVE_MAIN_CODE; - - rt_status = _rtl92e_fw_boot_cpu(dev); - if (rt_status) - pfirmware->status = FW_STATUS_3_TURNON_CPU; - else - netdev_dbg(dev, "_rtl92e_fw_boot_cpu fail!\n"); - - break; - - case FW_INIT_STEP2_DATA: - pfirmware->status = FW_STATUS_4_MOVE_DATA_CODE; - mdelay(1); - - rt_status = _rtl92e_wait_for_fw(dev, CPU_GEN_FIRM_RDY, 20); - if (rt_status) - pfirmware->status = FW_STATUS_5_READY; - break; - default: - rt_status = false; - netdev_dbg(dev, "Unknown firmware status"); - break; - } - - return rt_status; -} - -static bool _rtl92e_fw_prepare(struct net_device *dev, struct rt_fw_blob *blob, - const char *name, u8 padding) -{ - const struct firmware *fw; - int rc, i; - bool ret = true; - - rc = request_firmware(&fw, name, &dev->dev); - if (rc < 0) - return false; - - if (round_up(fw->size, 4) > MAX_FW_SIZE - padding) { - netdev_err(dev, "Firmware image %s too big for the device.\n", - name); - ret = false; - goto out; - } - - if (padding) - memset(blob->data, 0, padding); - if (fw->size % 4) - memset(blob->data + padding + fw->size, 0, 4); - memcpy(blob->data + padding, fw->data, fw->size); - - blob->size = round_up(fw->size, 4) + padding; - - /* Swap endian - firmware is packaged in invalid endiannes*/ - for (i = padding; i < blob->size; i += 4) { - u32 *data = (u32 *)(blob->data + i); - *data = swab32p(data); - } -out: - release_firmware(fw); - return ret; -} - -bool rtl92e_init_fw(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - bool rt_status = true; - - u32 file_length = 0; - u8 *mapped_file = NULL; - u8 i = 0; - enum opt_rst_type rst_opt = OPT_SYSTEM_RESET; - enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT; - - struct rt_firmware *pfirmware = priv->fw_info; - - netdev_dbg(dev, " PlatformInitFirmware()==>\n"); - - if (pfirmware->status == FW_STATUS_0_INIT) { - rst_opt = OPT_SYSTEM_RESET; - starting_state = FW_INIT_STEP0_BOOT; - - } else if (pfirmware->status == FW_STATUS_5_READY) { - rst_opt = OPT_FIRMWARE_RESET; - starting_state = FW_INIT_STEP2_DATA; - } - - for (i = starting_state; i <= FW_INIT_STEP2_DATA; i++) { - if (rst_opt == OPT_SYSTEM_RESET) { - if (pfirmware->blobs[i].size == 0) { - const char *fw_name[3] = { - RTL8192E_BOOT_IMG_FW, - RTL8192E_MAIN_IMG_FW, - RTL8192E_DATA_IMG_FW - }; - int pad = 0; - - if (i == FW_INIT_STEP1_MAIN) - pad = 128; - - if (!_rtl92e_fw_prepare(dev, - &pfirmware->blobs[i], - fw_name[i], - pad)) - goto download_firmware_fail; - } - } - - mapped_file = pfirmware->blobs[i].data; - file_length = pfirmware->blobs[i].size; - - rt_status = rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_INIT, - mapped_file, file_length); - if (!rt_status) - goto download_firmware_fail; - - if (!_rtl92e_fw_check_ready(dev, i)) - goto download_firmware_fail; - } - - netdev_dbg(dev, "Firmware Download Success\n"); - return rt_status; - -download_firmware_fail: - netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__); - return false; -} diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h deleted file mode 100644 index b9059abc901b..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef __INC_FIRMWARE_H -#define __INC_FIRMWARE_H - -#define RTL8192E_BOOT_IMG_FW "RTL8192E/boot.img" -#define RTL8192E_MAIN_IMG_FW "RTL8192E/main.img" -#define RTL8192E_DATA_IMG_FW "RTL8192E/data.img" - -enum firmware_init_step { - FW_INIT_STEP0_BOOT = 0, - FW_INIT_STEP1_MAIN = 1, - FW_INIT_STEP2_DATA = 2, -}; - -enum opt_rst_type { - OPT_SYSTEM_RESET = 0, - OPT_FIRMWARE_RESET = 1, -}; - -enum desc_packet_type { - DESC_PACKET_TYPE_INIT = 0, - DESC_PACKET_TYPE_NORMAL = 1, -}; - -enum firmware_status { - FW_STATUS_0_INIT = 0, - FW_STATUS_1_MOVE_BOOT_CODE = 1, - FW_STATUS_2_MOVE_MAIN_CODE = 2, - FW_STATUS_3_TURNON_CPU = 3, - FW_STATUS_4_MOVE_DATA_CODE = 4, - FW_STATUS_5_READY = 5, -}; - -#define MAX_FW_SIZE 64000 -struct rt_fw_blob { - u16 size; - u8 data[MAX_FW_SIZE]; -}; - -#define FW_BLOBS 3 -struct rt_firmware { - enum firmware_status status; - struct rt_fw_blob blobs[FW_BLOBS]; -}; - -bool rtl92e_init_fw(struct net_device *dev); -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h deleted file mode 100644 index e507593b939c..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h +++ /dev/null @@ -1,244 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef R8180_HW -#define R8180_HW - -enum baseband_config { - BB_CONFIG_PHY_REG = 0, - BB_CONFIG_AGC_TAB = 1, -}; - -#define RTL8190_EEPROM_ID 0x8129 -#define EEPROM_VID 0x02 -#define EEPROM_DID 0x04 -#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C - -#define EEPROM_Default_ThermalMeter 0x77 -#define EEPROM_Default_AntTxPowerDiff 0x0 -#define EEPROM_Default_TxPwDiff_CrystalCap 0x5 -#define EEPROM_Default_TxPower 0x1010 -#define EEPROM_ICVersion_ChannelPlan 0x7C -#define EEPROM_Customer_ID 0x7B -#define EEPROM_RFInd_PowerDiff 0x28 - -#define EEPROM_ThermalMeter 0x29 -#define EEPROM_TxPwDiff_CrystalCap 0x2A -#define EEPROM_TxPwIndex_CCK 0x2C -#define EEPROM_TxPwIndex_OFDM_24G 0x3A - -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_NetCore 0x5 -enum _RTL8192PCI_HW { - MAC0 = 0x000, - MAC4 = 0x004, - PCIF = 0x009, -#define MXDMA2_NO_LIMIT 0x7 - -#define MXDMA2_RX_SHIFT 4 -#define MXDMA2_TX_SHIFT 0 - PMR = 0x00c, - EPROM_CMD = 0x00e, - -#define EPROM_CMD_9356SEL BIT(4) -#define EPROM_CMD_OPERATING_MODE_SHIFT 6 -#define EPROM_CMD_NORMAL 0 -#define EPROM_CMD_PROGRAM 2 -#define EPROM_CS_BIT 3 -#define EPROM_CK_BIT 2 -#define EPROM_W_BIT 1 -#define EPROM_R_BIT 0 - - ANAPAR = 0x17, -#define BB_GLOBAL_RESET_BIT 0x1 - BB_GLOBAL_RESET = 0x020, - BSSIDR = 0x02E, - CMDR = 0x037, -#define CR_RE 0x08 -#define CR_TE 0x04 - SIFS = 0x03E, - RCR = 0x044, -#define RCR_ONLYERLPKT BIT(31) -#define RCR_CBSSID BIT(23) -#define RCR_ADD3 BIT(21) -#define RCR_AMF BIT(20) -#define RCR_ADF BIT(18) -#define RCR_AICV BIT(12) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - SLOT_TIME = 0x049, - ACK_TIMEOUT = 0x04c, - EDCAPARA_BE = 0x050, - EDCAPARA_BK = 0x054, - EDCAPARA_VO = 0x058, - EDCAPARA_VI = 0x05C, -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - BCN_TCFG = 0x062, -#define BCN_TCFG_CW_SHIFT 8 -#define BCN_TCFG_IFS 0 - BCN_INTERVAL = 0x070, - ATIMWND = 0x072, - BCN_DRV_EARLY_INT = 0x074, - BCN_DMATIME = 0x076, - BCN_ERR_THRESH = 0x078, - RWCAM = 0x0A0, -#define TOTAL_CAM_ENTRY 32 - WCAMI = 0x0A4, - SECR = 0x0B0, -#define SCR_TxUseDK BIT(0) -#define SCR_RxUseDK BIT(1) -#define SCR_TxEncEnable BIT(2) -#define SCR_RxDecEnable BIT(3) -#define SCR_NoSKMC BIT(5) - SWREGULATOR = 0x0BD, - INTA_MASK = 0x0f4, -#define IMR_TBDOK BIT(27) -#define IMR_TBDER BIT(26) -#define IMR_TXFOVW BIT(15) -#define IMR_TIMEOUT0 BIT(14) -#define IMR_BcnInt BIT(13) -#define IMR_RXFOVW BIT(12) -#define IMR_RDU BIT(11) -#define IMR_RXCMDOK BIT(10) -#define IMR_BDOK BIT(9) -#define IMR_HIGHDOK BIT(8) -#define IMR_COMDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_HCCADOK BIT(5) -#define IMR_BKDOK BIT(4) -#define IMR_BEDOK BIT(3) -#define IMR_VIDOK BIT(2) -#define IMR_VODOK BIT(1) -#define IMR_ROK BIT(0) - ISR = 0x0f8, - TP_POLL = 0x0fd, -#define TP_POLL_CQ BIT(5) - PSR = 0x0ff, - CPU_GEN = 0x100, -#define CPU_CCK_LOOPBACK 0x00030000 -#define CPU_GEN_SYSTEM_RESET 0x00000001 -#define CPU_GEN_FIRMWARE_RESET 0x00000008 -#define CPU_GEN_BOOT_RDY 0x00000010 -#define CPU_GEN_FIRM_RDY 0x00000020 -#define CPU_GEN_PUT_CODE_OK 0x00000080 -#define CPU_GEN_BB_RST 0x00000100 -#define CPU_GEN_PWR_STB_CPU 0x00000004 -#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF -#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 - ACM_HW_CTRL = 0x171, -#define ACM_HW_BEQ_EN BIT(1) -#define ACM_HW_VIQ_EN BIT(2) -#define ACM_HW_VOQ_EN BIT(3) - RQPN1 = 0x180, - RQPN2 = 0x184, - RQPN3 = 0x188, - QPNR = 0x1F0, - BQDA = 0x200, - HQDA = 0x204, - CQDA = 0x208, - MQDA = 0x20C, - HCCAQDA = 0x210, - VOQDA = 0x214, - VIQDA = 0x218, - BEQDA = 0x21C, - BKQDA = 0x220, - RDQDA = 0x228, - - WFCRC0 = 0x2f0, - WFCRC1 = 0x2f4, - WFCRC2 = 0x2f8, - - BW_OPMODE = 0x300, -#define BW_OPMODE_20MHZ BIT(2) - IC_VERRSION = 0x301, - MSR = 0x303, -#define MSR_LINK_MASK (BIT(1) | BIT(0)) -#define MSR_LINK_MANAGED 2 -#define MSR_LINK_ADHOC 1 -#define MSR_LINK_MASTER 3 - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - - RETRY_LIMIT = 0x304, -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - TSFR = 0x308, - RRSR = 0x310, -#define RRSR_SHORT_OFFSET 23 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define BRSR_AckShortPmb BIT(23) - UFWP = 0x318, - RATR0 = 0x320, -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ - RATR_MCS14 | RATR_MCS15) - - DRIVER_RSSI = 0x32c, - MCS_TXAGC = 0x340, - CCK_TXAGC = 0x348, - MAC_BLK_CTRL = 0x403, -}; - -#define GPI 0x108 - -#define ANAPAR_FOR_8192PCIE 0x17 - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c deleted file mode 100644 index fbe624e235df..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c +++ /dev/null @@ -1,1110 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include <linux/bitops.h> -#include "rtl_core.h" -#include "r8192E_hw.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" -#include "r8192E_phy.h" -#include "rtl_dm.h" - -#include "table.h" - -/*************************Define local function prototype**********************/ - -static u32 _rtl92e_phy_rf_fw_read(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset); -static void _rtl92e_phy_rf_fw_write(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset, - u32 Data); - -static u32 _rtl92e_calculate_bit_shift(u32 dwBitMask) -{ - if (!dwBitMask) - return 32; - return ffs(dwBitMask) - 1; -} - -void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask, - u32 dwData) -{ - u32 OriginalValue, BitShift, NewValue; - - if (dwBitMask != bMaskDWord) { - OriginalValue = rtl92e_readl(dev, dwRegAddr); - BitShift = _rtl92e_calculate_bit_shift(dwBitMask); - NewValue = (OriginalValue & ~dwBitMask) | (dwData << BitShift); - rtl92e_writel(dev, dwRegAddr, NewValue); - } else { - rtl92e_writel(dev, dwRegAddr, dwData); - } -} - -u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask) -{ - u32 OriginalValue, BitShift; - - OriginalValue = rtl92e_readl(dev, dwRegAddr); - BitShift = _rtl92e_calculate_bit_shift(dwBitMask); - - return (OriginalValue & dwBitMask) >> BitShift; -} - -static u32 _rtl92e_phy_rf_read(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 ret = 0; - u32 NewOffset = 0; - struct bb_reg_definition *pPhyReg = &priv->phy_reg_def[eRFPath]; - - Offset &= 0x3f; - - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); - if (Offset >= 31) { - priv->rf_reg_0value[eRFPath] |= 0x140; - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - NewOffset = Offset - 30; - } else if (Offset >= 16) { - priv->rf_reg_0value[eRFPath] |= 0x100; - priv->rf_reg_0value[eRFPath] &= (~0x40); - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - NewOffset = Offset - 15; - } else { - NewOffset = Offset; - } - rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, - NewOffset); - rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0); - rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1); - - mdelay(1); - - ret = rtl92e_get_bb_reg(dev, pPhyReg->rfLSSIReadBack, - bLSSIReadBackData); - - priv->rf_reg_0value[eRFPath] &= 0xebf; - - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); - - return ret; -} - -static void _rtl92e_phy_rf_write(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset, - u32 Data) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 DataAndAddr = 0, NewOffset = 0; - struct bb_reg_definition *pPhyReg = &priv->phy_reg_def[eRFPath]; - - Offset &= 0x3f; - - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); - - if (Offset >= 31) { - priv->rf_reg_0value[eRFPath] |= 0x140; - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - NewOffset = Offset - 30; - } else if (Offset >= 16) { - priv->rf_reg_0value[eRFPath] |= 0x100; - priv->rf_reg_0value[eRFPath] &= (~0x40); - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - NewOffset = Offset - 15; - } else { - NewOffset = Offset; - } - - DataAndAddr = (NewOffset & 0x3f) | (Data << 16); - - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); - - if (Offset == 0x0) - priv->rf_reg_0value[eRFPath] = Data; - - if (Offset != 0) { - priv->rf_reg_0value[eRFPath] &= 0xebf; - rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, - bMaskDWord, - (priv->rf_reg_0value[eRFPath] << 16)); - } - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3); -} - -void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask, u32 Data) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 Original_Value, BitShift, New_Value; - - if (priv->rtllib->rf_power_state != rf_on && !priv->being_init_adapter) - return; - - if (priv->rf_mode == RF_OP_By_FW) { - if (BitMask != bMask12Bits) { - Original_Value = _rtl92e_phy_rf_fw_read(dev, eRFPath, - RegAddr); - BitShift = _rtl92e_calculate_bit_shift(BitMask); - New_Value = (Original_Value & ~BitMask) | (Data << BitShift); - - _rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr, - New_Value); - } else { - _rtl92e_phy_rf_fw_write(dev, eRFPath, RegAddr, Data); - } - udelay(200); - } else { - if (BitMask != bMask12Bits) { - Original_Value = _rtl92e_phy_rf_read(dev, eRFPath, - RegAddr); - BitShift = _rtl92e_calculate_bit_shift(BitMask); - New_Value = (Original_Value & ~BitMask) | (Data << BitShift); - - _rtl92e_phy_rf_write(dev, eRFPath, RegAddr, New_Value); - } else { - _rtl92e_phy_rf_write(dev, eRFPath, RegAddr, Data); - } - } -} - -u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask) -{ - u32 Original_Value, Readback_Value, BitShift; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->rtllib->rf_power_state != rf_on && !priv->being_init_adapter) - return 0; - mutex_lock(&priv->rf_mutex); - if (priv->rf_mode == RF_OP_By_FW) { - Original_Value = _rtl92e_phy_rf_fw_read(dev, eRFPath, RegAddr); - udelay(200); - } else { - Original_Value = _rtl92e_phy_rf_read(dev, eRFPath, RegAddr); - } - BitShift = _rtl92e_calculate_bit_shift(BitMask); - Readback_Value = (Original_Value & BitMask) >> BitShift; - mutex_unlock(&priv->rf_mutex); - return Readback_Value; -} - -static u32 _rtl92e_phy_rf_fw_read(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset) -{ - u32 Data = 0; - u8 time = 0; - - Data |= ((Offset & 0xFF) << 12); - Data |= ((eRFPath & 0x3) << 20); - Data |= 0x80000000; - while (rtl92e_readl(dev, QPNR) & 0x80000000) { - if (time++ < 100) - udelay(10); - else - break; - } - rtl92e_writel(dev, QPNR, Data); - while (rtl92e_readl(dev, QPNR) & 0x80000000) { - if (time++ < 100) - udelay(10); - else - return 0; - } - return rtl92e_readl(dev, RF_DATA); -} - -static void _rtl92e_phy_rf_fw_write(struct net_device *dev, - enum rf90_radio_path eRFPath, u32 Offset, - u32 Data) -{ - u8 time = 0; - - Data |= ((Offset & 0xFF) << 12); - Data |= ((eRFPath & 0x3) << 20); - Data |= 0x400000; - Data |= 0x80000000; - - while (rtl92e_readl(dev, QPNR) & 0x80000000) { - if (time++ < 100) - udelay(10); - else - break; - } - rtl92e_writel(dev, QPNR, Data); -} - -void rtl92e_config_mac(struct net_device *dev) -{ - u32 dwArrayLen = 0, i = 0; - u32 *pdwArray = NULL; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->tx_pwr_data_read_from_eeprom) { - dwArrayLen = RTL8192E_MACPHY_ARR_PG_LEN; - pdwArray = RTL8192E_MACPHY_ARR_PG; - - } else { - dwArrayLen = RTL8192E_MACPHY_ARR_LEN; - pdwArray = RTL8192E_MACPHY_ARR; - } - for (i = 0; i < dwArrayLen; i += 3) { - if (pdwArray[i] == 0x318) - pdwArray[i + 2] = 0x00000800; - rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i + 1], - pdwArray[i + 2]); - } -} - -static void _rtl92e_phy_config_bb(struct net_device *dev, u8 ConfigType) -{ - int i; - u32 *Rtl819XPHY_REGArray_Table = NULL; - u32 *Rtl819XAGCTAB_Array_Table = NULL; - u16 AGCTAB_ArrayLen, PHY_REGArrayLen = 0; - - AGCTAB_ArrayLen = RTL8192E_AGCTAB_ARR_LEN; - Rtl819XAGCTAB_Array_Table = RTL8192E_AGCTAB_ARR; - PHY_REGArrayLen = RTL8192E_PHY_REG_1T2R_ARR_LEN; - Rtl819XPHY_REGArray_Table = RTL8192E_PHY_REG_1T2R_ARR; - - if (ConfigType == BB_CONFIG_PHY_REG) { - for (i = 0; i < PHY_REGArrayLen; i += 2) { - rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i], - bMaskDWord, - Rtl819XPHY_REGArray_Table[i + 1]); - } - } else if (ConfigType == BB_CONFIG_AGC_TAB) { - for (i = 0; i < AGCTAB_ArrayLen; i += 2) { - rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i], - bMaskDWord, - Rtl819XAGCTAB_Array_Table[i + 1]); - } - } -} - -static void _rtl92e_init_bb_rf_reg_def(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->phy_reg_def[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; - priv->phy_reg_def[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; - - priv->phy_reg_def[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; - priv->phy_reg_def[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; - - priv->phy_reg_def[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; - priv->phy_reg_def[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; - - priv->phy_reg_def[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; - priv->phy_reg_def[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; - - priv->phy_reg_def[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; - priv->phy_reg_def[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; - - priv->phy_reg_def[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; - priv->phy_reg_def[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; -} - -bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock, - enum rf90_radio_path eRFPath) -{ - bool ret = true; - u32 i, CheckTimes = 4, dwRegRead = 0; - u32 WriteAddr[4]; - u32 WriteData[] = {0xfffff027, 0xaa55a02f, 0x00000027, 0x55aa502f}; - - WriteAddr[HW90_BLOCK_MAC] = 0x100; - WriteAddr[HW90_BLOCK_PHY0] = 0x900; - WriteAddr[HW90_BLOCK_PHY1] = 0x800; - WriteAddr[HW90_BLOCK_RF] = 0x3; - - if (CheckBlock == HW90_BLOCK_MAC) { - netdev_warn(dev, "%s(): No checks available for MAC block.\n", - __func__); - return ret; - } - - for (i = 0; i < CheckTimes; i++) { - switch (CheckBlock) { - case HW90_BLOCK_PHY0: - case HW90_BLOCK_PHY1: - rtl92e_writel(dev, WriteAddr[CheckBlock], - WriteData[i]); - dwRegRead = rtl92e_readl(dev, WriteAddr[CheckBlock]); - break; - - case HW90_BLOCK_RF: - WriteData[i] &= 0xfff; - rtl92e_set_rf_reg(dev, eRFPath, - WriteAddr[HW90_BLOCK_RF], - bMask12Bits, WriteData[i]); - mdelay(10); - dwRegRead = rtl92e_get_rf_reg(dev, eRFPath, - WriteAddr[HW90_BLOCK_RF], - bMaskDWord); - mdelay(10); - break; - - default: - ret = false; - break; - } - - if (dwRegRead != WriteData[i]) { - netdev_warn(dev, "%s(): Check failed.\n", __func__); - ret = false; - break; - } - } - - return ret; -} - -static bool _rtl92e_bb_config_para_file(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - bool rtStatus = true; - u8 bRegValue = 0, eCheckItem = 0; - u32 dwRegValue = 0; - - bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET); - rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue | BB_GLOBAL_RESET_BIT)); - - dwRegValue = rtl92e_readl(dev, CPU_GEN); - rtl92e_writel(dev, CPU_GEN, (dwRegValue & (~CPU_GEN_BB_RST))); - - for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0; - eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) { - rtStatus = rtl92e_check_bb_and_rf(dev, - (enum hw90_block)eCheckItem, - (enum rf90_radio_path)0); - if (!rtStatus) - return rtStatus; - } - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn | bOFDMEn, 0x0); - _rtl92e_phy_config_bb(dev, BB_CONFIG_PHY_REG); - - dwRegValue = rtl92e_readl(dev, CPU_GEN); - rtl92e_writel(dev, CPU_GEN, (dwRegValue | CPU_GEN_BB_RST)); - - _rtl92e_phy_config_bb(dev, BB_CONFIG_AGC_TAB); - - if (priv->ic_cut > VERSION_8190_BD) { - dwRegValue = 0x0; - rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage, - (bXBTxAGC | bXCTxAGC | bXDTxAGC), dwRegValue); - - dwRegValue = priv->crystal_cap; - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, - dwRegValue); - } - - return rtStatus; -} - -bool rtl92e_config_bb(struct net_device *dev) -{ - _rtl92e_init_bb_rf_reg_def(dev); - return _rtl92e_bb_config_para_file(dev); -} - -void rtl92e_get_tx_power(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->mcs_tx_pwr_level_org_offset[0] = - rtl92e_readl(dev, rTxAGC_Rate18_06); - priv->mcs_tx_pwr_level_org_offset[1] = - rtl92e_readl(dev, rTxAGC_Rate54_24); - priv->mcs_tx_pwr_level_org_offset[2] = - rtl92e_readl(dev, rTxAGC_Mcs03_Mcs00); - priv->mcs_tx_pwr_level_org_offset[3] = - rtl92e_readl(dev, rTxAGC_Mcs07_Mcs04); - priv->mcs_tx_pwr_level_org_offset[4] = - rtl92e_readl(dev, rTxAGC_Mcs11_Mcs08); - priv->mcs_tx_pwr_level_org_offset[5] = - rtl92e_readl(dev, rTxAGC_Mcs15_Mcs12); - - priv->def_initial_gain[0] = rtl92e_readb(dev, rOFDM0_XAAGCCore1); - priv->def_initial_gain[1] = rtl92e_readb(dev, rOFDM0_XBAGCCore1); - priv->def_initial_gain[2] = rtl92e_readb(dev, rOFDM0_XCAGCCore1); - priv->def_initial_gain[3] = rtl92e_readb(dev, rOFDM0_XDAGCCore1); - - priv->framesync = rtl92e_readb(dev, rOFDM0_RxDetector3); -} - -void rtl92e_set_tx_power(struct net_device *dev, u8 channel) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 powerlevel = 0, powerlevelOFDM24G = 0; - - if (priv->epromtype == EEPROM_93C46) { - powerlevel = priv->tx_pwr_level_cck[channel - 1]; - powerlevelOFDM24G = priv->tx_pwr_level_ofdm_24g[channel - 1]; - } - - rtl92e_set_cck_tx_power(dev, powerlevel); - rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G); -} - -u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath) -{ - int i; - - switch (eRFPath) { - case RF90_PATH_A: - for (i = 0; i < RTL8192E_RADIO_A_ARR_LEN; i += 2) { - if (RTL8192E_RADIO_A_ARR[i] == 0xfe) { - msleep(100); - continue; - } - rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_A_ARR[i], - bMask12Bits, - RTL8192E_RADIO_A_ARR[i + 1]); - } - break; - case RF90_PATH_B: - for (i = 0; i < RTL8192E_RADIO_B_ARR_LEN; i += 2) { - if (RTL8192E_RADIO_B_ARR[i] == 0xfe) { - msleep(100); - continue; - } - rtl92e_set_rf_reg(dev, eRFPath, RTL8192E_RADIO_B_ARR[i], - bMask12Bits, - RTL8192E_RADIO_B_ARR[i + 1]); - } - break; - default: - break; - } - - return 0; -} - -static void _rtl92e_set_tx_power_level(struct net_device *dev, u8 channel) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 powerlevel = priv->tx_pwr_level_cck[channel - 1]; - u8 powerlevelOFDM24G = priv->tx_pwr_level_ofdm_24g[channel - 1]; - - rtl92e_set_cck_tx_power(dev, powerlevel); - rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G); -} - -static u8 _rtl92e_phy_set_sw_chnl_cmd_array(struct net_device *dev, - struct sw_chnl_cmd *CmdTable, - u32 CmdTableIdx, u32 CmdTableSz, - enum sw_chnl_cmd_id cmd_id, - u32 para1, u32 para2, u32 ms_delay) -{ - struct sw_chnl_cmd *pCmd; - - if (!CmdTable) { - netdev_err(dev, "%s(): CmdTable cannot be NULL.\n", __func__); - return false; - } - if (CmdTableIdx >= CmdTableSz) { - netdev_err(dev, "%s(): Invalid index requested.\n", __func__); - return false; - } - - pCmd = CmdTable + CmdTableIdx; - pCmd->cmd_id = cmd_id; - pCmd->para1 = para1; - pCmd->para2 = para2; - pCmd->ms_delay = ms_delay; - - return true; -} - -static u8 _rtl92e_phy_switch_channel_step(struct net_device *dev, u8 channel, - u8 *stage, u8 *step, u32 *delay) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - u32 PreCommonCmdCnt; - u32 PostCommonCmdCnt; - u32 RfDependCmdCnt; - struct sw_chnl_cmd *CurrentCmd = NULL; - u8 eRFPath; - - if (!rtllib_legal_channel(priv->rtllib, channel)) { - netdev_err(dev, "Invalid channel requested: %d\n", channel); - return true; - } - - { - PreCommonCmdCnt = 0; - _rtl92e_phy_set_sw_chnl_cmd_array(dev, ieee->PreCommonCmd, - PreCommonCmdCnt++, - MAX_PRECMD_CNT, - cmd_id_set_tx_power_level, - 0, 0, 0); - _rtl92e_phy_set_sw_chnl_cmd_array(dev, ieee->PreCommonCmd, - PreCommonCmdCnt++, - MAX_PRECMD_CNT, cmd_id_end, - 0, 0, 0); - - PostCommonCmdCnt = 0; - - _rtl92e_phy_set_sw_chnl_cmd_array(dev, ieee->PostCommonCmd, - PostCommonCmdCnt++, - MAX_POSTCMD_CNT, cmd_id_end, - 0, 0, 0); - - RfDependCmdCnt = 0; - - if (!(channel >= 1 && channel <= 14)) { - netdev_err(dev, - "Invalid channel requested for 8256: %d\n", - channel); - return false; - } - _rtl92e_phy_set_sw_chnl_cmd_array(dev, - ieee->RfDependCmd, - RfDependCmdCnt++, - MAX_RFDEPENDCMD_CNT, - cmd_id_rf_write_reg, - rZebra1_Channel, - channel, 10); - _rtl92e_phy_set_sw_chnl_cmd_array(dev, - ieee->RfDependCmd, - RfDependCmdCnt++, - MAX_RFDEPENDCMD_CNT, - cmd_id_end, 0, 0, 0); - - do { - switch (*stage) { - case 0: - CurrentCmd = &ieee->PreCommonCmd[*step]; - break; - case 1: - CurrentCmd = &ieee->RfDependCmd[*step]; - break; - case 2: - CurrentCmd = &ieee->PostCommonCmd[*step]; - break; - } - - if (CurrentCmd && CurrentCmd->cmd_id == cmd_id_end) { - if ((*stage) == 2) - return true; - (*stage)++; - (*step) = 0; - continue; - } - - if (!CurrentCmd) - continue; - switch (CurrentCmd->cmd_id) { - case cmd_id_set_tx_power_level: - if (priv->ic_cut > VERSION_8190_BD) - _rtl92e_set_tx_power_level(dev, - channel); - break; - case cmd_id_write_port_ulong: - rtl92e_writel(dev, CurrentCmd->para1, - CurrentCmd->para2); - break; - case cmd_id_write_port_ushort: - rtl92e_writew(dev, CurrentCmd->para1, - CurrentCmd->para2); - break; - case cmd_id_write_port_uchar: - rtl92e_writeb(dev, CurrentCmd->para1, - CurrentCmd->para2); - break; - case cmd_id_rf_write_reg: - for (eRFPath = 0; eRFPath < - priv->num_total_rf_path; eRFPath++) - rtl92e_set_rf_reg(dev, - (enum rf90_radio_path)eRFPath, - CurrentCmd->para1, bMask12Bits, - CurrentCmd->para2 << 7); - break; - default: - break; - } - - break; - } while (true); - } /*for (Number of RF paths)*/ - - (*delay) = CurrentCmd->ms_delay; - (*step)++; - return false; -} - -static void _rtl92e_phy_switch_channel(struct net_device *dev, u8 channel) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 delay = 0; - - while (!_rtl92e_phy_switch_channel_step(dev, channel, - &priv->sw_chnl_stage, - &priv->sw_chnl_step, &delay)) { - if (delay > 0) - msleep(delay); - if (!priv->up) - break; - } -} - -static void _rtl92e_phy_switch_channel_work_item(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - _rtl92e_phy_switch_channel(dev, priv->chan); -} - -void rtl92e_set_channel(struct net_device *dev, u8 channel) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (!priv->up) { - netdev_err(dev, "%s(): Driver is not initialized\n", __func__); - return; - } - if (priv->sw_chnl_in_progress) - return; - - switch (priv->rtllib->mode) { - case WIRELESS_MODE_B: - if (channel > 14) { - netdev_warn(dev, - "Channel %d not available in 802.11b.\n", - channel); - return; - } - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - if (channel > 14) { - netdev_warn(dev, - "Channel %d not available in 802.11g.\n", - channel); - return; - } - break; - } - - priv->sw_chnl_in_progress = true; - if (channel == 0) - channel = 1; - - priv->chan = channel; - - priv->sw_chnl_stage = 0; - priv->sw_chnl_step = 0; - - if (priv->up) - _rtl92e_phy_switch_channel_work_item(dev); - priv->sw_chnl_in_progress = false; -} - -static void _rtl92e_cck_tx_power_track_bw_switch_tssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - switch (priv->current_chnl_bw) { - case HT_CHANNEL_WIDTH_20: - priv->cck_present_attn = - priv->cck_present_attn_20m_def + - priv->cck_present_attn_diff; - - if (priv->cck_present_attn > - (CCK_TX_BB_GAIN_TABLE_LEN - 1)) - priv->cck_present_attn = - CCK_TX_BB_GAIN_TABLE_LEN - 1; - if (priv->cck_present_attn < 0) - priv->cck_present_attn = 0; - - if (priv->rtllib->current_network.channel == 14 && - !priv->bcck_in_ch14) { - priv->bcck_in_ch14 = true; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else if (priv->rtllib->current_network.channel != - 14 && priv->bcck_in_ch14) { - priv->bcck_in_ch14 = false; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else { - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } - break; - - case HT_CHANNEL_WIDTH_20_40: - priv->cck_present_attn = - priv->cck_present_attn_40m_def + - priv->cck_present_attn_diff; - - if (priv->cck_present_attn > - (CCK_TX_BB_GAIN_TABLE_LEN - 1)) - priv->cck_present_attn = - CCK_TX_BB_GAIN_TABLE_LEN - 1; - if (priv->cck_present_attn < 0) - priv->cck_present_attn = 0; - - if (priv->rtllib->current_network.channel == 14 && - !priv->bcck_in_ch14) { - priv->bcck_in_ch14 = true; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else if (priv->rtllib->current_network.channel != 14 - && priv->bcck_in_ch14) { - priv->bcck_in_ch14 = false; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else { - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } - break; - } -} - -static void _rtl92e_cck_tx_power_track_bw_switch_thermal(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->rtllib->current_network.channel == 14 && - !priv->bcck_in_ch14) - priv->bcck_in_ch14 = true; - else if (priv->rtllib->current_network.channel != 14 && - priv->bcck_in_ch14) - priv->bcck_in_ch14 = false; - - switch (priv->current_chnl_bw) { - case HT_CHANNEL_WIDTH_20: - if (priv->rec_cck_20m_idx == 0) - priv->rec_cck_20m_idx = 6; - priv->cck_index = priv->rec_cck_20m_idx; - break; - - case HT_CHANNEL_WIDTH_20_40: - priv->cck_index = priv->rec_cck_40m_idx; - break; - } - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); -} - -static void _rtl92e_cck_tx_power_track_bw_switch(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->ic_cut >= IC_VersionCut_D) - _rtl92e_cck_tx_power_track_bw_switch_tssi(dev); - else - _rtl92e_cck_tx_power_track_bw_switch_thermal(dev); -} - -static void _rtl92e_set_bw_mode_work_item(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 regBwOpMode; - - if (!priv->up) { - netdev_err(dev, "%s(): Driver is not initialized\n", __func__); - return; - } - regBwOpMode = rtl92e_readb(dev, BW_OPMODE); - - switch (priv->current_chnl_bw) { - case HT_CHANNEL_WIDTH_20: - regBwOpMode |= BW_OPMODE_20MHZ; - rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); - break; - - case HT_CHANNEL_WIDTH_20_40: - regBwOpMode &= ~BW_OPMODE_20MHZ; - rtl92e_writeb(dev, BW_OPMODE, regBwOpMode); - break; - - default: - netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__, - priv->current_chnl_bw); - break; - } - - switch (priv->current_chnl_bw) { - case HT_CHANNEL_WIDTH_20: - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x0); - rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x0); - - if (!priv->btxpower_tracking) { - rtl92e_writel(dev, rCCK0_TxFilter1, 0x1a1b0000); - rtl92e_writel(dev, rCCK0_TxFilter2, 0x090e1317); - rtl92e_writel(dev, rCCK0_DebugPort, 0x00000204); - } else { - _rtl92e_cck_tx_power_track_bw_switch(dev); - } - - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1); - - break; - case HT_CHANNEL_WIDTH_20_40: - rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x1); - rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x1); - - if (!priv->btxpower_tracking) { - rtl92e_writel(dev, rCCK0_TxFilter1, 0x35360000); - rtl92e_writel(dev, rCCK0_TxFilter2, 0x121c252e); - rtl92e_writel(dev, rCCK0_DebugPort, 0x00000409); - } else { - _rtl92e_cck_tx_power_track_bw_switch(dev); - } - - rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand, - (priv->n_cur_40mhz_prime_sc >> 1)); - rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00, - priv->n_cur_40mhz_prime_sc); - - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0); - break; - default: - netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__, - priv->current_chnl_bw); - break; - } - - rtl92e_set_bandwidth(dev, priv->current_chnl_bw); - - atomic_dec(&(priv->rtllib->atm_swbw)); - priv->set_bw_mode_in_progress = false; -} - -void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->set_bw_mode_in_progress) - return; - - atomic_inc(&(priv->rtllib->atm_swbw)); - priv->set_bw_mode_in_progress = true; - - priv->current_chnl_bw = bandwidth; - - if (Offset == HT_EXTCHNL_OFFSET_LOWER) - priv->n_cur_40mhz_prime_sc = HAL_PRIME_CHNL_OFFSET_UPPER; - else if (Offset == HT_EXTCHNL_OFFSET_UPPER) - priv->n_cur_40mhz_prime_sc = HAL_PRIME_CHNL_OFFSET_LOWER; - else - priv->n_cur_40mhz_prime_sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - _rtl92e_set_bw_mode_work_item(dev); -} - -void rtl92e_init_gain(struct net_device *dev, u8 Operation) -{ -#define SCAN_RX_INITIAL_GAIN 0x17 -#define POWER_DETECTION_TH 0x08 - struct r8192_priv *priv = rtllib_priv(dev); - u32 BitMask; - u8 initial_gain; - - if (priv->up) { - switch (Operation) { - case IG_Backup: - initial_gain = SCAN_RX_INITIAL_GAIN; - BitMask = bMaskByte0; - priv->initgain_backup.xaagccore1 = - rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1, - BitMask); - priv->initgain_backup.xbagccore1 = - rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1, - BitMask); - priv->initgain_backup.xcagccore1 = - rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1, - BitMask); - priv->initgain_backup.xdagccore1 = - rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1, - BitMask); - BitMask = bMaskByte2; - priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev, - rCCK0_CCA, BitMask); - - rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain); - rtl92e_writeb(dev, 0xa0a, POWER_DETECTION_TH); - break; - case IG_Restore: - BitMask = 0x7f; - rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, BitMask, - (u32)priv->initgain_backup.xaagccore1); - rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, BitMask, - (u32)priv->initgain_backup.xbagccore1); - rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, BitMask, - (u32)priv->initgain_backup.xcagccore1); - rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, BitMask, - (u32)priv->initgain_backup.xdagccore1); - BitMask = bMaskByte2; - rtl92e_set_bb_reg(dev, rCCK0_CCA, BitMask, - (u32)priv->initgain_backup.cca); - - rtl92e_set_tx_power(dev, - priv->rtllib->current_network.channel); - break; - } - } -} - -void rtl92e_set_rf_off(struct net_device *dev) -{ - rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT(4), 0x0); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0); - rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0); - rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0); - rtl92e_writeb(dev, ANAPAR_FOR_8192PCIE, 0x07); -} - -static bool _rtl92e_set_rf_power_state(struct net_device *dev, - enum rt_rf_power_state rf_power_state) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - (&priv->rtllib->pwr_save_ctrl); - bool bResult = true; - u8 i = 0, QueueID = 0; - struct rtl8192_tx_ring *ring = NULL; - - if (priv->set_rf_pwr_state_in_progress) - return false; - priv->set_rf_pwr_state_in_progress = true; - - switch (rf_power_state) { - case rf_on: - if ((priv->rtllib->rf_power_state == rf_off) && - RT_IN_PS_LEVEL(psc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 InitilizeCount = 3; - - do { - InitilizeCount--; - rtstatus = rtl92e_enable_nic(dev); - } while (!rtstatus && (InitilizeCount > 0)); - if (!rtstatus) { - netdev_err(dev, - "%s(): Failed to initialize Adapter.\n", - __func__); - priv->set_rf_pwr_state_in_progress = false; - return false; - } - RT_CLEAR_PS_LEVEL(psc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - rtl92e_writeb(dev, ANAPAR, 0x37); - mdelay(1); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, - 0x4, 0x1); - priv->hw_rf_off_action = 0; - rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, - BIT(4), 0x1); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, - 0x300, 0x3); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, - 0x18, 0x3); - rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, - 0x3, 0x3); - rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, - 0x3, 0x3); - rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, - 0x60, 0x3); - } - break; - case rf_sleep: - if (priv->rtllib->rf_power_state == rf_off) - break; - for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) { - ring = &priv->tx_ring[QueueID]; - if (skb_queue_len(&ring->queue) == 0) { - QueueID++; - continue; - } else { - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) - break; - } - rtl92e_set_rf_off(dev); - break; - case rf_off: - for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) { - ring = &priv->tx_ring[QueueID]; - if (skb_queue_len(&ring->queue) == 0) { - QueueID++; - continue; - } else { - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) - break; - } - rtl92e_set_rf_off(dev); - break; - default: - bResult = false; - netdev_warn(dev, - "%s(): Unknown state requested: 0x%X.\n", - __func__, rf_power_state); - break; - } - - if (bResult) - priv->rtllib->rf_power_state = rf_power_state; - - priv->set_rf_pwr_state_in_progress = false; - return bResult; -} - -bool rtl92e_set_rf_power_state(struct net_device *dev, - enum rt_rf_power_state rf_power_state) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - bool bResult = false; - - if (rf_power_state == priv->rtllib->rf_power_state && - priv->hw_rf_off_action == 0) { - return bResult; - } - - bResult = _rtl92e_set_rf_power_state(dev, rf_power_state); - return bResult; -} - -void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->up) { - switch (Operation) { - case SCAN_OPT_BACKUP: - priv->rtllib->init_gain_handler(dev, IG_Backup); - break; - - case SCAN_OPT_RESTORE: - priv->rtllib->init_gain_handler(dev, IG_Restore); - break; - } - } -} diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h deleted file mode 100644 index 956dfbdd5b68..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _R819XU_PHY_H -#define _R819XU_PHY_H - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -enum hw90_block { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, -}; - -enum rf90_radio_path { - RF90_PATH_A = 0, - RF90_PATH_B = 1, - RF90_PATH_MAX -}; - -void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, - u32 dwBitMask, u32 dwData); -u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask); -void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask, u32 Data); -u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath, - u32 RegAddr, u32 BitMask); -void rtl92e_config_mac(struct net_device *dev); -bool rtl92e_check_bb_and_rf(struct net_device *dev, - enum hw90_block CheckBlock, - enum rf90_radio_path eRFPath); -bool rtl92e_config_bb(struct net_device *dev); -void rtl92e_get_tx_power(struct net_device *dev); -void rtl92e_set_tx_power(struct net_device *dev, u8 channel); -u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath); - -void rtl92e_set_channel(struct net_device *dev, u8 channel); -void rtl92e_set_bw_mode(struct net_device *dev, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset); -void rtl92e_init_gain(struct net_device *dev, u8 operation); - -void rtl92e_set_rf_off(struct net_device *dev); - -bool rtl92e_set_rf_power_state(struct net_device *dev, - enum rt_rf_power_state rf_power_state); - -void rtl92e_scan_op_backup(struct net_device *dev, u8 operation); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h deleted file mode 100644 index c48c56869c19..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h +++ /dev/null @@ -1,773 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _R819XU_PHYREG_H -#define _R819XU_PHYREG_H - -#define RF_DATA 0x1d4 - -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -#define MCS_TXAGC 0x340 -#define CCK_TXAGC 0x348 - -/* Mac block on/off control register */ -#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC */ -#define rFPGA0_TxInfo 0x804 -#define rFPGA0_PSDFunction 0x808 -#define rFPGA0_TxGainStage 0x80c -#define rFPGA0_RFTiming1 0x810 -#define rFPGA0_RFTiming2 0x814 -#define rFPGA0_XA_HSSIParameter2 0x824 -#define rFPGA0_XB_HSSIParameter2 0x82c -#define rFPGA0_XA_LSSIParameter 0x840 -#define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_RFWakeUpParameter 0x850 -#define rFPGA0_RFSleepUpParameter 0x854 -#define rFPGA0_XA_RFInterfaceOE 0x860 -#define rFPGA0_XB_RFInterfaceOE 0x864 -#define rFPGA0_XAB_RFInterfaceSW 0x870 -#define rFPGA0_AnalogParameter1 0x880 -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 -#define rFPGA0_AnalogParameter4 0x88c -#define rFPGA0_XA_LSSIReadBack 0x8a0 -#define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_PSDReport 0x8b4 - -/* Page 9 - RF mode & OFDM TxSC */ -#define rFPGA1_RFMOD 0x900 -#define rFPGA1_TxBlock 0x904 -#define rFPGA1_DebugSelect 0x908 -#define rFPGA1_TxInfo 0x90c - -#define rCCK0_System 0xa00 -#define rCCK0_AFESetting 0xa04 -#define rCCK0_CCA 0xa08 -/* AGC default value, saturation level */ -#define rCCK0_RxAGC1 0xa0c -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ -#define rCCK0_RxHP 0xa14 -/* Timing recovery & channel estimation threshold */ -#define rCCK0_DSPParameter1 0xa18 -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* Debug port and TX filter 3 */ -#define rCCK0_FalseAlarmReport 0xa2c -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 -#define rCCK0_FACounterLower 0xa5c -#define rCCK0_FACounterUpper 0xa58 - -#define rOFDM0_LSTF 0xc00 -#define rOFDM0_TRxPathEnable 0xc04 -#define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c -#define rOFDM0_RxDetector1 0xc30 /* PD, BW & SBD */ -#define rOFDM0_RxDetector2 0xc34 /* SBD */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync */ -/* PD, SBD, Frame Sync & Short-GI */ -#define rOFDM0_RxDetector4 0xc3c -#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 -#define rOFDM0_ECCAThreshold 0xc4c /* Energy CCA */ -#define rOFDM0_XAAGCCore1 0xc50 -#define rOFDM0_XBAGCCore1 0xc58 -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 -#define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c -#define rOFDM0_XATxIQImbalance 0xc80 -#define rOFDM0_XATxAFE 0xc84 -#define rOFDM0_XCTxIQImbalance 0xc90 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 - -#define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 -#define rOFDM1_CFO 0xd08 -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not supported */ -#define rOFDM_ShortCFOAB 0xdac -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - -#define rTxAGC_Rate18_06 0xe00 -#define rTxAGC_Rate54_24 0xe04 -#define rTxAGC_CCK_Mcs32 0xe08 -#define rTxAGC_Mcs03_Mcs00 0xe10 -#define rTxAGC_Mcs07_Mcs04 0xe14 -#define rTxAGC_Mcs11_Mcs08 0xe18 -#define rTxAGC_Mcs15_Mcs12 0xe1c - -#define rZebra1_HSSIEnable 0x0 -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 -#define rZebra1_TxGain 0x8 -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra 4 */ -#define rGlobalCtrl 0 -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - -/* Bit Mask - Page 1*/ -#define bBBResetB 0x100 -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 -/* Bit Mask - Page 8 */ -#define bRFMOD 0x1 -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 -#define bCCKEn 0x1000000 -#define bOFDMEn 0x2000000 -#define bOFDMRxADCPhase 0x10000 -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f -#define bXBTxAGC 0xf00 -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 -#define bPAStart 0xf0000000 -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -/* Bit Mask - rFPGA0_RFTiming2 */ -#define bPAEnd 0xf -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -/* Channel gain at continue TX. */ -#define b3WireDataLength 0x800 -#define b3WireAddressLength 0x400 -/* 3-wire total control */ -#define bRFSI_RFENV 0x10 -#define bLSSIReadAddress 0x3f000000 /* LSSI "read" address */ -#define bLSSIReadEdge 0x80000000 /* LSSI "read" edge signal */ -#define bLSSIReadBackData 0xfff - -#define bDA6Swing 0x380000 -#define bADClkPhase 0x4000000 -#define b80MClkDelay 0x18000000 -#define bAFEWatchDogEnable 0x20000000 -#define bXtalCap 0x0f000000 -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bIntDifClkEnable 0x400 -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 - -#define bCCKRxAGCFormat 0x200 - -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* Page 8 */ -#define bOFDMTxSC 0x30000000 -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -/* Reset debug page and also HWord, LWord */ -#define bDebugPage 0xfff -/* Reset debug page and LWord */ -#define bDebugItem 0xff -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* Page a */ -#define bCCKBBMode 0x3 -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 -#define bCCKSideBand 0x10 -#define bCCKScramble 0x8 -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -/* CCK Rx Initial gain polarity */ -#define bCCKRFExtend 0x20000000 -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -/* AGCSAmp_dly */ -#define bCCKRxRFSettle 0x1f -#define bCCKFixedRxAGC 0x8000 -/*#define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */ -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 - -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 - -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* Page c */ -#define bNumOfSTF 0x3 -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -/* The threshold for high power */ -#define bRSSI_H 0x7f0000 -/* The threshold for ant diversity */ -#define bRSSI_Gen 0x7f000000 -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -/*#define bRxMF_Hold 0x3800*/ -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 - -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 - -#define bDAFormat 0x40000 - -#define bTxChEmuEnable 0x01000000 - -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 - -#define bExtLNAGain 0x7c00 - -/* Page d */ -#define bSTBCEn 0x4 -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -/* #define bRxPath1 0x01 - * #define bRxPath2 0x02 - * #define bRxPath3 0x04 - * #define bRxPath4 0x08 - * #define bTxPath1 0x10 - * #define bTxPath2 0x20 - */ -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 - -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 - -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 - -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 - -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 - -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 - -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Page e */ -#define bTxAGCRate18_06 0x7f7f7f7f -#define bTxAGCRate54_24 0x7f7f7f7f -#define bTxAGCRateMCS32 0x7f -#define bTxAGCRateCCK 0x7f00 -#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f -#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f -#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f -#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f - -#define bRxPesudoNoiseOn 0x20000000 /* Rx Pseduo noise */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* RF Zebra 1 */ -#define bZebra1_HSSIEnable 0x8 -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - -/* byte enable for sb_write */ -#define bByte0 0x1 -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - -/* for PutRegsetting & GetRegSetting BitMask */ -#define bMaskByte0 0xff -#define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 -#define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff -#define bMaskDWord 0xffffffff - -/* for PutRFRegsetting & GetRFRegSetting BitMask */ -#define bMask12Bits 0xfff - -#define bEnable 0x1 -#define bDisable 0x0 - -#define LeftAntenna 0x0 -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500 ms */ -#define tUpdateRxCounter 100 /* 100 ms */ - -#define rateCCK 0 -#define rateOFDM 1 -#define rateHT 2 - -#define bPMAC_End 0x1ff /* define Register-End */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -#define rRTL8256RxMixerPole 0xb -#define bZebraRxMixerPole 0x6 -#define rRTL8256TxBBOPBias 0x9 -#define bRTL8256TxBBOPBias 0x400 -#define rRTL8256TxBBBW 19 -#define bRTL8256TxBBBW 0x18 - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c deleted file mode 100644 index 69298c7c129a..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_phy.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */ -#include "r8192E_cmdpkt.h" - -void rtl92e_cam_reset(struct net_device *dev) -{ - u32 ulcommand = 0; - - ulcommand |= BIT(31) | BIT(30); - rtl92e_writel(dev, RWCAM, ulcommand); -} - -void rtl92e_enable_hw_security_config(struct net_device *dev) -{ - u8 SECR_value = 0x0; - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - SECR_value = SCR_TxEncEnable | SCR_RxDecEnable; - if (((ieee->pairwise_key_type == KEY_TYPE_WEP40) || - (ieee->pairwise_key_type == KEY_TYPE_WEP104)) && - (priv->rtllib->auth_mode != 2)) { - SECR_value |= SCR_RxUseDK; - SECR_value |= SCR_TxUseDK; - } - - ieee->hwsec_active = 1; - if ((ieee->ht_info->iot_action & HT_IOT_ACT_PURE_N_MODE) || !hwwep) { - ieee->hwsec_active = 0; - SECR_value &= ~SCR_RxDecEnable; - } - rtl92e_writeb(dev, SECR, SECR_value); -} - -void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, - u16 KeyType, const u8 *MacAddr, u32 *KeyContent) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - if (EntryNo >= TOTAL_CAM_ENTRY) - return; - - ieee->swcamtable[EntryNo].bused = true; - ieee->swcamtable[EntryNo].key_index = KeyIndex; - ieee->swcamtable[EntryNo].key_type = KeyType; - memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6); - ieee->swcamtable[EntryNo].useDK = 0; - memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16); -} - -void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, - u16 KeyType, const u8 *MacAddr, u8 DefaultKey, - u32 *KeyContent) -{ - u32 TargetCommand = 0; - u32 TargetContent = 0; - u16 usConfig = 0; - u8 i; - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - enum rt_rf_power_state rt_state; - - rt_state = priv->rtllib->rf_power_state; - if (rt_state == rf_off) { - if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) { - netdev_warn(dev, "%s(): RF is OFF.\n", - __func__); - return; - } - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); - } - priv->rtllib->is_set_key = true; - if (EntryNo >= TOTAL_CAM_ENTRY) { - netdev_info(dev, "%s(): Invalid CAM entry\n", __func__); - return; - } - - if (DefaultKey) - usConfig |= BIT(15) | (KeyType << 2); - else - usConfig |= BIT(15) | (KeyType << 2) | KeyIndex; - - for (i = 0; i < CAM_CONTENT_COUNT; i++) { - TargetCommand = i + CAM_CONTENT_COUNT * EntryNo; - TargetCommand |= BIT(31) | BIT(16); - - if (i == 0) { - TargetContent = (u32)(*(MacAddr + 0)) << 16 | - (u32)(*(MacAddr + 1)) << 24 | - (u32)usConfig; - - rtl92e_writel(dev, WCAMI, TargetContent); - rtl92e_writel(dev, RWCAM, TargetCommand); - } else if (i == 1) { - TargetContent = (u32)(*(MacAddr + 2)) | - (u32)(*(MacAddr + 3)) << 8 | - (u32)(*(MacAddr + 4)) << 16 | - (u32)(*(MacAddr + 5)) << 24; - rtl92e_writel(dev, WCAMI, TargetContent); - rtl92e_writel(dev, RWCAM, TargetCommand); - } else { - if (KeyContent) { - rtl92e_writel(dev, WCAMI, - (u32)(*(KeyContent + i - 2))); - rtl92e_writel(dev, RWCAM, TargetCommand); - udelay(100); - } - } - } -} diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h deleted file mode 100644 index 9deffdf96072..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL_CAM_H -#define _RTL_CAM_H - -#include <linux/types.h> - -struct net_device; - -void rtl92e_cam_reset(struct net_device *dev); -void rtl92e_enable_hw_security_config(struct net_device *dev); -void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex, - u16 KeyType, const u8 *MacAddr, u8 DefaultKey, - u32 *KeyContent); -void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, - u16 KeyType, const u8 *MacAddr, u32 *KeyContent); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c deleted file mode 100644 index dc1301f1a0c1..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ /dev/null @@ -1,2016 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include <linux/uaccess.h> -#include <linux/pci.h> -#include <linux/vmalloc.h> -#include <linux/ieee80211.h> -#include "rtl_core.h" -#include "r8192E_phy.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" -#include "r8192E_cmdpkt.h" - -#include "rtl_wx.h" -#include "rtl_dm.h" - -#include "rtl_pm.h" - -int hwwep = 1; -static char *ifname = "wlan%d"; - -static const struct pci_device_id rtl8192_pci_id_tbl[] = { - {PCI_DEVICE(0x10ec, 0x8192)}, - {PCI_DEVICE(0x07aa, 0x0044)}, - {PCI_DEVICE(0x07aa, 0x0047)}, - {} -}; - -MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl); - -static int _rtl92e_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void _rtl92e_pci_disconnect(struct pci_dev *pdev); -static irqreturn_t _rtl92e_irq(int irq, void *netdev); - -static SIMPLE_DEV_PM_OPS(rtl92e_pm_ops, rtl92e_suspend, rtl92e_resume); - -static struct pci_driver rtl8192_pci_driver = { - .name = DRV_NAME, /* Driver name */ - .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */ - .probe = _rtl92e_pci_probe, /* probe fn */ - .remove = _rtl92e_pci_disconnect, /* remove fn */ - .driver.pm = &rtl92e_pm_ops, -}; - -static short _rtl92e_is_tx_queue_empty(struct net_device *dev); -static void _rtl92e_watchdog_wq_cb(void *data); -static void _rtl92e_watchdog_timer_cb(struct timer_list *t); -static void _rtl92e_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, - int rate); -static int _rtl92e_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void _rtl92e_tx_cmd(struct net_device *dev, struct sk_buff *skb); -static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb); -static short _rtl92e_pci_initdescring(struct net_device *dev); -static void _rtl92e_irq_tx_tasklet(struct tasklet_struct *t); -static void _rtl92e_irq_rx_tasklet(struct tasklet_struct *t); -static void _rtl92e_cancel_deferred_work(struct r8192_priv *priv); -static int _rtl92e_up(struct net_device *dev); -static int _rtl92e_try_up(struct net_device *dev); -static int _rtl92e_down(struct net_device *dev, bool shutdownrf); -static void _rtl92e_restart(void *data); - -/**************************************************************************** - * -----------------------------IO STUFF------------------------- - ****************************************************************************/ - -u8 rtl92e_readb(struct net_device *dev, int x) -{ - return 0xff & readb((u8 __iomem *)dev->mem_start + x); -} - -u32 rtl92e_readl(struct net_device *dev, int x) -{ - return readl((u8 __iomem *)dev->mem_start + x); -} - -u16 rtl92e_readw(struct net_device *dev, int x) -{ - return readw((u8 __iomem *)dev->mem_start + x); -} - -void rtl92e_writeb(struct net_device *dev, int x, u8 y) -{ - writeb(y, (u8 __iomem *)dev->mem_start + x); - - udelay(20); -} - -void rtl92e_writel(struct net_device *dev, int x, u32 y) -{ - writel(y, (u8 __iomem *)dev->mem_start + x); - - udelay(20); -} - -void rtl92e_writew(struct net_device *dev, int x, u16 y) -{ - writew(y, (u8 __iomem *)dev->mem_start + x); - - udelay(20); -} - -/**************************************************************************** - * -----------------------------GENERAL FUNCTION------------------------- - ****************************************************************************/ -bool rtl92e_set_rf_state(struct net_device *dev, - enum rt_rf_power_state state_to_set, - RT_RF_CHANGE_SOURCE change_source) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - bool action_allowed = false; - bool connect_by_ssid = false; - enum rt_rf_power_state rt_state; - u16 rf_wait_counter = 0; - unsigned long flag; - - while (true) { - spin_lock_irqsave(&priv->rf_ps_lock, flag); - if (priv->rf_change_in_progress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - - while (priv->rf_change_in_progress) { - rf_wait_counter++; - mdelay(1); - - if (rf_wait_counter > 100) { - netdev_warn(dev, - "%s(): Timeout waiting for RF change.\n", - __func__); - return false; - } - } - } else { - priv->rf_change_in_progress = true; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - break; - } - } - - rt_state = priv->rtllib->rf_power_state; - - switch (state_to_set) { - case rf_on: - priv->rtllib->rf_off_reason &= (~change_source); - - if ((change_source == RF_CHANGE_BY_HW) && priv->hw_radio_off) - priv->hw_radio_off = false; - - if (!priv->rtllib->rf_off_reason) { - priv->rtllib->rf_off_reason = 0; - action_allowed = true; - - if (rt_state == rf_off && - change_source >= RF_CHANGE_BY_HW) - connect_by_ssid = true; - } - break; - - case rf_off: - - if (priv->rtllib->iw_mode == IW_MODE_INFRA) { - if ((priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) || - (change_source > RF_CHANGE_BY_IPS)) { - if (ieee->link_state == MAC80211_LINKED) - priv->blinked_ingpio = true; - else - priv->blinked_ingpio = false; - rtllib_mgnt_disconnect(priv->rtllib, - WLAN_REASON_DISASSOC_STA_HAS_LEFT); - } - } - if ((change_source == RF_CHANGE_BY_HW) && !priv->hw_radio_off) - priv->hw_radio_off = true; - priv->rtllib->rf_off_reason |= change_source; - action_allowed = true; - break; - - case rf_sleep: - priv->rtllib->rf_off_reason |= change_source; - action_allowed = true; - break; - - default: - break; - } - - if (action_allowed) { - rtl92e_set_rf_power_state(dev, state_to_set); - if (state_to_set == rf_on) { - if (connect_by_ssid && priv->blinked_ingpio) { - schedule_delayed_work( - &ieee->associate_procedure_wq, 0); - priv->blinked_ingpio = false; - } - } - } - - spin_lock_irqsave(&priv->rf_ps_lock, flag); - priv->rf_change_in_progress = false; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - return action_allowed; -} - -static short _rtl92e_check_nic_enough_desc(struct net_device *dev, int prio) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; - - if (ring->entries - skb_queue_len(&ring->queue) >= 2) - return 1; - return 0; -} - -static void _rtl92e_tx_timeout(struct net_device *dev, unsigned int txqueue) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - schedule_work(&priv->reset_wq); - netdev_info(dev, "TXTIMEOUT"); -} - -static void _rtl92e_update_cap(struct net_device *dev, u16 cap) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_network *net = &priv->rtllib->current_network; - bool ShortPreamble; - - if (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) { - if (priv->dot11_current_preamble_mode != PREAMBLE_SHORT) { - ShortPreamble = true; - priv->dot11_current_preamble_mode = PREAMBLE_SHORT; - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_ACK_PREAMBLE, - (unsigned char *)&ShortPreamble); - } - } else { - if (priv->dot11_current_preamble_mode != PREAMBLE_LONG) { - ShortPreamble = false; - priv->dot11_current_preamble_mode = PREAMBLE_LONG; - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_ACK_PREAMBLE, - (unsigned char *)&ShortPreamble); - } - } - - if (net->mode & (WIRELESS_MODE_G | WIRELESS_MODE_N_24G)) { - u8 slot_time_val; - u8 cur_slot_time = priv->slot_time; - - if ((cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) && - (!priv->rtllib->ht_info->current_rt2rt_long_slot_time)) { - if (cur_slot_time != SHORT_SLOT_TIME) { - slot_time_val = SHORT_SLOT_TIME; - priv->rtllib->set_hw_reg_handler(dev, - HW_VAR_SLOT_TIME, &slot_time_val); - } - } else { - if (cur_slot_time != NON_SHORT_SLOT_TIME) { - slot_time_val = NON_SHORT_SLOT_TIME; - priv->rtllib->set_hw_reg_handler(dev, - HW_VAR_SLOT_TIME, &slot_time_val); - } - } - } -} - -static const struct rtllib_qos_parameters def_qos_parameters = { - {cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3)}, - {cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7)}, - {2, 2, 2, 2}, - {0, 0, 0, 0}, - {0, 0, 0, 0} -}; - -static void _rtl92e_update_beacon(void *data) -{ - struct r8192_priv *priv = container_of(data, struct r8192_priv, update_beacon_wq.work); - struct net_device *dev = priv->rtllib->dev; - struct rtllib_device *ieee = priv->rtllib; - struct rtllib_network *net = &ieee->current_network; - - if (ieee->ht_info->current_ht_support) - HT_update_self_and_peer_setting(ieee, net); - ieee->ht_info->current_rt2rt_long_slot_time = net->bssht.bd_rt2rt_long_slot_time; - _rtl92e_update_cap(dev, net->capability); -} - -static void _rtl92e_qos_activate(void *data) -{ - struct r8192_priv *priv = container_of(data, struct r8192_priv, qos_activate); - struct net_device *dev = priv->rtllib->dev; - int i; - - mutex_lock(&priv->mutex); - if (priv->rtllib->link_state != MAC80211_LINKED) - goto success; - - for (i = 0; i < QOS_QUEUE_NUM; i++) - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_AC_PARAM, (u8 *)(&i)); - -success: - mutex_unlock(&priv->mutex); -} - -static int _rtl92e_qos_handle_probe_response(struct r8192_priv *priv, - int active_network, - struct rtllib_network *network) -{ - int ret = 0; - u32 size = sizeof(struct rtllib_qos_parameters); - - if (priv->rtllib->link_state != MAC80211_LINKED) - return ret; - - if (priv->rtllib->iw_mode != IW_MODE_INFRA) - return ret; - - if (network->flags & NETWORK_HAS_QOS_MASK) { - if (active_network && - (network->flags & NETWORK_HAS_QOS_PARAMETERS)) - network->qos_data.active = network->qos_data.supported; - - if ((network->qos_data.active == 1) && (active_network == 1) && - (network->flags & NETWORK_HAS_QOS_PARAMETERS) && - (network->qos_data.old_param_count != - network->qos_data.param_count)) { - network->qos_data.old_param_count = - network->qos_data.param_count; - priv->rtllib->wmm_acm = network->qos_data.wmm_acm; - schedule_work(&priv->qos_activate); - } - } else { - memcpy(&priv->rtllib->current_network.qos_data.parameters, - &def_qos_parameters, size); - - if ((network->qos_data.active == 1) && (active_network == 1)) - schedule_work(&priv->qos_activate); - - network->qos_data.active = 0; - network->qos_data.supported = 0; - } - - return 0; -} - -static int _rtl92e_handle_beacon(struct net_device *dev, - struct rtllib_beacon *beacon, - struct rtllib_network *network) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - _rtl92e_qos_handle_probe_response(priv, 1, network); - - schedule_delayed_work(&priv->update_beacon_wq, 0); - return 0; -} - -static int _rtl92e_qos_assoc_resp(struct r8192_priv *priv, - struct rtllib_network *network) -{ - unsigned long flags; - u32 size = sizeof(struct rtllib_qos_parameters); - int set_qos_param = 0; - - if (!priv || !network) - return 0; - - if (priv->rtllib->link_state != MAC80211_LINKED) - return 0; - - if (priv->rtllib->iw_mode != IW_MODE_INFRA) - return 0; - - spin_lock_irqsave(&priv->rtllib->lock, flags); - if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { - memcpy(&priv->rtllib->current_network.qos_data.parameters, - &network->qos_data.parameters, - sizeof(struct rtllib_qos_parameters)); - priv->rtllib->current_network.qos_data.active = 1; - priv->rtllib->wmm_acm = network->qos_data.wmm_acm; - set_qos_param = 1; - priv->rtllib->current_network.qos_data.old_param_count = - priv->rtllib->current_network.qos_data.param_count; - priv->rtllib->current_network.qos_data.param_count = - network->qos_data.param_count; - } else { - memcpy(&priv->rtllib->current_network.qos_data.parameters, - &def_qos_parameters, size); - priv->rtllib->current_network.qos_data.active = 0; - priv->rtllib->current_network.qos_data.supported = 0; - set_qos_param = 1; - } - - spin_unlock_irqrestore(&priv->rtllib->lock, flags); - - if (set_qos_param == 1) { - rtl92e_dm_init_edca_turbo(priv->rtllib->dev); - schedule_work(&priv->qos_activate); - } - return 0; -} - -static int _rtl92e_handle_assoc_response(struct net_device *dev, - struct rtllib_assoc_response_frame *resp, - struct rtllib_network *network) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - _rtl92e_qos_assoc_resp(priv, network); - return 0; -} - -void rtl92e_config_rate(struct net_device *dev, u16 *rate_config) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_network *net; - u8 i = 0, basic_rate = 0; - - net = &priv->rtllib->current_network; - - for (i = 0; i < net->rates_len; i++) { - basic_rate = net->rates[i] & 0x7f; - switch (basic_rate) { - case MGN_1M: - *rate_config |= RRSR_1M; - break; - case MGN_2M: - *rate_config |= RRSR_2M; - break; - case MGN_5_5M: - *rate_config |= RRSR_5_5M; - break; - case MGN_11M: - *rate_config |= RRSR_11M; - break; - case MGN_6M: - *rate_config |= RRSR_6M; - break; - case MGN_9M: - *rate_config |= RRSR_9M; - break; - case MGN_12M: - *rate_config |= RRSR_12M; - break; - case MGN_18M: - *rate_config |= RRSR_18M; - break; - case MGN_24M: - *rate_config |= RRSR_24M; - break; - case MGN_36M: - *rate_config |= RRSR_36M; - break; - case MGN_48M: - *rate_config |= RRSR_48M; - break; - case MGN_54M: - *rate_config |= RRSR_54M; - break; - } - } - - for (i = 0; i < net->rates_ex_len; i++) { - basic_rate = net->rates_ex[i] & 0x7f; - switch (basic_rate) { - case MGN_1M: - *rate_config |= RRSR_1M; - break; - case MGN_2M: - *rate_config |= RRSR_2M; - break; - case MGN_5_5M: - *rate_config |= RRSR_5_5M; - break; - case MGN_11M: - *rate_config |= RRSR_11M; - break; - case MGN_6M: - *rate_config |= RRSR_6M; - break; - case MGN_9M: - *rate_config |= RRSR_9M; - break; - case MGN_12M: - *rate_config |= RRSR_12M; - break; - case MGN_18M: - *rate_config |= RRSR_18M; - break; - case MGN_24M: - *rate_config |= RRSR_24M; - break; - case MGN_36M: - *rate_config |= RRSR_36M; - break; - case MGN_48M: - *rate_config |= RRSR_48M; - break; - case MGN_54M: - *rate_config |= RRSR_54M; - break; - } - } -} - -static void _rtl92e_refresh_support_rate(struct r8192_priv *priv) -{ - struct rtllib_device *ieee = priv->rtllib; - - if (ieee->mode == WIRELESS_MODE_N_24G) { - memcpy(ieee->reg_dot11ht_oper_rate_set, - ieee->reg_ht_supp_rate_set, 16); - memcpy(ieee->reg_dot11tx_ht_oper_rate_set, - ieee->reg_ht_supp_rate_set, 16); - - } else { - memset(ieee->reg_dot11ht_oper_rate_set, 0, 16); - } -} - -void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 support_mode = (WIRELESS_MODE_N_24G | WIRELESS_MODE_G | WIRELESS_MODE_B); - - if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode & support_mode) == 0)) - wireless_mode = WIRELESS_MODE_N_24G; - - if ((wireless_mode & (WIRELESS_MODE_B | WIRELESS_MODE_G)) == - (WIRELESS_MODE_G | WIRELESS_MODE_B)) - wireless_mode = WIRELESS_MODE_G; - - priv->rtllib->mode = wireless_mode; - - if (wireless_mode == WIRELESS_MODE_N_24G) - priv->rtllib->ht_info->enable_ht = 1; - else - priv->rtllib->ht_info->enable_ht = 0; - - _rtl92e_refresh_support_rate(priv); -} - -static int _rtl92e_sta_up(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - (&priv->rtllib->pwr_save_ctrl); - bool init_status; - - priv->up = 1; - priv->rtllib->ieee_up = 1; - - priv->up_first_time = 0; - init_status = rtl92e_start_adapter(dev); - if (!init_status) { - netdev_err(dev, "%s(): Initialization failed!\n", __func__); - return -1; - } - - RT_CLEAR_PS_LEVEL(psc, RT_RF_OFF_LEVL_HALT_NIC); - - if (priv->polling_timer_on == 0) - rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer); - - if (priv->rtllib->link_state != MAC80211_LINKED) - rtllib_softmac_start_protocol(priv->rtllib); - rtllib_reset_queue(priv->rtllib); - _rtl92e_watchdog_timer_cb(&priv->watch_dog_timer); - - if (!netif_queue_stopped(dev)) - netif_start_queue(dev); - else - netif_wake_queue(dev); - - priv->bfirst_after_down = false; - return 0; -} - -static int _rtl92e_sta_down(struct net_device *dev, bool shutdownrf) -{ - struct r8192_priv *priv = rtllib_priv(dev); - unsigned long flags = 0; - u8 rf_in_progress_timeout = 0; - - if (priv->up == 0) - return -1; - - priv->rtllib->rtllib_ips_leave(dev); - - if (priv->rtllib->link_state == MAC80211_LINKED) - rtl92e_leisure_ps_leave(dev); - - priv->up = 0; - priv->rtllib->ieee_up = 0; - priv->bfirst_after_down = true; - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - - priv->rtllib->wpa_ie_len = 0; - kfree(priv->rtllib->wpa_ie); - priv->rtllib->wpa_ie = NULL; - rtl92e_cam_reset(dev); - memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32); - rtl92e_irq_disable(dev); - - del_timer_sync(&priv->watch_dog_timer); - _rtl92e_cancel_deferred_work(priv); - cancel_delayed_work(&priv->rtllib->hw_wakeup_wq); - - rtllib_softmac_stop_protocol(priv->rtllib); - spin_lock_irqsave(&priv->rf_ps_lock, flags); - while (priv->rf_change_in_progress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - if (rf_in_progress_timeout > 100) { - spin_lock_irqsave(&priv->rf_ps_lock, flags); - break; - } - mdelay(1); - rf_in_progress_timeout++; - spin_lock_irqsave(&priv->rf_ps_lock, flags); - } - priv->rf_change_in_progress = true; - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - rtl92e_stop_adapter(dev, false); - spin_lock_irqsave(&priv->rf_ps_lock, flags); - priv->rf_change_in_progress = false; - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - udelay(100); - memset(&priv->rtllib->current_network, 0, - offsetof(struct rtllib_network, list)); - - return 0; -} - -static void _rtl92e_init_priv_handler(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->rtllib->softmac_hard_start_xmit = _rtl92e_hard_start_xmit; - priv->rtllib->set_chan = rtl92e_set_channel; - priv->rtllib->link_change = rtl92e_link_change; - priv->rtllib->softmac_data_hard_start_xmit = _rtl92e_hard_data_xmit; - priv->rtllib->check_nic_enough_desc = _rtl92e_check_nic_enough_desc; - priv->rtllib->handle_assoc_response = _rtl92e_handle_assoc_response; - priv->rtllib->handle_beacon = _rtl92e_handle_beacon; - priv->rtllib->set_wireless_mode = rtl92e_set_wireless_mode; - priv->rtllib->leisure_ps_leave = rtl92e_leisure_ps_leave; - priv->rtllib->set_bw_mode_handler = rtl92e_set_bw_mode; - - priv->rtllib->sta_wake_up = rtl92e_hw_wakeup; - priv->rtllib->enter_sleep_state = rtl92e_enter_sleep; - priv->rtllib->ps_is_queue_empty = _rtl92e_is_tx_queue_empty; - - priv->rtllib->get_nmode_support_by_sec_cfg = rtl92e_get_nmode_support_by_sec; - priv->rtllib->get_half_nmode_support_by_aps_handler = - rtl92e_is_halfn_supported_by_ap; - - priv->rtllib->set_hw_reg_handler = rtl92e_set_reg; - priv->rtllib->allow_all_dest_addr_handler = rtl92e_set_monitor_mode; - priv->rtllib->init_gain_handler = rtl92e_init_gain; - priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq; - priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave; - priv->rtllib->scan_operation_backup_handler = rtl92e_scan_op_backup; -} - -static void _rtl92e_init_priv_variable(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 i; - - priv->dot11_current_preamble_mode = PREAMBLE_AUTO; - priv->rtllib->status = 0; - priv->polling_timer_on = 0; - priv->up_first_time = 1; - priv->blinked_ingpio = false; - priv->being_init_adapter = false; - priv->txringcount = 64; - priv->rxbuffersize = 9100; - priv->rxringcount = MAX_RX_COUNT; - priv->irq_enabled = 0; - priv->chan = 1; - priv->rtllib->mode = WIRELESS_MODE_AUTO; - priv->rtllib->iw_mode = IW_MODE_INFRA; - priv->rtllib->ieee_up = 0; - priv->retry_rts = DEFAULT_RETRY_RTS; - priv->retry_data = DEFAULT_RETRY_DATA; - priv->rtllib->rts = DEFAULT_RTS_THRESHOLD; - priv->rtllib->rate = 110; - priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - priv->bcck_in_ch14 = false; - priv->cck_present_attn = 0; - priv->rfa_txpowertrackingindex = 0; - priv->cck_pwr_enl = 6; - memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32); - priv->rx_ctr = 0; - priv->rtllib->wx_set_enc = 0; - priv->hw_radio_off = false; - priv->rtllib->rf_off_reason = 0; - priv->rf_change_in_progress = false; - priv->hw_rf_off_action = 0; - priv->set_rf_pwr_state_in_progress = false; - priv->rtllib->pwr_save_ctrl.bLeisurePs = true; - priv->rtllib->lps_delay_cnt = 0; - priv->rtllib->sta_sleep = LPS_IS_WAKE; - priv->rtllib->rf_power_state = rf_on; - - priv->rtllib->current_network.beacon_interval = DEFAULT_BEACONINTERVAL; - priv->rtllib->iw_mode = IW_MODE_INFRA; - priv->rtllib->be_scan_inprogress = false; - - priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; - - priv->fw_info = vzalloc(sizeof(struct rt_firmware)); - if (!priv->fw_info) - netdev_err(dev, - "rtl8192e: Unable to allocate space for firmware\n"); - - skb_queue_head_init(&priv->skb_queue); - - for (i = 0; i < MAX_QUEUE_SIZE; i++) - skb_queue_head_init(&priv->rtllib->skb_waitq[i]); -} - -static void _rtl92e_init_priv_lock(struct r8192_priv *priv) -{ - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->irq_th_lock); - spin_lock_init(&priv->rf_ps_lock); - spin_lock_init(&priv->ps_lock); - mutex_init(&priv->wx_mutex); - mutex_init(&priv->rf_mutex); - mutex_init(&priv->mutex); -} - -static void _rtl92e_init_priv_task(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - INIT_WORK(&priv->reset_wq, (void *)_rtl92e_restart); - INIT_WORK(&priv->rtllib->ips_leave_wq, (void *)rtl92e_ips_leave_wq); - INIT_DELAYED_WORK(&priv->watch_dog_wq, (void *)_rtl92e_watchdog_wq_cb); - INIT_DELAYED_WORK(&priv->txpower_tracking_wq, (void *)rtl92e_dm_txpower_tracking_wq); - INIT_DELAYED_WORK(&priv->rfpath_check_wq, (void *)rtl92e_dm_rf_pathcheck_wq); - INIT_DELAYED_WORK(&priv->update_beacon_wq, (void *)_rtl92e_update_beacon); - INIT_WORK(&priv->qos_activate, (void *)_rtl92e_qos_activate); - INIT_DELAYED_WORK(&priv->rtllib->hw_wakeup_wq, (void *)rtl92e_hw_wakeup_wq); - INIT_DELAYED_WORK(&priv->rtllib->hw_sleep_wq, (void *)rtl92e_hw_sleep_wq); - tasklet_setup(&priv->irq_rx_tasklet, _rtl92e_irq_rx_tasklet); - tasklet_setup(&priv->irq_tx_tasklet, _rtl92e_irq_tx_tasklet); -} - -static short _rtl92e_get_channel_map(struct net_device *dev) -{ - int i; - - struct r8192_priv *priv = rtllib_priv(dev); - - for (i = 1; i <= 11; i++) - (priv->rtllib->active_channel_map)[i] = 1; - (priv->rtllib->active_channel_map)[12] = 2; - (priv->rtllib->active_channel_map)[13] = 2; - - return 0; -} - -static short _rtl92e_init(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - memset(&priv->stats, 0, sizeof(struct rt_stats)); - - _rtl92e_init_priv_handler(dev); - _rtl92e_init_priv_variable(dev); - _rtl92e_init_priv_lock(priv); - _rtl92e_init_priv_task(dev); - rtl92e_get_eeprom_size(dev); - rtl92e_init_variables(dev); - _rtl92e_get_channel_map(dev); - - rtl92e_dm_init(dev); - - timer_setup(&priv->watch_dog_timer, _rtl92e_watchdog_timer_cb, 0); - - timer_setup(&priv->gpio_polling_timer, rtl92e_check_rfctrl_gpio_timer, - 0); - - rtl92e_irq_disable(dev); - if (request_irq(dev->irq, _rtl92e_irq, IRQF_SHARED, dev->name, dev)) { - netdev_err(dev, "Error allocating IRQ %d", dev->irq); - return -1; - } - - priv->irq = dev->irq; - - if (_rtl92e_pci_initdescring(dev) != 0) { - netdev_err(dev, "Endopoints initialization failed"); - free_irq(dev->irq, dev); - return -1; - } - - return 0; -} - -/*************************************************************************** - * -------------------------------WATCHDOG STUFF--------------------------- - **************************************************************************/ -static short _rtl92e_is_tx_queue_empty(struct net_device *dev) -{ - int i = 0; - struct r8192_priv *priv = rtllib_priv(dev); - - for (i = 0; i <= MGNT_QUEUE; i++) { - if ((i == TXCMD_QUEUE) || (i == HCCA_QUEUE)) - continue; - if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0) { - netdev_info(dev, "===>tx queue is not empty:%d, %d\n", - i, skb_queue_len(&(&priv->tx_ring[i])->queue)); - return 0; - } - } - return 1; -} - -static enum reset_type _rtl92e_tx_check_stuck(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 QueueID; - bool bCheckFwTxCnt = false; - struct rtl8192_tx_ring *ring = NULL; - struct sk_buff *skb = NULL; - struct cb_desc *tcb_desc = NULL; - unsigned long flags = 0; - - switch (priv->rtllib->ps) { - case RTLLIB_PS_DISABLED: - break; - case (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST): - break; - default: - break; - } - spin_lock_irqsave(&priv->irq_th_lock, flags); - for (QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++) { - if (QueueID == TXCMD_QUEUE) - continue; - - if (QueueID == BEACON_QUEUE) - continue; - - ring = &priv->tx_ring[QueueID]; - - if (skb_queue_len(&ring->queue) == 0) { - continue; - } else { - skb = __skb_peek(&ring->queue); - tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - tcb_desc->stuck_count++; - bCheckFwTxCnt = true; - if (tcb_desc->stuck_count > 1) - netdev_info(dev, - "%s: QueueID=%d tcb_desc->stuck_count=%d\n", - __func__, QueueID, - tcb_desc->stuck_count); - } - } - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - - if (bCheckFwTxCnt) { - if (rtl92e_is_tx_stuck(dev)) - return RESET_TYPE_SILENT; - } - - return RESET_TYPE_NORESET; -} - -static enum reset_type _rtl92e_rx_check_stuck(struct net_device *dev) -{ - if (rtl92e_is_rx_stuck(dev)) - return RESET_TYPE_SILENT; - - return RESET_TYPE_NORESET; -} - -static void _rtl92e_if_check_reset(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - enum reset_type TxResetType = RESET_TYPE_NORESET; - enum reset_type RxResetType = RESET_TYPE_NORESET; - enum rt_rf_power_state rfState; - - rfState = priv->rtllib->rf_power_state; - - if (rfState == rf_on) - TxResetType = _rtl92e_tx_check_stuck(dev); - - if (rfState == rf_on && - (priv->rtllib->iw_mode == IW_MODE_INFRA) && - (priv->rtllib->link_state == MAC80211_LINKED)) - RxResetType = _rtl92e_rx_check_stuck(dev); - - if (TxResetType == RESET_TYPE_SILENT || - RxResetType == RESET_TYPE_SILENT) { - netdev_info(dev, "%s(): TxResetType is %d, RxResetType is %d\n", - __func__, TxResetType, RxResetType); - } -} - -static void _rtl92e_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum, - u32 *TotalRxDataNum) -{ - u16 slot_index; - u8 i; - - *TotalRxBcnNum = 0; - *TotalRxDataNum = 0; - - slot_index = (priv->rtllib->link_detect_info.slot_index++) % - (priv->rtllib->link_detect_info.slot_num); - priv->rtllib->link_detect_info.RxBcnNum[slot_index] = - priv->rtllib->link_detect_info.num_recv_bcn_in_period; - priv->rtllib->link_detect_info.RxDataNum[slot_index] = - priv->rtllib->link_detect_info.num_recv_data_in_period; - for (i = 0; i < priv->rtllib->link_detect_info.slot_num; i++) { - *TotalRxBcnNum += priv->rtllib->link_detect_info.RxBcnNum[i]; - *TotalRxDataNum += priv->rtllib->link_detect_info.RxDataNum[i]; - } -} - -static void _rtl92e_watchdog_wq_cb(void *data) -{ - struct r8192_priv *priv = container_of_dwork_rsl(data, - struct r8192_priv, watch_dog_wq); - struct net_device *dev = priv->rtllib->dev; - struct rtllib_device *ieee = priv->rtllib; - static u8 check_reset_cnt; - unsigned long flags; - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - (&priv->rtllib->pwr_save_ctrl); - bool busy_traffic = false; - bool bHigherBusyTraffic = false; - bool bHigherBusyRxTraffic = false; - bool bEnterPS = false; - - if (!priv->up || priv->hw_radio_off) - return; - - if (priv->rtllib->link_state >= MAC80211_LINKED) { - if (priv->rtllib->cnt_after_link < 2) - priv->rtllib->cnt_after_link++; - } else { - priv->rtllib->cnt_after_link = 0; - } - - rtl92e_dm_watchdog(dev); - - if (!rtllib_act_scanning(priv->rtllib, false)) { - if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->link_state == - MAC80211_NOLINK) && - (ieee->rf_power_state == rf_on) && !ieee->is_set_key && - (!ieee->proto_stoppping) && !ieee->wx_set_enc) { - if (ieee->pwr_save_ctrl.return_point == IPS_CALLBACK_NONE) - rtl92e_ips_enter(dev); - } - } - if ((ieee->link_state == MAC80211_LINKED) && (ieee->iw_mode == IW_MODE_INFRA)) { - if (ieee->link_detect_info.num_rx_ok_in_period > 100 || - ieee->link_detect_info.num_tx_ok_in_period > 100) - busy_traffic = true; - - if (ieee->link_detect_info.num_rx_ok_in_period > 4000 || - ieee->link_detect_info.num_tx_ok_in_period > 4000) { - bHigherBusyTraffic = true; - if (ieee->link_detect_info.num_rx_ok_in_period > 5000) - bHigherBusyRxTraffic = true; - else - bHigherBusyRxTraffic = false; - } - - if (((ieee->link_detect_info.num_rx_unicast_ok_in_period + - ieee->link_detect_info.num_tx_ok_in_period) > 8) || - (ieee->link_detect_info.num_rx_unicast_ok_in_period > 2)) - bEnterPS = false; - else - bEnterPS = true; - - if (ieee->current_network.beacon_interval < 95) - bEnterPS = false; - - if (bEnterPS) - rtl92e_leisure_ps_enter(dev); - else - rtl92e_leisure_ps_leave(dev); - - } else { - rtl92e_leisure_ps_leave(dev); - } - - ieee->link_detect_info.num_rx_ok_in_period = 0; - ieee->link_detect_info.num_tx_ok_in_period = 0; - ieee->link_detect_info.num_rx_unicast_ok_in_period = 0; - ieee->link_detect_info.busy_traffic = busy_traffic; - - ieee->link_detect_info.bHigherBusyTraffic = bHigherBusyTraffic; - ieee->link_detect_info.bHigherBusyRxTraffic = bHigherBusyRxTraffic; - - if (ieee->link_state == MAC80211_LINKED && ieee->iw_mode == IW_MODE_INFRA) { - u32 TotalRxBcnNum = 0; - u32 TotalRxDataNum = 0; - - _rtl92e_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum); - - if ((TotalRxBcnNum + TotalRxDataNum) == 0) - priv->check_roaming_cnt++; - else - priv->check_roaming_cnt = 0; - - if (priv->check_roaming_cnt > 0) { - if (ieee->rf_power_state == rf_off) - netdev_info(dev, "%s(): RF is off\n", __func__); - - netdev_info(dev, - "===>%s(): AP is power off, chan:%d, connect another one\n", - __func__, priv->chan); - - ieee->link_state = RTLLIB_ASSOCIATING; - - remove_peer_ts(priv->rtllib, - priv->rtllib->current_network.bssid); - ieee->is_roaming = true; - ieee->is_set_key = false; - ieee->link_change(dev); - notify_wx_assoc_event(ieee); - - if (!(ieee->rtllib_ap_sec_type(ieee) & - (SEC_ALG_CCMP | SEC_ALG_TKIP))) - schedule_delayed_work( - &ieee->associate_procedure_wq, 0); - - priv->check_roaming_cnt = 0; - } - ieee->link_detect_info.num_recv_bcn_in_period = 0; - ieee->link_detect_info.num_recv_data_in_period = 0; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - if ((check_reset_cnt++ >= 3) && (!ieee->is_roaming) && - (!priv->rf_change_in_progress) && (!psc->bSwRfProcessing)) { - _rtl92e_if_check_reset(dev); - check_reset_cnt = 3; - } - spin_unlock_irqrestore(&priv->tx_lock, flags); -} - -static void _rtl92e_watchdog_timer_cb(struct timer_list *t) -{ - struct r8192_priv *priv = from_timer(priv, t, watch_dog_timer); - - schedule_delayed_work(&priv->watch_dog_wq, 0); - mod_timer(&priv->watch_dog_timer, jiffies + - msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME)); -} - -/**************************************************************************** - * ---------------------------- NIC TX/RX STUFF--------------------------- - ****************************************************************************/ -void rtl92e_rx_enable(struct net_device *dev) -{ - rtl92e_enable_rx(dev); -} - -void rtl92e_tx_enable(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - rtl92e_enable_tx(dev); - - rtllib_reset_queue(priv->rtllib); -} - -static void _rtl92e_free_rx_ring(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int i; - - for (i = 0; i < priv->rxringcount; i++) { - struct sk_buff *skb = priv->rx_buf[i]; - - if (!skb) - continue; - - dma_unmap_single(&priv->pdev->dev, - *((dma_addr_t *)skb->cb), - priv->rxbuffersize, DMA_FROM_DEVICE); - kfree_skb(skb); - } - - dma_free_coherent(&priv->pdev->dev, - sizeof(*priv->rx_ring) * priv->rxringcount, - priv->rx_ring, - priv->rx_ring_dma); - priv->rx_ring = NULL; -} - -static void _rtl92e_free_tx_ring(struct net_device *dev, unsigned int prio) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - dma_unmap_single(&priv->pdev->dev, entry->TxBuffAddr, - skb->len, DMA_TO_DEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - - dma_free_coherent(&priv->pdev->dev, - sizeof(*ring->desc) * ring->entries, ring->desc, - ring->dma); - ring->desc = NULL; -} - -static void _rtl92e_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, - int rate) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u8 queue_index = tcb_desc->queue_index; - - if ((priv->rtllib->rf_power_state == rf_off) || !priv->up) { - kfree_skb(skb); - return; - } - - if (queue_index == TXCMD_QUEUE) - netdev_warn(dev, "%s(): queue index == TXCMD_QUEUE\n", - __func__); - - memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); - skb_push(skb, priv->rtllib->tx_headroom); - ret = _rtl92e_tx(dev, skb); - - if (queue_index != MGNT_QUEUE) { - priv->rtllib->stats.tx_bytes += (skb->len - - priv->rtllib->tx_headroom); - priv->rtllib->stats.tx_packets++; - } - - if (ret != 0) - kfree_skb(skb); -} - -static int _rtl92e_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u8 queue_index = tcb_desc->queue_index; - - if (queue_index != TXCMD_QUEUE) { - if ((priv->rtllib->rf_power_state == rf_off) || - !priv->up) { - kfree_skb(skb); - return 0; - } - } - - memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); - if (queue_index == TXCMD_QUEUE) { - _rtl92e_tx_cmd(dev, skb); - return 0; - } - - tcb_desc->ratr_index = 7; - tcb_desc->tx_dis_rate_fallback = 1; - tcb_desc->tx_use_drv_assinged_rate = 1; - tcb_desc->tx_enable_fw_calc_dur = 1; - skb_push(skb, priv->rtllib->tx_headroom); - ret = _rtl92e_tx(dev, skb); - if (ret != 0) - kfree_skb(skb); - return ret; -} - -static void _rtl92e_tx_isr(struct net_device *dev, int prio) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - - if (prio != BEACON_QUEUE) { - if (entry->OWN) - return; - ring->idx = (ring->idx + 1) % ring->entries; - } - - skb = __skb_dequeue(&ring->queue); - dma_unmap_single(&priv->pdev->dev, entry->TxBuffAddr, - skb->len, DMA_TO_DEVICE); - - kfree_skb(skb); - } - if (prio != BEACON_QUEUE) - tasklet_schedule(&priv->irq_tx_tasklet); -} - -static void _rtl92e_tx_cmd(struct net_device *dev, struct sk_buff *skb) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtl8192_tx_ring *ring; - struct tx_desc_cmd *entry; - unsigned int idx; - struct cb_desc *tcb_desc; - unsigned long flags; - - spin_lock_irqsave(&priv->irq_th_lock, flags); - ring = &priv->tx_ring[TXCMD_QUEUE]; - - idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; - entry = (struct tx_desc_cmd *)&ring->desc[idx]; - - tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - - rtl92e_fill_tx_cmd_desc(dev, entry, tcb_desc, skb); - - __skb_queue_tail(&ring->queue, skb); - spin_unlock_irqrestore(&priv->irq_th_lock, flags); -} - -static short _rtl92e_tx(struct net_device *dev, struct sk_buff *skb) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtl8192_tx_ring *ring; - unsigned long flags; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - struct tx_desc *pdesc = NULL; - struct ieee80211_hdr *header = NULL; - u8 *pda_addr = NULL; - int idx; - u32 fwinfo_size = 0; - - priv->rtllib->awake_pkt_sent = true; - - fwinfo_size = sizeof(struct tx_fwinfo_8190pci); - - header = (struct ieee80211_hdr *)(((u8 *)skb->data) + fwinfo_size); - pda_addr = header->addr1; - - if (!is_broadcast_ether_addr(pda_addr) && !is_multicast_ether_addr(pda_addr)) - priv->stats.txbytesunicast += skb->len - fwinfo_size; - - spin_lock_irqsave(&priv->irq_th_lock, flags); - ring = &priv->tx_ring[tcb_desc->queue_index]; - if (tcb_desc->queue_index != BEACON_QUEUE) - idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; - else - idx = 0; - - pdesc = &ring->desc[idx]; - if ((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) { - netdev_warn(dev, - "No more TX desc@%d, ring->idx = %d, idx = %d, skblen = 0x%x queuelen=%d", - tcb_desc->queue_index, ring->idx, idx, skb->len, - skb_queue_len(&ring->queue)); - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return skb->len; - } - rtl92e_fill_tx_desc(dev, pdesc, tcb_desc, skb); - __skb_queue_tail(&ring->queue, skb); - pdesc->OWN = 1; - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - netif_trans_update(dev); - - rtl92e_writew(dev, TP_POLL, 0x01 << tcb_desc->queue_index); - return 0; -} - -static short _rtl92e_alloc_rx_ring(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rx_desc *entry = NULL; - int i; - - priv->rx_ring = dma_alloc_coherent(&priv->pdev->dev, - sizeof(*priv->rx_ring) * priv->rxringcount, - &priv->rx_ring_dma, - GFP_ATOMIC); - if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - netdev_warn(dev, "Cannot allocate RX ring\n"); - return -ENOMEM; - } - - priv->rx_idx = 0; - - for (i = 0; i < priv->rxringcount; i++) { - struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize); - dma_addr_t *mapping; - - entry = &priv->rx_ring[i]; - if (!skb) - return 0; - skb->dev = dev; - priv->rx_buf[i] = skb; - mapping = (dma_addr_t *)skb->cb; - *mapping = dma_map_single(&priv->pdev->dev, - skb_tail_pointer(skb), - priv->rxbuffersize, DMA_FROM_DEVICE); - if (dma_mapping_error(&priv->pdev->dev, *mapping)) { - dev_kfree_skb_any(skb); - return -1; - } - entry->BufferAddress = *mapping; - - entry->Length = priv->rxbuffersize; - entry->OWN = 1; - } - - if (entry) - entry->EOR = 1; - return 0; -} - -static int _rtl92e_alloc_tx_ring(struct net_device *dev, unsigned int prio, - unsigned int entries) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct tx_desc *ring; - dma_addr_t dma; - int i; - - ring = dma_alloc_coherent(&priv->pdev->dev, sizeof(*ring) * entries, - &dma, GFP_ATOMIC); - if (!ring || (unsigned long)ring & 0xFF) { - netdev_warn(dev, "Cannot allocate TX ring (prio = %d)\n", prio); - return -ENOMEM; - } - - priv->tx_ring[prio].desc = ring; - priv->tx_ring[prio].dma = dma; - priv->tx_ring[prio].idx = 0; - priv->tx_ring[prio].entries = entries; - skb_queue_head_init(&priv->tx_ring[prio].queue); - - for (i = 0; i < entries; i++) - ring[i].NextDescAddress = - (u32)dma + ((i + 1) % entries) * - sizeof(*ring); - - return 0; -} - -static short _rtl92e_pci_initdescring(struct net_device *dev) -{ - u32 ret; - int i; - struct r8192_priv *priv = rtllib_priv(dev); - - ret = _rtl92e_alloc_rx_ring(dev); - if (ret) - return ret; - - for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) { - ret = _rtl92e_alloc_tx_ring(dev, i, priv->txringcount); - if (ret) - goto err_free_rings; - } - - return 0; - -err_free_rings: - _rtl92e_free_rx_ring(dev); - for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) - if (priv->tx_ring[i].desc) - _rtl92e_free_tx_ring(dev, i); - return 1; -} - -void rtl92e_reset_desc_ring(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int i; - unsigned long flags = 0; - - if (priv->rx_ring) { - struct rx_desc *entry = NULL; - - for (i = 0; i < priv->rxringcount; i++) { - entry = &priv->rx_ring[i]; - entry->OWN = 1; - } - priv->rx_idx = 0; - } - - spin_lock_irqsave(&priv->irq_th_lock, flags); - for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) { - if (priv->tx_ring[i].desc) { - struct rtl8192_tx_ring *ring = &priv->tx_ring[i]; - - while (skb_queue_len(&ring->queue)) { - struct tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = - __skb_dequeue(&ring->queue); - - dma_unmap_single(&priv->pdev->dev, - entry->TxBuffAddr, skb->len, - DMA_TO_DEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - ring->idx = 0; - } - } - spin_unlock_irqrestore(&priv->irq_th_lock, flags); -} - -long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index) -{ - long signal_power; - - signal_power = (long)((signal_strength_index + 1) >> 1); - signal_power -= 95; - - return signal_power; -} - -void rtl92e_update_rx_statistics(struct r8192_priv *priv, - struct rtllib_rx_stats *pprevious_stats) -{ - int weighting = 0; - - if (priv->stats.recv_signal_power == 0) - priv->stats.recv_signal_power = - pprevious_stats->RecvSignalPower; - - if (pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power) - weighting = 5; - else if (pprevious_stats->RecvSignalPower < - priv->stats.recv_signal_power) - weighting = (-5); - priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + - pprevious_stats->RecvSignalPower + - weighting) / 6; -} - -u8 rtl92e_rx_db_to_percent(s8 antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; - -} /* QueryRxPwrPercentage */ - -u8 rtl92e_evm_db_to_percent(s8 value) -{ - s8 ret_val = clamp(-value, 0, 33) * 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, - struct rtllib_rx_stats *ptarget_stats) -{ - ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU; - ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU; -} - -static void _rtl92e_rx_normal(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct ieee80211_hdr *rtllib_hdr = NULL; - bool unicast_packet = false; - u32 skb_len = 0; - - struct rtllib_rx_stats stats = { - .signal = 0, - .noise = (u8)-98, - .rate = 0, - }; - unsigned int count = priv->rxringcount; - - while (count--) { - struct rx_desc *pdesc = &priv->rx_ring - [priv->rx_idx]; - struct sk_buff *skb = priv->rx_buf - [priv->rx_idx]; - struct sk_buff *new_skb; - - if (pdesc->OWN) - return; - if (!rtl92e_get_rx_stats(dev, &stats, pdesc, skb)) - goto done; - new_skb = dev_alloc_skb(priv->rxbuffersize); - /* if allocation of new skb failed - drop current packet - * and reuse skb - */ - if (unlikely(!new_skb)) - goto done; - - dma_unmap_single(&priv->pdev->dev, *((dma_addr_t *)skb->cb), - priv->rxbuffersize, DMA_FROM_DEVICE); - - skb_put(skb, pdesc->Length); - skb_reserve(skb, stats.rx_drv_info_size + - stats.rx_buf_shift); - skb_trim(skb, skb->len - S_CRC_LEN); - rtllib_hdr = (struct ieee80211_hdr *)skb->data; - if (!is_multicast_ether_addr(rtllib_hdr->addr1)) { - /* unicast packet */ - unicast_packet = true; - } - skb_len = skb->len; - - if (!rtllib_rx(priv->rtllib, skb, &stats)) { - dev_kfree_skb_any(skb); - } else { - if (unicast_packet) - priv->stats.rxbytesunicast += skb_len; - } - - skb = new_skb; - skb->dev = dev; - - priv->rx_buf[priv->rx_idx] = skb; - *((dma_addr_t *)skb->cb) = dma_map_single(&priv->pdev->dev, - skb_tail_pointer(skb), - priv->rxbuffersize, DMA_FROM_DEVICE); - if (dma_mapping_error(&priv->pdev->dev, *((dma_addr_t *)skb->cb))) { - dev_kfree_skb_any(skb); - return; - } -done: - pdesc->BufferAddress = *((dma_addr_t *)skb->cb); - pdesc->OWN = 1; - pdesc->Length = priv->rxbuffersize; - if (priv->rx_idx == priv->rxringcount - 1) - pdesc->EOR = 1; - priv->rx_idx = (priv->rx_idx + 1) % - priv->rxringcount; - } -} - -static void _rtl92e_tx_resume(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - struct sk_buff *skb; - int queue_index; - - for (queue_index = BK_QUEUE; - queue_index < MAX_QUEUE_SIZE; queue_index++) { - while ((!skb_queue_empty(&ieee->skb_waitq[queue_index])) && - (priv->rtllib->check_nic_enough_desc(dev, queue_index) > 0)) { - skb = skb_dequeue(&ieee->skb_waitq[queue_index]); - ieee->softmac_data_hard_start_xmit(skb, dev, 0); - } - } -} - -static void _rtl92e_irq_tx_tasklet(struct tasklet_struct *t) -{ - struct r8192_priv *priv = from_tasklet(priv, t, irq_tx_tasklet); - - _rtl92e_tx_resume(priv->rtllib->dev); -} - -static void _rtl92e_irq_rx_tasklet(struct tasklet_struct *t) -{ - struct r8192_priv *priv = from_tasklet(priv, t, irq_rx_tasklet); - - _rtl92e_rx_normal(priv->rtllib->dev); - - rtl92e_writel(priv->rtllib->dev, INTA_MASK, - rtl92e_readl(priv->rtllib->dev, INTA_MASK) | IMR_RDU); -} - -/**************************************************************************** - * ---------------------------- NIC START/CLOSE STUFF--------------------------- - ****************************************************************************/ -static void _rtl92e_cancel_deferred_work(struct r8192_priv *priv) -{ - cancel_delayed_work_sync(&priv->watch_dog_wq); - cancel_delayed_work_sync(&priv->update_beacon_wq); - cancel_delayed_work(&priv->rtllib->hw_sleep_wq); - cancel_work_sync(&priv->reset_wq); - cancel_work_sync(&priv->qos_activate); -} - -static int _rtl92e_up(struct net_device *dev) -{ - if (_rtl92e_sta_up(dev) == -1) - return -1; - return 0; -} - -static int _rtl92e_open(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - - mutex_lock(&priv->wx_mutex); - ret = _rtl92e_try_up(dev); - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_try_up(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->up == 1) - return -1; - return _rtl92e_up(dev); -} - -static int _rtl92e_close(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - - if ((rtllib_act_scanning(priv->rtllib, false)) && - !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)) { - rtllib_stop_scan(priv->rtllib); - } - - mutex_lock(&priv->wx_mutex); - - ret = _rtl92e_down(dev, true); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_down(struct net_device *dev, bool shutdownrf) -{ - if (_rtl92e_sta_down(dev, shutdownrf) == -1) - return -1; - - return 0; -} - -void rtl92e_commit(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->up == 0) - return; - rtllib_softmac_stop_protocol(priv->rtllib); - rtl92e_irq_disable(dev); - rtl92e_stop_adapter(dev, true); - _rtl92e_up(dev); -} - -static void _rtl92e_restart(void *data) -{ - struct r8192_priv *priv = container_of(data, struct r8192_priv, reset_wq); - struct net_device *dev = priv->rtllib->dev; - - mutex_lock(&priv->wx_mutex); - - rtl92e_commit(dev); - - mutex_unlock(&priv->wx_mutex); -} - -static void _rtl92e_set_multicast(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - short promisc; - - promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - priv->promisc = promisc; -} - -static int _rtl92e_set_mac_adr(struct net_device *dev, void *mac) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct sockaddr *addr = mac; - - mutex_lock(&priv->wx_mutex); - - eth_hw_addr_set(dev, addr->sa_data); - - schedule_work(&priv->reset_wq); - mutex_unlock(&priv->wx_mutex); - - return 0; -} - -static irqreturn_t _rtl92e_irq(int irq, void *netdev) -{ - struct net_device *dev = netdev; - struct r8192_priv *priv = rtllib_priv(dev); - unsigned long flags; - u32 inta; - - if (priv->irq_enabled == 0) - goto done; - - spin_lock_irqsave(&priv->irq_th_lock, flags); - - rtl92e_ack_irq(dev, &inta); - - if (!inta) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - goto done; - } - - if (inta == 0xffff) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - goto done; - } - - if (!netif_running(dev)) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - goto done; - } - - if (inta & IMR_MGNTDOK) { - _rtl92e_tx_isr(dev, MGNT_QUEUE); - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - if (priv->rtllib->ack_tx_to_ieee) { - if (_rtl92e_is_tx_queue_empty(dev)) { - priv->rtllib->ack_tx_to_ieee = 0; - rtllib_ps_tx_ack(priv->rtllib, 1); - } - } - spin_lock_irqsave(&priv->irq_th_lock, flags); - } - - if (inta & IMR_COMDOK) - _rtl92e_tx_isr(dev, TXCMD_QUEUE); - - if (inta & IMR_HIGHDOK) - _rtl92e_tx_isr(dev, HIGH_QUEUE); - - if (inta & IMR_ROK) - tasklet_schedule(&priv->irq_rx_tasklet); - - if (inta & IMR_RDU) { - rtl92e_writel(dev, INTA_MASK, - rtl92e_readl(dev, INTA_MASK) & ~IMR_RDU); - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & IMR_RXFOVW) - tasklet_schedule(&priv->irq_rx_tasklet); - - if (inta & IMR_BKDOK) { - priv->rtllib->link_detect_info.num_tx_ok_in_period++; - _rtl92e_tx_isr(dev, BK_QUEUE); - } - - if (inta & IMR_BEDOK) { - priv->rtllib->link_detect_info.num_tx_ok_in_period++; - _rtl92e_tx_isr(dev, BE_QUEUE); - } - - if (inta & IMR_VIDOK) { - priv->rtllib->link_detect_info.num_tx_ok_in_period++; - _rtl92e_tx_isr(dev, VI_QUEUE); - } - - if (inta & IMR_VODOK) { - priv->rtllib->link_detect_info.num_tx_ok_in_period++; - _rtl92e_tx_isr(dev, VO_QUEUE); - } - - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - -done: - - return IRQ_HANDLED; -} - -/**************************************************************************** - * ---------------------------- PCI_STUFF--------------------------- - ****************************************************************************/ -static const struct net_device_ops rtl8192_netdev_ops = { - .ndo_open = _rtl92e_open, - .ndo_stop = _rtl92e_close, - .ndo_tx_timeout = _rtl92e_tx_timeout, - .ndo_set_rx_mode = _rtl92e_set_multicast, - .ndo_set_mac_address = _rtl92e_set_mac_adr, - .ndo_validate_addr = eth_validate_addr, - .ndo_start_xmit = rtllib_xmit, -}; - -static int _rtl92e_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long ioaddr = 0; - struct net_device *dev = NULL; - struct r8192_priv *priv = NULL; - unsigned long pmem_start, pmem_len, pmem_flags; - int err = -ENOMEM; - - if (pci_enable_device(pdev)) { - dev_err(&pdev->dev, "Failed to enable PCI device"); - return -EIO; - } - - pci_set_master(pdev); - - if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { - if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) { - dev_info(&pdev->dev, - "Unable to obtain 32bit DMA for consistent allocations\n"); - goto err_pci_disable; - } - } - dev = alloc_rtllib(sizeof(struct r8192_priv)); - if (!dev) - goto err_pci_disable; - - err = -ENODEV; - - pci_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); - priv = rtllib_priv(dev); - priv->rtllib = (struct rtllib_device *)netdev_priv_rsl(dev); - priv->pdev = pdev; - priv->rtllib->pdev = pdev; - if ((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK) && - (pdev->subsystem_device == 0x3304)) - priv->rtllib->bSupportRemoteWakeUp = 1; - else - priv->rtllib->bSupportRemoteWakeUp = 0; - - pmem_start = pci_resource_start(pdev, 1); - pmem_len = pci_resource_len(pdev, 1); - pmem_flags = pci_resource_flags(pdev, 1); - - if (!(pmem_flags & IORESOURCE_MEM)) { - netdev_err(dev, "region #1 not a MMIO resource, aborting"); - goto err_rel_rtllib; - } - - dev_info(&pdev->dev, "Memory mapped space start: 0x%08lx\n", - pmem_start); - if (!request_mem_region(pmem_start, pmem_len, DRV_NAME)) { - netdev_err(dev, "request_mem_region failed!"); - goto err_rel_rtllib; - } - - ioaddr = (unsigned long)ioremap(pmem_start, pmem_len); - if (ioaddr == (unsigned long)NULL) { - netdev_err(dev, "ioremap failed!"); - goto err_rel_mem; - } - - dev->mem_start = ioaddr; - dev->mem_end = ioaddr + pci_resource_len(pdev, 0); - - if (!rtl92e_check_adapter(pdev, dev)) - goto err_unmap; - - dev->irq = pdev->irq; - priv->irq = 0; - - dev->netdev_ops = &rtl8192_netdev_ops; - - dev->wireless_handlers = &r8192_wx_handlers_def; - dev->ethtool_ops = &rtl819x_ethtool_ops; - - dev->type = ARPHRD_ETHER; - dev->watchdog_timeo = HZ * 3; - - if (dev_alloc_name(dev, ifname) < 0) - dev_alloc_name(dev, ifname); - - if (_rtl92e_init(dev) != 0) { - netdev_warn(dev, "Initialization failed"); - goto err_free_irq; - } - - netif_carrier_off(dev); - netif_stop_queue(dev); - - if (register_netdev(dev)) - goto err_free_irq; - - if (priv->polling_timer_on == 0) - rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer); - - return 0; - -err_free_irq: - free_irq(dev->irq, dev); - priv->irq = 0; -err_unmap: - iounmap((void __iomem *)ioaddr); -err_rel_mem: - release_mem_region(pmem_start, pmem_len); -err_rel_rtllib: - free_rtllib(dev); -err_pci_disable: - pci_disable_device(pdev); - return err; -} - -static void _rtl92e_pci_disconnect(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct r8192_priv *priv; - u32 i; - - if (dev) { - unregister_netdev(dev); - - priv = rtllib_priv(dev); - - del_timer_sync(&priv->gpio_polling_timer); - cancel_delayed_work_sync(&priv->gpio_change_rf_wq); - priv->polling_timer_on = 0; - _rtl92e_down(dev, true); - rtl92e_dm_deinit(dev); - vfree(priv->fw_info); - priv->fw_info = NULL; - _rtl92e_free_rx_ring(dev); - for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) - _rtl92e_free_tx_ring(dev, i); - - if (priv->irq) { - dev_info(&pdev->dev, "Freeing irq %d\n", dev->irq); - free_irq(dev->irq, dev); - priv->irq = 0; - } - - if (dev->mem_start != 0) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } - - free_rtllib(dev); - } - - pci_disable_device(pdev); -} - -bool rtl92e_enable_nic(struct net_device *dev) -{ - bool init_status = true; - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - (&priv->rtllib->pwr_save_ctrl); - - if (!priv->up) { - netdev_warn(dev, "%s(): Driver is already down!\n", __func__); - return false; - } - - init_status = rtl92e_start_adapter(dev); - if (!init_status) { - netdev_warn(dev, "%s(): Initialization failed!\n", __func__); - return false; - } - RT_CLEAR_PS_LEVEL(psc, RT_RF_OFF_LEVL_HALT_NIC); - - rtl92e_irq_enable(dev); - return init_status; -} - -module_pci_driver(rtl8192_pci_driver); - -void rtl92e_check_rfctrl_gpio_timer(struct timer_list *t) -{ - struct r8192_priv *priv = from_timer(priv, t, gpio_polling_timer); - - priv->polling_timer_on = 1; - - schedule_delayed_work(&priv->gpio_change_rf_wq, 0); - - mod_timer(&priv->gpio_polling_timer, jiffies + - msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME)); -} - -/*************************************************************************** - * ------------------- module init / exit stubs ---------------- - ***************************************************************************/ -MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); -MODULE_VERSION(DRV_VERSION); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(RTL8192E_BOOT_IMG_FW); -MODULE_FIRMWARE(RTL8192E_MAIN_IMG_FW); -MODULE_FIRMWARE(RTL8192E_DATA_IMG_FW); - -module_param(ifname, charp, 0644); -module_param(hwwep, int, 0644); - -MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default"); -MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support(default use hw. set 0 to use software security)"); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h deleted file mode 100644 index 8297d7e59415..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h +++ /dev/null @@ -1,402 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL_CORE_H -#define _RTL_CORE_H - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/etherdevice.h> -#include <linux/delay.h> -#include <linux/rtnetlink.h> -#include <linux/wireless.h> -#include <linux/timer.h> -#include <linux/proc_fs.h> -#include <linux/if_arp.h> -#include <linux/random.h> -#include <linux/io.h> - -/* Need this defined before including local include files */ -#define DRV_NAME "rtl819xE" - -#include "../rtllib.h" - -#include "r8192E_firmware.h" -#include "r8192E_hw.h" - -#include "r8190P_def.h" -#include "r8192E_dev.h" - -#include "rtl_eeprom.h" -#include "rtl_ps.h" -#include "rtl_pci.h" -#include "rtl_cam.h" - -#define DRV_COPYRIGHT \ - "Copyright(c) 2008 - 2010 Realsil Semiconductor Corporation" -#define DRV_AUTHOR "<wlanfae@realtek.com>" -#define DRV_VERSION "0014.0401.2010" - -#define TOTAL_CAM_ENTRY 32 -#define CAM_CONTENT_COUNT 8 - -#define HAL_HW_PCI_REVISION_ID_8192PCIE 0x01 -#define HAL_HW_PCI_REVISION_ID_8192SE 0x10 - -#define RTLLIB_WATCH_DOG_TIME 2000 - -#define MAX_DEV_ADDR_SIZE 8 /*support till 64 bit bus width OS*/ -#define MAX_FIRMWARE_INFORMATION_SIZE 32 -#define MAX_802_11_HEADER_LENGTH (40 + MAX_FIRMWARE_INFORMATION_SIZE) -#define ENCRYPTION_MAX_OVERHEAD 128 -#define MAX_FRAGMENT_COUNT 8 -#define MAX_TRANSMIT_BUFFER_SIZE \ - (1600 + (MAX_802_11_HEADER_LENGTH + ENCRYPTION_MAX_OVERHEAD) * \ - MAX_FRAGMENT_COUNT) - -#define CMDPACKET_FRAG_SIZE (4 * (MAX_TRANSMIT_BUFFER_SIZE / 4) - 8) - -#define DEFAULT_FRAG_THRESHOLD 2342U -#define MIN_FRAG_THRESHOLD 256U -#define DEFAULT_BEACONINTERVAL 0x64U - -#define DEFAULT_RETRY_RTS 7 -#define DEFAULT_RETRY_DATA 7 - -#define PHY_RSSI_SLID_WIN_MAX 100 - -#define TX_BB_GAIN_TABLE_LEN 37 -#define CCK_TX_BB_GAIN_TABLE_LEN 23 - -#define CHANNEL_PLAN_LEN 10 -#define S_CRC_LEN 4 - -#define NIC_SEND_HANG_THRESHOLD_NORMAL 4 -#define NIC_SEND_HANG_THRESHOLD_POWERSAVE 8 - -#define MAX_TX_QUEUE 9 - -#define MAX_RX_COUNT 64 -#define MAX_TX_QUEUE_COUNT 9 - -extern int hwwep; - -enum nic_t { - NIC_UNKNOWN = 0, - NIC_8192E = 1, - NIC_8190P = 2, - NIC_8192SE = 4, - NIC_8192CE = 5, - NIC_8192CU = 6, - NIC_8192DE = 7, - NIC_8192DU = 8, -}; - -enum rt_eeprom_type { - EEPROM_93C46, - EEPROM_93C56, -}; - -enum dcmg_txcmd_op { - TXCMD_TXRA_HISTORY_CTRL = 0xFF900000, - TXCMD_RESET_TX_PKT_BUFF = 0xFF900001, - TXCMD_RESET_RX_PKT_BUFF = 0xFF900002, - TXCMD_SET_TX_DURATION = 0xFF900003, - TXCMD_SET_RX_RSSI = 0xFF900004, - TXCMD_SET_TX_PWR_TRACKING = 0xFF900005, - TXCMD_XXXX_CTRL, -}; - -enum rt_customer_id { - RT_CID_DEFAULT = 0, - RT_CID_TOSHIBA = 9, - RT_CID_819X_NETCORE = 10, -}; - -enum reset_type { - RESET_TYPE_NORESET = 0x00, - RESET_TYPE_SILENT = 0x02 -}; - -struct rt_stats { - unsigned long received_rate_histogram[4][32]; - unsigned long txbytesunicast; - unsigned long rxbytesunicast; - unsigned long txretrycount; - u8 last_packet_rate; - unsigned long slide_signal_strength[100]; - unsigned long slide_evm[100]; - unsigned long slide_rssi_total; - unsigned long slide_evm_total; - long signal_strength; - long last_signal_strength_inpercent; - long recv_signal_power; - u8 rx_rssi_percentage[4]; - u8 rx_evm_percentage[2]; - u32 slide_beacon_pwdb[100]; - u32 slide_beacon_total; - u32 CurrentShowTxate; -}; - -struct init_gain { - u8 xaagccore1; - u8 xbagccore1; - u8 xcagccore1; - u8 xdagccore1; - u8 cca; - -}; - -struct tx_ring { - u32 *desc; - u8 nStuckCount; - struct tx_ring *next; -} __packed; - -struct rtl8192_tx_ring { - struct tx_desc *desc; - dma_addr_t dma; - unsigned int idx; - unsigned int entries; - struct sk_buff_head queue; -}; - -struct r8192_priv { - struct pci_dev *pdev; - struct pci_dev *bridge_pdev; - - bool bfirst_after_down; - bool being_init_adapter; - - int irq; - short irq_enabled; - - short up; - short up_first_time; - struct delayed_work update_beacon_wq; - struct delayed_work watch_dog_wq; - struct delayed_work txpower_tracking_wq; - struct delayed_work rfpath_check_wq; - struct delayed_work gpio_change_rf_wq; - struct rtllib_device *rtllib; - - struct work_struct reset_wq; - - enum rt_customer_id customer_id; - - enum ht_channel_width current_chnl_bw; - struct bb_reg_definition phy_reg_def[4]; - struct rate_adaptive rate_adaptive; - - struct rt_firmware *fw_info; - enum rtl819x_loopback loopback_mode; - - struct timer_list watch_dog_timer; - struct timer_list fsync_timer; - struct timer_list gpio_polling_timer; - - spinlock_t irq_th_lock; - spinlock_t tx_lock; - spinlock_t rf_ps_lock; - spinlock_t ps_lock; - - struct sk_buff_head skb_queue; - - struct tasklet_struct irq_rx_tasklet; - struct tasklet_struct irq_tx_tasklet; - - struct mutex wx_mutex; - struct mutex rf_mutex; - struct mutex mutex; - - struct rt_stats stats; - struct iw_statistics wstats; - - struct rx_desc *rx_ring; - struct sk_buff *rx_buf[MAX_RX_COUNT]; - dma_addr_t rx_ring_dma; - unsigned int rx_idx; - int rxringcount; - u16 rxbuffersize; - - u32 receive_config; - u8 retry_data; - u8 retry_rts; - u16 rts; - - struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT]; - int txringcount; - atomic_t tx_pending[0x10]; - - u16 short_retry_limit; - u16 long_retry_limit; - - bool hw_radio_off; - bool blinked_ingpio; - u8 polling_timer_on; - - /**********************************************************/ - struct work_struct qos_activate; - - short promisc; - - short chan; - - u32 irq_mask[2]; - - u8 rf_mode; - enum nic_t card_8192; - u8 card_8192_version; - - u8 ic_cut; - char nick[IW_ESSID_MAX_SIZE + 1]; - u8 check_roaming_cnt; - - u32 silent_reset_rx_slot_index; - u32 silent_reset_rx_stuck_event[MAX_SILENT_RESET_RX_SLOT_NUM]; - - u16 basic_rate; - u8 short_preamble; - u8 dot11_current_preamble_mode; - u8 slot_time; - - bool autoload_fail_flag; - - short epromtype; - u16 eeprom_vid; - u16 eeprom_did; - u8 eeprom_customer_id; - - u8 eeprom_tx_pwr_level_cck[14]; - u8 eeprom_tx_pwr_level_ofdm24g[14]; - u16 eeprom_ant_pwr_diff; - u8 eeprom_thermal_meter; - u8 eeprom_crystal_cap; - - u8 eeprom_legacy_ht_tx_pwr_diff; - - u8 crystal_cap; - u8 thermal_meter[2]; - - u8 sw_chnl_in_progress; - u8 sw_chnl_stage; - u8 sw_chnl_step; - u8 set_bw_mode_in_progress; - - u8 n_cur_40mhz_prime_sc; - - u32 rf_reg_0value[4]; - u8 num_total_rf_path; - bool brfpath_rxenable[RF90_PATH_MAX]; - - bool tx_pwr_data_read_from_eeprom; - - u8 hw_rf_off_action; - - bool rf_change_in_progress; - bool set_rf_pwr_state_in_progress; - - u8 cck_pwr_enl; - u16 tssi_13dBm; - u32 pwr_track; - u8 cck_present_attn_20m_def; - u8 cck_present_attn_40m_def; - s8 cck_present_attn_diff; - s8 cck_present_attn; - long undecorated_smoothed_pwdb; - - u32 mcs_tx_pwr_level_org_offset[6]; - u8 tx_pwr_level_cck[14]; - u8 tx_pwr_level_ofdm_24g[14]; - u8 legacy_ht_tx_pwr_diff; - u8 antenna_tx_pwr_diff[3]; - - bool dynamic_tx_high_pwr; - bool dynamic_tx_low_pwr; - bool last_dtp_flag_high; - bool last_dtp_flag_low; - - u8 rfa_txpowertrackingindex; - u8 rfa_txpowertrackingindex_real; - u8 rfa_txpowertracking_default; - bool btxpower_tracking; - bool bcck_in_ch14; - - u8 txpower_count; - bool tx_pwr_tracking_init; - - u8 ofdm_index[2]; - u8 cck_index; - - u8 rec_cck_20m_idx; - u8 rec_cck_40m_idx; - - struct init_gain initgain_backup; - u8 def_initial_gain[4]; - bool bis_any_nonbepkts; - bool bcurrent_turbo_EDCA; - bool bis_cur_rdlstate; - - u32 rate_record; - u32 rate_count_diff_rec; - u32 continue_diff_count; - bool bswitch_fsync; - u8 framesync; - - u16 tx_counter; - u16 rx_ctr; -}; - -extern const struct ethtool_ops rtl819x_ethtool_ops; - -u8 rtl92e_readb(struct net_device *dev, int x); -u32 rtl92e_readl(struct net_device *dev, int x); -u16 rtl92e_readw(struct net_device *dev, int x); -void rtl92e_writeb(struct net_device *dev, int x, u8 y); -void rtl92e_writew(struct net_device *dev, int x, u16 y); -void rtl92e_writel(struct net_device *dev, int x, u32 y); - -void force_pci_posting(struct net_device *dev); - -void rtl92e_rx_enable(struct net_device *dev); -void rtl92e_tx_enable(struct net_device *dev); - -void rtl92e_hw_sleep_wq(void *data); -void rtl92e_commit(struct net_device *dev); - -void rtl92e_check_rfctrl_gpio_timer(struct timer_list *t); - -void rtl92e_hw_wakeup_wq(void *data); - -void rtl92e_reset_desc_ring(struct net_device *dev); -void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode); -void rtl92e_irq_enable(struct net_device *dev); -void rtl92e_config_rate(struct net_device *dev, u16 *rate_config); -void rtl92e_irq_disable(struct net_device *dev); - -long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index); -void rtl92e_update_rx_statistics(struct r8192_priv *priv, - struct rtllib_rx_stats *pprevious_stats); -u8 rtl92e_evm_db_to_percent(s8 value); -u8 rtl92e_rx_db_to_percent(s8 antpower); -void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats, - struct rtllib_rx_stats *ptarget_stats); -bool rtl92e_enable_nic(struct net_device *dev); - -bool rtl92e_set_rf_state(struct net_device *dev, - enum rt_rf_power_state state_to_set, - RT_RF_CHANGE_SOURCE change_source); -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c deleted file mode 100644 index e9ca5a8768ad..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ /dev/null @@ -1,1856 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "rtl_dm.h" -#include "r8192E_hw.h" -#include "r8192E_phy.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" -#include "r8192E_cmdpkt.h" - -/*---------------------------Define Local Constant---------------------------*/ -static u32 edca_setting_DL[HT_IOT_PEER_MAX] = { - 0x5e4322, - 0x5e4322, - 0x5ea44f, - 0x5e4322, - 0x604322, - 0xa44f, - 0x5e4322, - 0x5e4332 -}; - -static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = { - 0x5e4322, - 0x5e4322, - 0x5e4322, - 0x5e4322, - 0x604322, - 0xa44f, - 0x5e4322, - 0x5e4322 -}; - -static u32 edca_setting_UL[HT_IOT_PEER_MAX] = { - 0x5e4322, - 0xa44f, - 0x5ea44f, - 0x5e4322, - 0x604322, - 0x5e4322, - 0x5e4322, - 0x5e4332 -}; - -const u32 dm_tx_bb_gain[TX_BB_GAIN_TABLE_LEN] = { - 0x7f8001fe, /* 12 dB */ - 0x788001e2, /* 11 dB */ - 0x71c001c7, - 0x6b8001ae, - 0x65400195, - 0x5fc0017f, - 0x5a400169, - 0x55400155, - 0x50800142, - 0x4c000130, - 0x47c0011f, - 0x43c0010f, - 0x40000100, - 0x3c8000f2, - 0x390000e4, - 0x35c000d7, - 0x32c000cb, - 0x300000c0, - 0x2d4000b5, - 0x2ac000ab, - 0x288000a2, - 0x26000098, - 0x24000090, - 0x22000088, - 0x20000080, - 0x1a00006c, - 0x1c800072, - 0x18000060, - 0x19800066, - 0x15800056, - 0x26c0005b, - 0x14400051, - 0x24400051, - 0x1300004c, - 0x12000048, - 0x11000044, - 0x10000040, /* -24 dB */ -}; - -const u8 dm_cck_tx_bb_gain[CCK_TX_BB_GAIN_TABLE_LEN][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} -}; - -const u8 dm_cck_tx_bb_gain_ch14[CCK_TX_BB_GAIN_TABLE_LEN][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, - {0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00}, - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, - {0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00}, - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} -}; - -/*---------------------------Define Local Constant---------------------------*/ - - -/*------------------------Define global variable-----------------------------*/ -struct dig_t dm_digtable; - -static struct drx_path_sel dm_rx_path_sel_table; -/*------------------------Define global variable-----------------------------*/ - - -/*------------------------Define local variable------------------------------*/ -/*------------------------Define local variable------------------------------*/ - - - -/*---------------------Define local function prototype-----------------------*/ -static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev); - -static void _rtl92e_dm_init_bandwidth_autoswitch(struct net_device *dev); -static void _rtl92e_dm_bandwidth_autoswitch(struct net_device *dev); - -static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev); - -static void _rtl92e_dm_dig_init(struct net_device *dev); -static void _rtl92e_dm_ctrl_initgain_byrssi(struct net_device *dev); -static void _rtl92e_dm_initial_gain(struct net_device *dev); -static void _rtl92e_dm_pd_th(struct net_device *dev); -static void _rtl92e_dm_cs_ratio(struct net_device *dev); - -static void _rtl92e_dm_init_cts_to_self(struct net_device *dev); - -static void _rtl92e_dm_check_edca_turbo(struct net_device *dev); -static void _rtl92e_dm_check_rx_path_selection(struct net_device *dev); -static void _rtl92e_dm_init_rx_path_selection(struct net_device *dev); -static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev); - -static void _rtl92e_dm_init_fsync(struct net_device *dev); -static void _rtl92e_dm_deinit_fsync(struct net_device *dev); - -static void _rtl92e_dm_check_txrateandretrycount(struct net_device *dev); -static void _rtl92e_dm_check_fsync(struct net_device *dev); -static void _rtl92e_dm_check_rf_ctrl_gpio(void *data); -static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t); - -/*---------------------Define local function prototype-----------------------*/ - -static void _rtl92e_dm_init_dynamic_tx_power(struct net_device *dev); -static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev); - -static void _rtl92e_dm_send_rssi_to_fw(struct net_device *dev); -static void _rtl92e_dm_cts_to_self(struct net_device *dev); -/*---------------------------Define function prototype------------------------*/ - -void rtl92e_dm_init(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->undecorated_smoothed_pwdb = -1; - - _rtl92e_dm_init_dynamic_tx_power(dev); - - rtl92e_init_adaptive_rate(dev); - - _rtl92e_dm_dig_init(dev); - rtl92e_dm_init_edca_turbo(dev); - _rtl92e_dm_init_bandwidth_autoswitch(dev); - _rtl92e_dm_init_fsync(dev); - _rtl92e_dm_init_rx_path_selection(dev); - _rtl92e_dm_init_cts_to_self(dev); - - INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, (void *)_rtl92e_dm_check_rf_ctrl_gpio); -} - -void rtl92e_dm_deinit(struct net_device *dev) -{ - _rtl92e_dm_deinit_fsync(dev); -} - -void rtl92e_dm_watchdog(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->being_init_adapter) - return; - - _rtl92e_dm_check_txrateandretrycount(dev); - _rtl92e_dm_check_edca_turbo(dev); - - _rtl92e_dm_check_rate_adaptive(dev); - _rtl92e_dm_dynamic_tx_power(dev); - _rtl92e_dm_check_tx_power_tracking(dev); - - _rtl92e_dm_ctrl_initgain_byrssi(dev); - _rtl92e_dm_bandwidth_autoswitch(dev); - - _rtl92e_dm_check_rx_path_selection(dev); - _rtl92e_dm_check_fsync(dev); - - _rtl92e_dm_send_rssi_to_fw(dev); - _rtl92e_dm_cts_to_self(dev); -} - -void rtl92e_init_adaptive_rate(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rate_adaptive *pra = &priv->rate_adaptive; - - pra->ratr_state = DM_RATR_STA_MAX; - pra->high2low_rssi_thresh_for_ra = RATE_ADAPTIVE_TH_HIGH; - pra->low2high_rssi_thresh_for_ra20M = RATE_ADAPTIVE_TH_LOW_20M + 5; - pra->low2high_rssi_thresh_for_ra40M = RATE_ADAPTIVE_TH_LOW_40M + 5; - - pra->high_rssi_thresh_for_ra = RATE_ADAPTIVE_TH_HIGH + 5; - pra->low_rssi_thresh_for_ra20M = RATE_ADAPTIVE_TH_LOW_20M; - pra->low_rssi_thresh_for_ra40M = RATE_ADAPTIVE_TH_LOW_40M; - - if (priv->customer_id == RT_CID_819X_NETCORE) - pra->ping_rssi_enable = 1; - else - pra->ping_rssi_enable = 0; - pra->ping_rssi_thresh_for_ra = 15; - - pra->upper_rssi_threshold_ratr = 0x000fc000; - pra->middle_rssi_threshold_ratr = 0x000ff000; - pra->low_rssi_threshold_ratr = 0x000ff001; - pra->low_rssi_threshold_ratr_40M = 0x000ff005; - pra->low_rssi_threshold_ratr_20M = 0x000ff001; - pra->ping_rssi_ratr = 0x0000000d; -} - -static void _rtl92e_dm_check_rate_adaptive(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_hi_throughput *ht_info = priv->rtllib->ht_info; - struct rate_adaptive *pra = &priv->rate_adaptive; - u32 current_ratr, target_ratr = 0; - u32 low_rssi_thresh_for_ra = 0, high_rssi_thresh_for_ra = 0; - bool bshort_gi_enabled = false; - static u8 ping_rssi_state; - - if (!priv->up) - return; - - if (priv->rtllib->mode != WIRELESS_MODE_N_24G) - return; - - if (priv->rtllib->link_state == MAC80211_LINKED) { - bshort_gi_enabled = (ht_info->cur_tx_bw40mhz && - ht_info->cur_short_gi_40mhz) || - (!ht_info->cur_tx_bw40mhz && - ht_info->cur_short_gi_20mhz); - - pra->upper_rssi_threshold_ratr = - (pra->upper_rssi_threshold_ratr & (~BIT(31))) | - ((bshort_gi_enabled) ? BIT(31) : 0); - - pra->middle_rssi_threshold_ratr = - (pra->middle_rssi_threshold_ratr & (~BIT(31))) | - ((bshort_gi_enabled) ? BIT(31) : 0); - - if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) { - pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_40M & (~BIT(31))) | - ((bshort_gi_enabled) ? BIT(31) : 0); - } else { - pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_20M & (~BIT(31))) | - ((bshort_gi_enabled) ? BIT(31) : 0); - } - pra->ping_rssi_ratr = - (pra->ping_rssi_ratr & (~BIT(31))) | - ((bshort_gi_enabled) ? BIT(31) : 0); - - if (pra->ratr_state == DM_RATR_STA_HIGH) { - high_rssi_thresh_for_ra = pra->high2low_rssi_thresh_for_ra; - low_rssi_thresh_for_ra = (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) ? - (pra->low_rssi_thresh_for_ra40M) : (pra->low_rssi_thresh_for_ra20M); - } else if (pra->ratr_state == DM_RATR_STA_LOW) { - high_rssi_thresh_for_ra = pra->high_rssi_thresh_for_ra; - low_rssi_thresh_for_ra = (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) ? - (pra->low2high_rssi_thresh_for_ra40M) : (pra->low2high_rssi_thresh_for_ra20M); - } else { - high_rssi_thresh_for_ra = pra->high_rssi_thresh_for_ra; - low_rssi_thresh_for_ra = (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) ? - (pra->low_rssi_thresh_for_ra40M) : (pra->low_rssi_thresh_for_ra20M); - } - - if (priv->undecorated_smoothed_pwdb >= - (long)high_rssi_thresh_for_ra) { - pra->ratr_state = DM_RATR_STA_HIGH; - target_ratr = pra->upper_rssi_threshold_ratr; - } else if (priv->undecorated_smoothed_pwdb >= - (long)low_rssi_thresh_for_ra) { - pra->ratr_state = DM_RATR_STA_MIDDLE; - target_ratr = pra->middle_rssi_threshold_ratr; - } else { - pra->ratr_state = DM_RATR_STA_LOW; - target_ratr = pra->low_rssi_threshold_ratr; - } - - if (pra->ping_rssi_enable) { - if (priv->undecorated_smoothed_pwdb < - (long)(pra->ping_rssi_thresh_for_ra + 5)) { - if ((priv->undecorated_smoothed_pwdb < - (long)pra->ping_rssi_thresh_for_ra) || - ping_rssi_state) { - pra->ratr_state = DM_RATR_STA_LOW; - target_ratr = pra->ping_rssi_ratr; - ping_rssi_state = 1; - } - } else { - ping_rssi_state = 0; - } - } - - if (priv->rtllib->get_half_nmode_support_by_aps_handler(dev)) - target_ratr &= 0xf00fffff; - - current_ratr = rtl92e_readl(dev, RATR0); - if (target_ratr != current_ratr) { - u32 ratr_value; - - ratr_value = target_ratr; - ratr_value &= ~(RATE_ALL_OFDM_2SS); - rtl92e_writel(dev, RATR0, ratr_value); - rtl92e_writeb(dev, UFWP, 1); - } - - } else { - pra->ratr_state = DM_RATR_STA_MAX; - } -} - -static void _rtl92e_dm_init_bandwidth_autoswitch(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH; - priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW; - priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = false; - priv->rtllib->bandwidth_auto_switch.bautoswitch_enable = false; -} - -static void _rtl92e_dm_bandwidth_autoswitch(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->current_chnl_bw == HT_CHANNEL_WIDTH_20 || - !priv->rtllib->bandwidth_auto_switch.bautoswitch_enable) - return; - if (!priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz) { - if (priv->undecorated_smoothed_pwdb <= - priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz) - priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = true; - } else { - if (priv->undecorated_smoothed_pwdb >= - priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz) - priv->rtllib->bandwidth_auto_switch.forced_tx_20MHz = false; - } -} - -static u32 OFDMSwingTable[OFDM_TABLE_LEN] = { - 0x7f8001fe, - 0x71c001c7, - 0x65400195, - 0x5a400169, - 0x50800142, - 0x47c0011f, - 0x40000100, - 0x390000e4, - 0x32c000cb, - 0x2d4000b5, - 0x288000a2, - 0x24000090, - 0x20000080, - 0x1c800072, - 0x19800066, - 0x26c0005b, - 0x24400051, - 0x12000048, - 0x10000040 -}; - -static u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_LEN][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} -}; - -static u8 CCKSwingTable_Ch14[CCK_TABLE_LEN][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} -}; - -#define Pw_Track_Flag 0x11d -#define Tssi_Mea_Value 0x13c -#define Tssi_Report_Value1 0x134 -#define Tssi_Report_Value2 0x13e -#define FW_Busy_Flag 0x13f - -static void _rtl92e_dm_tx_update_tssi_weak_signal(struct net_device *dev) -{ - struct r8192_priv *p = rtllib_priv(dev); - - if (p->rfa_txpowertrackingindex > 0) { - p->rfa_txpowertrackingindex--; - if (p->rfa_txpowertrackingindex_real > 4) { - p->rfa_txpowertrackingindex_real--; - rtl92e_set_bb_reg(dev, - rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); - } - } else { - rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, dm_tx_bb_gain[4]); - } -} - -static void _rtl92e_dm_tx_update_tssi_strong_signal(struct net_device *dev) -{ - struct r8192_priv *p = rtllib_priv(dev); - - if (p->rfa_txpowertrackingindex < (TX_BB_GAIN_TABLE_LEN - 1)) { - p->rfa_txpowertrackingindex++; - p->rfa_txpowertrackingindex_real++; - rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]); - } else { - rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord, - dm_tx_bb_gain[TX_BB_GAIN_TABLE_LEN - 1]); - } -} - -static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - bool viviflag = false; - struct dcmd_txcmd tx_cmd; - int i = 0, j = 0, k = 0; - u8 tmp_report[5] = {0, 0, 0, 0, 0}; - u8 Pwr_Flag; - u16 Avg_TSSI_Meas, tssi_13dBm, Avg_TSSI_Meas_from_driver = 0; - u32 delta = 0; - - rtl92e_writeb(dev, Pw_Track_Flag, 0); - rtl92e_writeb(dev, FW_Busy_Flag, 0); - priv->rtllib->bdynamic_txpower_enable = false; - - for (j = 0; j <= 30; j++) { - tx_cmd.op = TXCMD_SET_TX_PWR_TRACKING; - tx_cmd.length = 4; - tx_cmd.value = priv->pwr_track >> 24; - rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_NORMAL, (u8 *)&tx_cmd, - sizeof(struct dcmd_txcmd)); - mdelay(1); - for (i = 0; i <= 30; i++) { - Pwr_Flag = rtl92e_readb(dev, Pw_Track_Flag); - - if (Pwr_Flag == 0) { - mdelay(1); - - if (priv->rtllib->rf_power_state != rf_on) { - rtl92e_writeb(dev, Pw_Track_Flag, 0); - rtl92e_writeb(dev, FW_Busy_Flag, 0); - return; - } - - continue; - } - - Avg_TSSI_Meas = rtl92e_readw(dev, Tssi_Mea_Value); - - if (Avg_TSSI_Meas == 0) { - rtl92e_writeb(dev, Pw_Track_Flag, 0); - rtl92e_writeb(dev, FW_Busy_Flag, 0); - return; - } - - for (k = 0; k < 5; k++) { - if (k != 4) - tmp_report[k] = rtl92e_readb(dev, - Tssi_Report_Value1 + k); - else - tmp_report[k] = rtl92e_readb(dev, - Tssi_Report_Value2); - - if (tmp_report[k] <= 20) { - viviflag = true; - break; - } - } - - if (viviflag) { - rtl92e_writeb(dev, Pw_Track_Flag, 0); - viviflag = false; - for (k = 0; k < 5; k++) - tmp_report[k] = 0; - break; - } - - for (k = 0; k < 5; k++) - Avg_TSSI_Meas_from_driver += tmp_report[k]; - - Avg_TSSI_Meas_from_driver *= 100 / 5; - tssi_13dBm = priv->tssi_13dBm; - - if (Avg_TSSI_Meas_from_driver > tssi_13dBm) - delta = Avg_TSSI_Meas_from_driver - tssi_13dBm; - else - delta = tssi_13dBm - Avg_TSSI_Meas_from_driver; - - if (delta <= E_FOR_TX_POWER_TRACK) { - priv->rtllib->bdynamic_txpower_enable = true; - rtl92e_writeb(dev, Pw_Track_Flag, 0); - rtl92e_writeb(dev, FW_Busy_Flag, 0); - return; - } - if (Avg_TSSI_Meas_from_driver < tssi_13dBm - E_FOR_TX_POWER_TRACK) - _rtl92e_dm_tx_update_tssi_weak_signal(dev); - else - _rtl92e_dm_tx_update_tssi_strong_signal(dev); - - priv->cck_present_attn_diff - = priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default; - - if (priv->current_chnl_bw == HT_CHANNEL_WIDTH_20) - priv->cck_present_attn = - priv->cck_present_attn_20m_def + - priv->cck_present_attn_diff; - else - priv->cck_present_attn = - priv->cck_present_attn_40m_def + - priv->cck_present_attn_diff; - - if (priv->cck_present_attn > (CCK_TX_BB_GAIN_TABLE_LEN - 1)) - priv->cck_present_attn = CCK_TX_BB_GAIN_TABLE_LEN - 1; - if (priv->cck_present_attn < 0) - priv->cck_present_attn = 0; - - if (priv->cck_present_attn > -1 && - priv->cck_present_attn < CCK_TX_BB_GAIN_TABLE_LEN) { - if (priv->rtllib->current_network.channel == 14 && - !priv->bcck_in_ch14) { - priv->bcck_in_ch14 = true; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) { - priv->bcck_in_ch14 = false; - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else { - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } - } - - if (priv->cck_present_attn_diff <= -12 || - priv->cck_present_attn_diff >= 24) { - priv->rtllib->bdynamic_txpower_enable = true; - rtl92e_writeb(dev, Pw_Track_Flag, 0); - rtl92e_writeb(dev, FW_Busy_Flag, 0); - return; - } - - rtl92e_writeb(dev, Pw_Track_Flag, 0); - Avg_TSSI_Meas_from_driver = 0; - for (k = 0; k < 5; k++) - tmp_report[k] = 0; - break; - } - rtl92e_writeb(dev, FW_Busy_Flag, 0); - } - priv->rtllib->bdynamic_txpower_enable = true; - rtl92e_writeb(dev, Pw_Track_Flag, 0); -} - -static void _rtl92e_dm_tx_power_tracking_cb_thermal(struct net_device *dev) -{ -#define ThermalMeterVal 9 - struct r8192_priv *priv = rtllib_priv(dev); - u32 tmp_reg, tmp_cck; - u8 tmp_ofdm_index, tmp_cck_index, tmp_cck_20m_index, tmp_cck_40m_index, tmpval; - int i = 0, CCKSwingNeedUpdate = 0; - - if (!priv->tx_pwr_tracking_init) { - tmp_reg = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance, - bMaskDWord); - for (i = 0; i < OFDM_TABLE_LEN; i++) { - if (tmp_reg == OFDMSwingTable[i]) - priv->ofdm_index[0] = i; - } - - tmp_cck = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2); - for (i = 0; i < CCK_TABLE_LEN; i++) { - if (tmp_cck == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { - priv->cck_index = i; - break; - } - } - priv->tx_pwr_tracking_init = true; - return; - } - - tmp_reg = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078); - if (tmp_reg < 3 || tmp_reg > 13) - return; - if (tmp_reg >= 12) - tmp_reg = 12; - priv->thermal_meter[0] = ThermalMeterVal; - priv->thermal_meter[1] = ThermalMeterVal; - - if (priv->thermal_meter[0] >= (u8)tmp_reg) { - tmp_ofdm_index = 6 + (priv->thermal_meter[0] - (u8)tmp_reg); - tmp_cck_20m_index = tmp_ofdm_index; - tmp_cck_40m_index = tmp_cck_20m_index - 6; - if (tmp_ofdm_index >= OFDM_TABLE_LEN) - tmp_ofdm_index = OFDM_TABLE_LEN - 1; - if (tmp_cck_20m_index >= CCK_TABLE_LEN) - tmp_cck_20m_index = CCK_TABLE_LEN - 1; - if (tmp_cck_40m_index >= CCK_TABLE_LEN) - tmp_cck_40m_index = CCK_TABLE_LEN - 1; - } else { - tmpval = (u8)tmp_reg - priv->thermal_meter[0]; - if (tmpval >= 6) { - tmp_ofdm_index = 0; - tmp_cck_20m_index = 0; - } else { - tmp_ofdm_index = 6 - tmpval; - tmp_cck_20m_index = 6 - tmpval; - } - tmp_cck_40m_index = 0; - } - if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - tmp_cck_index = tmp_cck_40m_index; - else - tmp_cck_index = tmp_cck_20m_index; - - priv->rec_cck_20m_idx = tmp_cck_20m_index; - priv->rec_cck_40m_idx = tmp_cck_40m_index; - - if (priv->rtllib->current_network.channel == 14 && - !priv->bcck_in_ch14) { - priv->bcck_in_ch14 = true; - CCKSwingNeedUpdate = 1; - } else if (priv->rtllib->current_network.channel != 14 && - priv->bcck_in_ch14) { - priv->bcck_in_ch14 = false; - CCKSwingNeedUpdate = 1; - } - - if (priv->cck_index != tmp_cck_index) { - priv->cck_index = tmp_cck_index; - CCKSwingNeedUpdate = 1; - } - - if (CCKSwingNeedUpdate) - rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - if (priv->ofdm_index[0] != tmp_ofdm_index) { - priv->ofdm_index[0] = tmp_ofdm_index; - rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, - OFDMSwingTable[priv->ofdm_index[0]]); - } - priv->txpower_count = 0; -} - -void rtl92e_dm_txpower_tracking_wq(void *data) -{ - struct r8192_priv *priv = container_of_dwork_rsl(data, - struct r8192_priv, txpower_tracking_wq); - struct net_device *dev = priv->rtllib->dev; - - if (priv->ic_cut >= IC_VersionCut_D) - _rtl92e_dm_tx_power_tracking_callback_tssi(dev); - else - _rtl92e_dm_tx_power_tracking_cb_thermal(dev); -} - -static void _rtl92e_dm_initialize_tx_power_tracking_tssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->btxpower_tracking = true; - priv->txpower_count = 0; - priv->tx_pwr_tracking_init = false; -} - -static void _rtl92e_dm_init_tx_power_tracking_thermal(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->rtllib->FwRWRF) - priv->btxpower_tracking = true; - else - priv->btxpower_tracking = false; - priv->txpower_count = 0; - priv->tx_pwr_tracking_init = false; -} - -void rtl92e_dm_init_txpower_tracking(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->ic_cut >= IC_VersionCut_D) - _rtl92e_dm_initialize_tx_power_tracking_tssi(dev); - else - _rtl92e_dm_init_tx_power_tracking_thermal(dev); -} - -static void _rtl92e_dm_check_tx_power_tracking_tssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - static u32 tx_power_track_counter; - - if (rtl92e_readb(dev, 0x11e) == 1) - return; - if (!priv->btxpower_tracking) - return; - tx_power_track_counter++; - - if (tx_power_track_counter >= 180) { - schedule_delayed_work(&priv->txpower_tracking_wq, 0); - tx_power_track_counter = 0; - } -} - -static void _rtl92e_dm_check_tx_power_tracking_thermal(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - static u8 TM_Trigger; - u8 TxPowerCheckCnt = 0; - - TxPowerCheckCnt = 2; - if (!priv->btxpower_tracking) - return; - - if (priv->txpower_count <= TxPowerCheckCnt) { - priv->txpower_count++; - return; - } - - if (!TM_Trigger) { - rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); - rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); - rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); - rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); - TM_Trigger = 1; - return; - } - netdev_info(dev, "===============>Schedule TxPowerTrackingWorkItem\n"); - schedule_delayed_work(&priv->txpower_tracking_wq, 0); - TM_Trigger = 0; -} - -static void _rtl92e_dm_check_tx_power_tracking(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->ic_cut >= IC_VersionCut_D) - _rtl92e_dm_check_tx_power_tracking_tssi(dev); - else - _rtl92e_dm_check_tx_power_tracking_thermal(dev); -} - -static void _rtl92e_dm_cck_tx_power_adjust_tssi(struct net_device *dev, - bool bInCH14) -{ - u32 TempVal; - struct r8192_priv *priv = rtllib_priv(dev); - u8 attenuation = priv->cck_present_attn; - - TempVal = 0; - if (!bInCH14) { - TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][0] + - (dm_cck_tx_bb_gain[attenuation][1] << 8)); - - rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) + - (dm_cck_tx_bb_gain[attenuation][3] << 8) + - (dm_cck_tx_bb_gain[attenuation][4] << 16) + - (dm_cck_tx_bb_gain[attenuation][5] << 24)); - rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] + - (dm_cck_tx_bb_gain[attenuation][7] << 8)); - - rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } else { - TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][0]) + - (dm_cck_tx_bb_gain_ch14[attenuation][1] << 8)); - - rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) + - (dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) + - (dm_cck_tx_bb_gain_ch14[attenuation][4] << 16) + - (dm_cck_tx_bb_gain_ch14[attenuation][5] << 24)); - rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) + - (dm_cck_tx_bb_gain_ch14[attenuation][7] << 8)); - - rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } -} - -static void _rtl92e_dm_cck_tx_power_adjust_thermal_meter(struct net_device *dev, - bool bInCH14) -{ - u32 TempVal; - struct r8192_priv *priv = rtllib_priv(dev); - - TempVal = 0; - if (!bInCH14) { - TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][0] + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][1] << 8); - rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][2] + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][3] << 8) + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][4] << 16) + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][5] << 24); - rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - TempVal = CCKSwingTable_Ch1_Ch13[priv->cck_index][6] + - (CCKSwingTable_Ch1_Ch13[priv->cck_index][7] << 8); - - rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } else { - TempVal = CCKSwingTable_Ch14[priv->cck_index][0] + - (CCKSwingTable_Ch14[priv->cck_index][1] << 8); - - rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - TempVal = CCKSwingTable_Ch14[priv->cck_index][2] + - (CCKSwingTable_Ch14[priv->cck_index][3] << 8) + - (CCKSwingTable_Ch14[priv->cck_index][4] << 16) + - (CCKSwingTable_Ch14[priv->cck_index][5] << 24); - rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - TempVal = CCKSwingTable_Ch14[priv->cck_index][6] + - (CCKSwingTable_Ch14[priv->cck_index][7] << 8); - - rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } -} - -void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->ic_cut >= IC_VersionCut_D) - _rtl92e_dm_cck_tx_power_adjust_tssi(dev, binch14); - else - _rtl92e_dm_cck_tx_power_adjust_thermal_meter(dev, binch14); -} - -static void _rtl92e_dm_dig_init(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - dm_digtable.cur_sta_connect_state = DIG_STA_DISCONNECT; - dm_digtable.pre_sta_connect_state = DIG_STA_DISCONNECT; - - dm_digtable.rssi_low_thresh = DM_DIG_THRESH_LOW; - dm_digtable.rssi_high_thresh = DM_DIG_THRESH_HIGH; - - dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; - dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; - - dm_digtable.rssi_val = 50; - dm_digtable.backoff_val = DM_DIG_BACKOFF; - dm_digtable.rx_gain_range_max = DM_DIG_MAX; - if (priv->customer_id == RT_CID_819X_NETCORE) - dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore; - else - dm_digtable.rx_gain_range_min = DM_DIG_MIN; -} - -/*----------------------------------------------------------------------------- - * Function: dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm() - * - * Overview: Driver monitor RSSI and False Alarm to change initial gain. - Only change initial gain during link in progress. - * - * Input: IN PADAPTER pAdapter - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 03/04/2009 hpfan Create Version 0. - * - ******************************************************************************/ - -static void _rtl92e_dm_ctrl_initgain_byrssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 i; - static u8 fw_dig; - - if (fw_dig <= 3) { - for (i = 0; i < 3; i++) - rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8); - fw_dig++; - } - - if (priv->rtllib->link_state == MAC80211_LINKED) - dm_digtable.cur_sta_connect_state = DIG_STA_CONNECT; - else - dm_digtable.cur_sta_connect_state = DIG_STA_DISCONNECT; - - dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; - _rtl92e_dm_initial_gain(dev); - _rtl92e_dm_pd_th(dev); - _rtl92e_dm_cs_ratio(dev); - dm_digtable.pre_sta_connect_state = dm_digtable.cur_sta_connect_state; -} - -static void _rtl92e_dm_initial_gain(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 initial_gain = 0; - static u8 initialized, force_write; - - if (rtllib_act_scanning(priv->rtllib, true)) { - force_write = 1; - return; - } - - if (dm_digtable.pre_sta_connect_state == dm_digtable.cur_sta_connect_state) { - if (dm_digtable.cur_sta_connect_state == DIG_STA_CONNECT) { - long gain_range = dm_digtable.rssi_val + 10 - - dm_digtable.backoff_val; - gain_range = clamp_t(long, gain_range, - dm_digtable.rx_gain_range_min, - dm_digtable.rx_gain_range_max); - dm_digtable.cur_ig_value = gain_range; - } else { - if (dm_digtable.cur_ig_value == 0) - dm_digtable.cur_ig_value = priv->def_initial_gain[0]; - else - dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; - } - } else { - dm_digtable.cur_ig_value = priv->def_initial_gain[0]; - dm_digtable.pre_ig_value = 0; - } - - if (dm_digtable.pre_ig_value != rtl92e_readb(dev, rOFDM0_XAAGCCore1)) - force_write = 1; - - if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) - || !initialized || force_write) { - initial_gain = dm_digtable.cur_ig_value; - rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain); - rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain); - dm_digtable.pre_ig_value = dm_digtable.cur_ig_value; - initialized = 1; - force_write = 0; - } -} - -static void _rtl92e_dm_pd_th(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - static u8 initialized, force_write; - - if (dm_digtable.pre_sta_connect_state == dm_digtable.cur_sta_connect_state) { - if (dm_digtable.cur_sta_connect_state == DIG_STA_CONNECT) { - if (dm_digtable.rssi_val >= - dm_digtable.rssi_high_power_highthresh) - dm_digtable.curpd_thstate = - DIG_PD_AT_HIGH_POWER; - else if (dm_digtable.rssi_val <= - dm_digtable.rssi_low_thresh) - dm_digtable.curpd_thstate = - DIG_PD_AT_LOW_POWER; - else if ((dm_digtable.rssi_val >= - dm_digtable.rssi_high_thresh) && - (dm_digtable.rssi_val < - dm_digtable.rssi_high_power_lowthresh)) - dm_digtable.curpd_thstate = - DIG_PD_AT_NORMAL_POWER; - else - dm_digtable.curpd_thstate = - dm_digtable.prepd_thstate; - } else { - dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; - } - } else { - dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; - } - - if ((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || - (initialized <= 3) || force_write) { - if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { - if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x00); - else - rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42); - } else if (dm_digtable.curpd_thstate == - DIG_PD_AT_NORMAL_POWER) { - if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x20); - else - rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44); - } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { - if (priv->current_chnl_bw != HT_CHANNEL_WIDTH_20) - rtl92e_writeb(dev, (rOFDM0_XATxAFE + 3), 0x10); - else - rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43); - } - dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; - if (initialized <= 3) - initialized++; - force_write = 0; - } -} - -static void _rtl92e_dm_cs_ratio(struct net_device *dev) -{ - static u8 initialized, force_write; - - if (dm_digtable.pre_sta_connect_state == dm_digtable.cur_sta_connect_state) { - if (dm_digtable.cur_sta_connect_state == DIG_STA_CONNECT) { - if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh) - dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) - dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; - else - dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; - } else { - dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - } - } else { - dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - } - - if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || - !initialized || force_write) { - if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) - rtl92e_writeb(dev, 0xa0a, 0x08); - else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) - rtl92e_writeb(dev, 0xa0a, 0xcd); - dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; - initialized = 1; - force_write = 0; - } -} - -void rtl92e_dm_init_edca_turbo(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->bcurrent_turbo_EDCA = false; - priv->rtllib->bis_any_nonbepkts = false; - priv->bis_cur_rdlstate = false; -} - -static void _rtl92e_dm_check_edca_turbo(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_hi_throughput *ht_info = priv->rtllib->ht_info; - - static unsigned long lastTxOkCnt; - static unsigned long lastRxOkCnt; - unsigned long curTxOkCnt = 0; - unsigned long curRxOkCnt = 0; - - if (priv->rtllib->link_state != MAC80211_LINKED) - goto dm_CheckEdcaTurbo_EXIT; - if (priv->rtllib->ht_info->iot_action & HT_IOT_ACT_DISABLE_EDCA_TURBO) - goto dm_CheckEdcaTurbo_EXIT; - - if (!priv->rtllib->bis_any_nonbepkts) { - curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; - curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if (ht_info->iot_action & HT_IOT_ACT_EDCA_BIAS_ON_RX) { - if (curTxOkCnt > 4 * curRxOkCnt) { - if (priv->bis_cur_rdlstate || - !priv->bcurrent_turbo_EDCA) { - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_UL[ht_info->iot_peer]); - priv->bis_cur_rdlstate = false; - } - } else { - if (!priv->bis_cur_rdlstate || - !priv->bcurrent_turbo_EDCA) { - if (priv->rtllib->mode == WIRELESS_MODE_G) - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_DL_GMode[ht_info->iot_peer]); - else - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_DL[ht_info->iot_peer]); - priv->bis_cur_rdlstate = true; - } - } - priv->bcurrent_turbo_EDCA = true; - } else { - if (curRxOkCnt > 4 * curTxOkCnt) { - if (!priv->bis_cur_rdlstate || - !priv->bcurrent_turbo_EDCA) { - if (priv->rtllib->mode == WIRELESS_MODE_G) - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_DL_GMode[ht_info->iot_peer]); - else - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_DL[ht_info->iot_peer]); - priv->bis_cur_rdlstate = true; - } - } else { - if (priv->bis_cur_rdlstate || - !priv->bcurrent_turbo_EDCA) { - rtl92e_writel(dev, EDCAPARA_BE, - edca_setting_UL[ht_info->iot_peer]); - priv->bis_cur_rdlstate = false; - } - } - - priv->bcurrent_turbo_EDCA = true; - } - } else { - if (priv->bcurrent_turbo_EDCA) { - u8 tmp = AC0_BE; - - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_AC_PARAM, - (u8 *)(&tmp)); - priv->bcurrent_turbo_EDCA = false; - } - } - -dm_CheckEdcaTurbo_EXIT: - priv->rtllib->bis_any_nonbepkts = false; - lastTxOkCnt = priv->stats.txbytesunicast; - lastRxOkCnt = priv->stats.rxbytesunicast; -} - -static void _rtl92e_dm_init_cts_to_self(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); - - priv->rtllib->bCTSToSelfEnable = true; -} - -static void _rtl92e_dm_cts_to_self(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); - struct rt_hi_throughput *ht_info = priv->rtllib->ht_info; - static unsigned long lastTxOkCnt; - static unsigned long lastRxOkCnt; - unsigned long curTxOkCnt = 0; - unsigned long curRxOkCnt = 0; - - if (!priv->rtllib->bCTSToSelfEnable) { - ht_info->iot_action &= ~HT_IOT_ACT_FORCED_CTS2SELF; - return; - } - if (ht_info->iot_peer == HT_IOT_PEER_BROADCOM) { - curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; - curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if (curRxOkCnt > 4 * curTxOkCnt) - ht_info->iot_action &= ~HT_IOT_ACT_FORCED_CTS2SELF; - else - ht_info->iot_action |= HT_IOT_ACT_FORCED_CTS2SELF; - - lastTxOkCnt = priv->stats.txbytesunicast; - lastRxOkCnt = priv->stats.rxbytesunicast; - } -} - -static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) -{ - struct r8192_priv *priv = container_of_dwork_rsl(data, - struct r8192_priv, gpio_change_rf_wq); - struct net_device *dev = priv->rtllib->dev; - u8 tmp1byte; - enum rt_rf_power_state rf_power_state_to_set; - bool bActuallySet = false; - - if ((priv->up_first_time == 1) || (priv->being_init_adapter)) - return; - - if (priv->bfirst_after_down) - return; - - tmp1byte = rtl92e_readb(dev, GPI); - - rf_power_state_to_set = (tmp1byte & BIT(1)) ? rf_on : rf_off; - - if (priv->hw_radio_off && (rf_power_state_to_set == rf_on)) { - netdev_info(dev, "gpiochangeRF - HW Radio ON\n"); - priv->hw_radio_off = false; - bActuallySet = true; - } else if (!priv->hw_radio_off && (rf_power_state_to_set == rf_off)) { - netdev_info(dev, "gpiochangeRF - HW Radio OFF\n"); - priv->hw_radio_off = true; - bActuallySet = true; - } - - if (bActuallySet) { - mdelay(1000); - priv->hw_rf_off_action = 1; - rtl92e_set_rf_state(dev, rf_power_state_to_set, RF_CHANGE_BY_HW); - } -} - -void rtl92e_dm_rf_pathcheck_wq(void *data) -{ - struct r8192_priv *priv = container_of_dwork_rsl(data, - struct r8192_priv, - rfpath_check_wq); - struct net_device *dev = priv->rtllib->dev; - u8 rfpath, i; - - rfpath = rtl92e_readb(dev, 0xc04); - - for (i = 0; i < RF90_PATH_MAX; i++) { - if (rfpath & (0x01 << i)) - priv->brfpath_rxenable[i] = true; - else - priv->brfpath_rxenable[i] = false; - } - if (!dm_rx_path_sel_table.enable) - return; - - _rtl92e_dm_rx_path_sel_byrssi(dev); -} - -static void _rtl92e_dm_init_rx_path_selection(struct net_device *dev) -{ - u8 i; - struct r8192_priv *priv = rtllib_priv(dev); - - dm_rx_path_sel_table.enable = 1; - dm_rx_path_sel_table.ss_th_low = RX_PATH_SEL_SS_TH_LOW; - dm_rx_path_sel_table.diff_th = RX_PATH_SEL_DIFF_TH; - if (priv->customer_id == RT_CID_819X_NETCORE) - dm_rx_path_sel_table.cck_method = CCK_Rx_Version_2; - else - dm_rx_path_sel_table.cck_method = CCK_Rx_Version_1; - dm_rx_path_sel_table.disabled_rf = 0; - for (i = 0; i < 4; i++) { - dm_rx_path_sel_table.rf_rssi[i] = 50; - dm_rx_path_sel_table.cck_pwdb_sta[i] = -64; - dm_rx_path_sel_table.rf_enable_rssi_th[i] = 100; - } -} - -#define PWDB_IN_RANGE ((cur_cck_pwdb < tmp_cck_max_pwdb) && \ - (cur_cck_pwdb > tmp_cck_sec_pwdb)) - -static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u8 i, max_rssi_index = 0, min_rssi_index = 0; - u8 sec_rssi_index = 0, rf_num = 0; - u8 tmp_max_rssi = 0, tmp_min_rssi = 0, tmp_sec_rssi = 0; - u8 cck_default_Rx = 0x2; - u8 cck_optional_Rx = 0x3; - long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; - u8 cck_rx_ver2_max_index = 0; - u8 cck_rx_ver2_sec_index = 0; - u8 cur_rf_rssi; - long cur_cck_pwdb; - static u8 disabled_rf_cnt, cck_Rx_Path_initialized; - u8 update_cck_rx_path; - - if (!cck_Rx_Path_initialized) { - dm_rx_path_sel_table.cck_rx_path = (rtl92e_readb(dev, 0xa07) & 0xf); - cck_Rx_Path_initialized = 1; - } - - dm_rx_path_sel_table.disabled_rf = 0xf; - dm_rx_path_sel_table.disabled_rf &= ~(rtl92e_readb(dev, 0xc04)); - - if (priv->rtllib->mode == WIRELESS_MODE_B) - dm_rx_path_sel_table.cck_method = CCK_Rx_Version_2; - - for (i = 0; i < RF90_PATH_MAX; i++) { - dm_rx_path_sel_table.rf_rssi[i] = priv->stats.rx_rssi_percentage[i]; - - if (!priv->brfpath_rxenable[i]) - continue; - - rf_num++; - cur_rf_rssi = dm_rx_path_sel_table.rf_rssi[i]; - - if (rf_num == 1) { - max_rssi_index = min_rssi_index = sec_rssi_index = i; - tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; - } else if (rf_num == 2) { - if (cur_rf_rssi >= tmp_max_rssi) { - tmp_max_rssi = cur_rf_rssi; - max_rssi_index = i; - } else { - tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; - sec_rssi_index = min_rssi_index = i; - } - } else { - if (cur_rf_rssi > tmp_max_rssi) { - tmp_sec_rssi = tmp_max_rssi; - sec_rssi_index = max_rssi_index; - tmp_max_rssi = cur_rf_rssi; - max_rssi_index = i; - } else if (cur_rf_rssi == tmp_max_rssi) { - tmp_sec_rssi = cur_rf_rssi; - sec_rssi_index = i; - } else if ((cur_rf_rssi < tmp_max_rssi) && - (cur_rf_rssi > tmp_sec_rssi)) { - tmp_sec_rssi = cur_rf_rssi; - sec_rssi_index = i; - } else if (cur_rf_rssi == tmp_sec_rssi) { - if (tmp_sec_rssi == tmp_min_rssi) { - tmp_sec_rssi = cur_rf_rssi; - sec_rssi_index = i; - } - } else if ((cur_rf_rssi < tmp_sec_rssi) && - (cur_rf_rssi > tmp_min_rssi)) { - ; - } else if (cur_rf_rssi == tmp_min_rssi) { - if (tmp_sec_rssi == tmp_min_rssi) { - tmp_min_rssi = cur_rf_rssi; - min_rssi_index = i; - } - } else if (cur_rf_rssi < tmp_min_rssi) { - tmp_min_rssi = cur_rf_rssi; - min_rssi_index = i; - } - } - } - - rf_num = 0; - if (dm_rx_path_sel_table.cck_method == CCK_Rx_Version_2) { - for (i = 0; i < RF90_PATH_MAX; i++) { - if (!priv->brfpath_rxenable[i]) - continue; - - rf_num++; - cur_cck_pwdb = dm_rx_path_sel_table.cck_pwdb_sta[i]; - - if (rf_num == 1) { - cck_rx_ver2_max_index = i; - cck_rx_ver2_sec_index = i; - tmp_cck_max_pwdb = cur_cck_pwdb; - tmp_cck_min_pwdb = cur_cck_pwdb; - tmp_cck_sec_pwdb = cur_cck_pwdb; - } else if (rf_num == 2) { - if (cur_cck_pwdb >= tmp_cck_max_pwdb) { - tmp_cck_max_pwdb = cur_cck_pwdb; - cck_rx_ver2_max_index = i; - } else { - tmp_cck_sec_pwdb = cur_cck_pwdb; - tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } - } else { - if (cur_cck_pwdb > tmp_cck_max_pwdb) { - tmp_cck_sec_pwdb = tmp_cck_max_pwdb; - cck_rx_ver2_sec_index = cck_rx_ver2_max_index; - tmp_cck_max_pwdb = cur_cck_pwdb; - cck_rx_ver2_max_index = i; - } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } else if (PWDB_IN_RANGE) { - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } else if (cur_cck_pwdb == tmp_cck_sec_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } - } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && - (cur_cck_pwdb > tmp_cck_min_pwdb)) { - ; - } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - tmp_cck_min_pwdb = cur_cck_pwdb; - } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { - tmp_cck_min_pwdb = cur_cck_pwdb; - } - } - } - } - - update_cck_rx_path = 0; - if (dm_rx_path_sel_table.cck_method == CCK_Rx_Version_2) { - cck_default_Rx = cck_rx_ver2_max_index; - cck_optional_Rx = cck_rx_ver2_sec_index; - if (tmp_cck_max_pwdb != -64) - update_cck_rx_path = 1; - } - - if (tmp_min_rssi < dm_rx_path_sel_table.ss_th_low && disabled_rf_cnt < 2) { - if ((tmp_max_rssi - tmp_min_rssi) >= - dm_rx_path_sel_table.diff_th) { - dm_rx_path_sel_table.rf_enable_rssi_th[min_rssi_index] = - tmp_max_rssi + 5; - rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, - 0x1 << min_rssi_index, 0x0); - rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, - 0x1 << min_rssi_index, 0x0); - disabled_rf_cnt++; - } - if (dm_rx_path_sel_table.cck_method == CCK_Rx_Version_1) { - cck_default_Rx = max_rssi_index; - cck_optional_Rx = sec_rssi_index; - if (tmp_max_rssi) - update_cck_rx_path = 1; - } - } - - if (update_cck_rx_path) { - dm_rx_path_sel_table.cck_rx_path = (cck_default_Rx << 2) | - (cck_optional_Rx); - rtl92e_set_bb_reg(dev, rCCK0_AFESetting, 0x0f000000, - dm_rx_path_sel_table.cck_rx_path); - } - - if (dm_rx_path_sel_table.disabled_rf) { - for (i = 0; i < 4; i++) { - if ((dm_rx_path_sel_table.disabled_rf >> i) & 0x1) { - if (tmp_max_rssi >= - dm_rx_path_sel_table.rf_enable_rssi_th[i]) { - rtl92e_set_bb_reg(dev, - rOFDM0_TRxPathEnable, - 0x1 << i, 0x1); - rtl92e_set_bb_reg(dev, - rOFDM1_TRxPathEnable, - 0x1 << i, 0x1); - dm_rx_path_sel_table.rf_enable_rssi_th[i] = 100; - disabled_rf_cnt--; - } - } - } - } -} - -static void _rtl92e_dm_check_rx_path_selection(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - schedule_delayed_work(&priv->rfpath_check_wq, 0); -} - -static void _rtl92e_dm_init_fsync(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->rtllib->fsync_time_interval = 500; - priv->rtllib->fsync_rate_bitmap = 0x0f000800; - priv->rtllib->fsync_rssi_threshold = 30; - priv->rtllib->bfsync_enable = false; - priv->rtllib->fsync_multiple_timeinterval = 3; - priv->rtllib->fsync_firstdiff_ratethreshold = 100; - priv->rtllib->fsync_seconddiff_ratethreshold = 200; - priv->rtllib->fsync_state = DEFAULT_FSYNC; - - timer_setup(&priv->fsync_timer, _rtl92e_dm_fsync_timer_callback, 0); -} - -static void _rtl92e_dm_deinit_fsync(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - del_timer_sync(&priv->fsync_timer); -} - -static void _rtl92e_dm_fsync_timer_callback(struct timer_list *t) -{ - struct r8192_priv *priv = from_timer(priv, t, fsync_timer); - struct net_device *dev = priv->rtllib->dev; - u32 rate_index, rate_count = 0, rate_count_diff = 0; - bool bSwitchFromCountDiff = false; - bool bDoubleTimeInterval = false; - - if (priv->rtllib->link_state == MAC80211_LINKED && - priv->rtllib->bfsync_enable && - (priv->rtllib->ht_info->iot_action & HT_IOT_ACT_CDD_FSYNC)) { - u32 rate_bitmap; - - for (rate_index = 0; rate_index <= 27; rate_index++) { - rate_bitmap = 1 << rate_index; - if (priv->rtllib->fsync_rate_bitmap & rate_bitmap) - rate_count += - priv->stats.received_rate_histogram[1] - [rate_index]; - } - - if (rate_count < priv->rate_record) - rate_count_diff = 0xffffffff - rate_count + - priv->rate_record; - else - rate_count_diff = rate_count - priv->rate_record; - if (rate_count_diff < priv->rate_count_diff_rec) { - u32 DiffNum = priv->rate_count_diff_rec - - rate_count_diff; - if (DiffNum >= - priv->rtllib->fsync_seconddiff_ratethreshold) - priv->continue_diff_count++; - else - priv->continue_diff_count = 0; - - if (priv->continue_diff_count >= 2) { - bSwitchFromCountDiff = true; - priv->continue_diff_count = 0; - } - } else { - priv->continue_diff_count = 0; - } - - if (rate_count_diff <= - priv->rtllib->fsync_firstdiff_ratethreshold) { - bSwitchFromCountDiff = true; - priv->continue_diff_count = 0; - } - priv->rate_record = rate_count; - priv->rate_count_diff_rec = rate_count_diff; - if (priv->undecorated_smoothed_pwdb > - priv->rtllib->fsync_rssi_threshold && - bSwitchFromCountDiff) { - bDoubleTimeInterval = true; - priv->bswitch_fsync = !priv->bswitch_fsync; - if (priv->bswitch_fsync) { - rtl92e_writeb(dev, 0xC36, 0x1c); - rtl92e_writeb(dev, 0xC3e, 0x90); - } else { - rtl92e_writeb(dev, 0xC36, 0x5c); - rtl92e_writeb(dev, 0xC3e, 0x96); - } - } else if (priv->undecorated_smoothed_pwdb <= - priv->rtllib->fsync_rssi_threshold) { - if (priv->bswitch_fsync) { - priv->bswitch_fsync = false; - rtl92e_writeb(dev, 0xC36, 0x5c); - rtl92e_writeb(dev, 0xC3e, 0x96); - } - } - if (bDoubleTimeInterval) { - if (timer_pending(&priv->fsync_timer)) - del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + - msecs_to_jiffies(priv->rtllib->fsync_time_interval * - priv->rtllib->fsync_multiple_timeinterval); - add_timer(&priv->fsync_timer); - } else { - if (timer_pending(&priv->fsync_timer)) - del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + - msecs_to_jiffies(priv->rtllib->fsync_time_interval); - add_timer(&priv->fsync_timer); - } - } else { - if (priv->bswitch_fsync) { - priv->bswitch_fsync = false; - rtl92e_writeb(dev, 0xC36, 0x5c); - rtl92e_writeb(dev, 0xC3e, 0x96); - } - priv->continue_diff_count = 0; - rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); - } -} - -static void _rtl92e_dm_start_hw_fsync(struct net_device *dev) -{ - u8 rf_timing = 0x77; - struct r8192_priv *priv = rtllib_priv(dev); - - rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cf); - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_RF_TIMING, - (u8 *)(&rf_timing)); - rtl92e_writeb(dev, 0xc3b, 0x41); -} - -static void _rtl92e_dm_end_hw_fsync(struct net_device *dev) -{ - u8 rf_timing = 0xaa; - struct r8192_priv *priv = rtllib_priv(dev); - - rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); - priv->rtllib->set_hw_reg_handler(dev, HW_VAR_RF_TIMING, (u8 *) - (&rf_timing)); - rtl92e_writeb(dev, 0xc3b, 0x49); -} - -static void _rtl92e_dm_end_sw_fsync(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - del_timer_sync(&(priv->fsync_timer)); - - if (priv->bswitch_fsync) { - priv->bswitch_fsync = false; - - rtl92e_writeb(dev, 0xC36, 0x5c); - - rtl92e_writeb(dev, 0xC3e, 0x96); - } - - priv->continue_diff_count = 0; - rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd); -} - -static void _rtl92e_dm_start_sw_fsync(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 rate_index; - u32 rate_bitmap; - - priv->rate_record = 0; - priv->continue_diff_count = 0; - priv->rate_count_diff_rec = 0; - priv->bswitch_fsync = false; - - if (priv->rtllib->mode == WIRELESS_MODE_N_24G) { - priv->rtllib->fsync_firstdiff_ratethreshold = 600; - priv->rtllib->fsync_seconddiff_ratethreshold = 0xffff; - } else { - priv->rtllib->fsync_firstdiff_ratethreshold = 200; - priv->rtllib->fsync_seconddiff_ratethreshold = 200; - } - for (rate_index = 0; rate_index <= 27; rate_index++) { - rate_bitmap = 1 << rate_index; - if (priv->rtllib->fsync_rate_bitmap & rate_bitmap) - priv->rate_record += - priv->stats.received_rate_histogram[1] - [rate_index]; - } - if (timer_pending(&priv->fsync_timer)) - del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + - msecs_to_jiffies(priv->rtllib->fsync_time_interval); - add_timer(&priv->fsync_timer); - - rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd); -} - -static void _rtl92e_dm_check_fsync(struct net_device *dev) -{ -#define RegC38_Default 0 -#define RegC38_NonFsync_Other_AP 1 -#define RegC38_Fsync_AP_BCM 2 - struct r8192_priv *priv = rtllib_priv(dev); - static u8 reg_c38_State = RegC38_Default; - - if (priv->rtllib->link_state == MAC80211_LINKED && - priv->rtllib->ht_info->iot_peer == HT_IOT_PEER_BROADCOM) { - if (priv->rtllib->bfsync_enable == 0) { - switch (priv->rtllib->fsync_state) { - case DEFAULT_FSYNC: - _rtl92e_dm_start_hw_fsync(dev); - priv->rtllib->fsync_state = HW_FSYNC; - break; - case SW_FSYNC: - _rtl92e_dm_end_sw_fsync(dev); - _rtl92e_dm_start_hw_fsync(dev); - priv->rtllib->fsync_state = HW_FSYNC; - break; - default: - break; - } - } else { - switch (priv->rtllib->fsync_state) { - case DEFAULT_FSYNC: - _rtl92e_dm_start_sw_fsync(dev); - priv->rtllib->fsync_state = SW_FSYNC; - break; - case HW_FSYNC: - _rtl92e_dm_end_hw_fsync(dev); - _rtl92e_dm_start_sw_fsync(dev); - priv->rtllib->fsync_state = SW_FSYNC; - break; - default: - break; - } - } - if (reg_c38_State != RegC38_Fsync_AP_BCM) { - rtl92e_writeb(dev, rOFDM0_RxDetector3, 0x95); - - reg_c38_State = RegC38_Fsync_AP_BCM; - } - } else { - switch (priv->rtllib->fsync_state) { - case HW_FSYNC: - _rtl92e_dm_end_hw_fsync(dev); - priv->rtllib->fsync_state = DEFAULT_FSYNC; - break; - case SW_FSYNC: - _rtl92e_dm_end_sw_fsync(dev); - priv->rtllib->fsync_state = DEFAULT_FSYNC; - break; - default: - break; - } - - if (priv->rtllib->link_state == MAC80211_LINKED) { - if (priv->undecorated_smoothed_pwdb <= - REG_C38_TH) { - if (reg_c38_State != - RegC38_NonFsync_Other_AP) { - rtl92e_writeb(dev, - rOFDM0_RxDetector3, - 0x90); - - reg_c38_State = - RegC38_NonFsync_Other_AP; - } - } else if (priv->undecorated_smoothed_pwdb >= - (REG_C38_TH + 5)) { - if (reg_c38_State) { - rtl92e_writeb(dev, - rOFDM0_RxDetector3, - priv->framesync); - reg_c38_State = RegC38_Default; - } - } - } else { - if (reg_c38_State) { - rtl92e_writeb(dev, rOFDM0_RxDetector3, - priv->framesync); - reg_c38_State = RegC38_Default; - } - } - } -} - -/*---------------------------Define function prototype------------------------*/ -static void _rtl92e_dm_init_dynamic_tx_power(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->rtllib->bdynamic_txpower_enable = true; - priv->last_dtp_flag_high = false; - priv->last_dtp_flag_low = false; - priv->dynamic_tx_high_pwr = false; - priv->dynamic_tx_low_pwr = false; -} - -static void _rtl92e_dm_dynamic_tx_power(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - unsigned int txhipower_threshold = 0; - unsigned int txlowpower_threshold = 0; - - if (!priv->rtllib->bdynamic_txpower_enable) { - priv->dynamic_tx_high_pwr = false; - priv->dynamic_tx_low_pwr = false; - return; - } - if ((priv->rtllib->ht_info->iot_peer == HT_IOT_PEER_ATHEROS) && - (priv->rtllib->mode == WIRELESS_MODE_G)) { - txhipower_threshold = TX_POWER_ATHEROAP_THRESH_HIGH; - txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; - } else { - txhipower_threshold = TX_POWER_NEAR_FIELD_THRESH_HIGH; - txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; - } - - if (priv->rtllib->link_state == MAC80211_LINKED) { - if (priv->undecorated_smoothed_pwdb >= txhipower_threshold) { - priv->dynamic_tx_high_pwr = true; - priv->dynamic_tx_low_pwr = false; - } else { - if (priv->undecorated_smoothed_pwdb < - txlowpower_threshold && priv->dynamic_tx_high_pwr) - priv->dynamic_tx_high_pwr = false; - if (priv->undecorated_smoothed_pwdb < 35) - priv->dynamic_tx_low_pwr = true; - else if (priv->undecorated_smoothed_pwdb >= 40) - priv->dynamic_tx_low_pwr = false; - } - } else { - priv->dynamic_tx_high_pwr = false; - priv->dynamic_tx_low_pwr = false; - } - - if ((priv->dynamic_tx_high_pwr != priv->last_dtp_flag_high) || - (priv->dynamic_tx_low_pwr != priv->last_dtp_flag_low)) { - rtl92e_set_tx_power(dev, priv->rtllib->current_network.channel); - } - priv->last_dtp_flag_high = priv->dynamic_tx_high_pwr; - priv->last_dtp_flag_low = priv->dynamic_tx_low_pwr; -} - -static void _rtl92e_dm_check_txrateandretrycount(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - ieee->softmac_stats.CurrentShowTxate = rtl92e_readb(dev, CURRENT_TX_RATE_REG); - ieee->softmac_stats.last_packet_rate = rtl92e_readb(dev, INITIAL_TX_RATE_REG); - ieee->softmac_stats.txretrycount = rtl92e_readl(dev, TX_RETRY_COUNT_REG); -} - -static void _rtl92e_dm_send_rssi_to_fw(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - rtl92e_writeb(dev, DRIVER_RSSI, priv->undecorated_smoothed_pwdb); -} diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h deleted file mode 100644 index 55641f17412b..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h +++ /dev/null @@ -1,155 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef __R8192UDM_H__ -#define __R8192UDM_H__ - -/*--------------------------Define Parameters-------------------------------*/ -#define OFDM_TABLE_LEN 19 -#define CCK_TABLE_LEN 12 - -#define DM_DIG_THRESH_HIGH 40 -#define DM_DIG_THRESH_LOW 35 - -#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 -#define DM_DIG_HIGH_PWR_THRESH_LOW 70 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_BACKOFF 12 -#define DM_DIG_MAX 0x36 -#define DM_DIG_MIN 0x1c -#define DM_DIG_MIN_Netcore 0x12 - -#define RX_PATH_SEL_SS_TH_LOW 30 -#define RX_PATH_SEL_DIFF_TH 18 - -#define RATE_ADAPTIVE_TH_HIGH 50 -#define RATE_ADAPTIVE_TH_LOW_20M 30 -#define RATE_ADAPTIVE_TH_LOW_40M 10 -#define VERY_LOW_RSSI 15 - -#define E_FOR_TX_POWER_TRACK 300 -#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68 -#define TX_POWER_NEAR_FIELD_THRESH_LOW 62 -#define TX_POWER_ATHEROAP_THRESH_HIGH 78 -#define TX_POWER_ATHEROAP_THRESH_LOW 72 - -#define CURRENT_TX_RATE_REG 0x1e0 -#define INITIAL_TX_RATE_REG 0x1e1 -#define TX_RETRY_COUNT_REG 0x1ac -#define REG_C38_TH 20 - -/*--------------------------Define Parameters-------------------------------*/ - -/*------------------------------Define structure----------------------------*/ -struct dig_t { - long rssi_low_thresh; - long rssi_high_thresh; - - long rssi_high_power_lowthresh; - long rssi_high_power_highthresh; - - u8 cur_sta_connect_state; - u8 pre_sta_connect_state; - - u8 curpd_thstate; - u8 prepd_thstate; - u8 curcs_ratio_state; - u8 precs_ratio_state; - - u32 pre_ig_value; - u32 cur_ig_value; - - u8 backoff_val; - u8 rx_gain_range_max; - u8 rx_gain_range_min; - - long rssi_val; -}; - -enum dm_ratr_sta { - DM_RATR_STA_HIGH = 0, - DM_RATR_STA_MIDDLE = 1, - DM_RATR_STA_LOW = 2, - DM_RATR_STA_MAX -}; - -enum dm_dig_connect { - DIG_STA_DISCONNECT = 0, - DIG_STA_CONNECT = 1, -}; - -enum dm_dig_pd_th { - DIG_PD_AT_LOW_POWER = 0, - DIG_PD_AT_NORMAL_POWER = 1, - DIG_PD_AT_HIGH_POWER = 2, - DIG_PD_MAX -}; - -enum dm_dig_cs_ratio { - DIG_CS_RATIO_LOWER = 0, - DIG_CS_RATIO_HIGHER = 1, - DIG_CS_MAX -}; - -struct drx_path_sel { - u8 enable; - u8 cck_method; - u8 cck_rx_path; - - u8 ss_th_low; - u8 diff_th; - u8 disabled_rf; - u8 reserved; - - u8 rf_rssi[4]; - u8 rf_enable_rssi_th[4]; - long cck_pwdb_sta[4]; -}; - -enum dm_cck_rx_path_method { - CCK_Rx_Version_1 = 0, - CCK_Rx_Version_2 = 1, - CCK_Rx_Version_MAX -}; - -struct dcmd_txcmd { - u32 op; - u32 length; - u32 value; -}; - -/*------------------------------Define structure----------------------------*/ - -/*------------------------Export global variable----------------------------*/ -extern struct dig_t dm_digtable; - -/* Pre-calculated gain tables */ -extern const u32 dm_tx_bb_gain[TX_BB_GAIN_TABLE_LEN]; -extern const u8 dm_cck_tx_bb_gain[CCK_TX_BB_GAIN_TABLE_LEN][8]; -extern const u8 dm_cck_tx_bb_gain_ch14[CCK_TX_BB_GAIN_TABLE_LEN][8]; - -/*------------------------Export global variable----------------------------*/ - -/*--------------------------Exported Function prototype---------------------*/ -/*--------------------------Exported Function prototype---------------------*/ - -void rtl92e_dm_init(struct net_device *dev); -void rtl92e_dm_deinit(struct net_device *dev); - -void rtl92e_dm_watchdog(struct net_device *dev); - -void rtl92e_init_adaptive_rate(struct net_device *dev); -void rtl92e_dm_txpower_tracking_wq(void *data); - -void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14); - -void rtl92e_dm_init_edca_turbo(struct net_device *dev); -void rtl92e_dm_rf_pathcheck_wq(void *data); -void rtl92e_dm_init_txpower_tracking(struct net_device *dev); -#endif /*__R8192UDM_H__ */ diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c deleted file mode 100644 index db57c655c695..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "rtl_eeprom.h" - -static void _rtl92e_gpio_write_bit(struct net_device *dev, int no, bool val) -{ - u8 reg = rtl92e_readb(dev, EPROM_CMD); - - if (val) - reg |= 1 << no; - else - reg &= ~(1 << no); - - rtl92e_writeb(dev, EPROM_CMD, reg); - udelay(EPROM_DELAY); -} - -static bool _rtl92e_gpio_get_bit(struct net_device *dev, int no) -{ - u8 reg = rtl92e_readb(dev, EPROM_CMD); - - return (reg >> no) & 0x1; -} - -static void _rtl92e_eeprom_ck_cycle(struct net_device *dev) -{ - _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 1); - _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 0); -} - -static u16 _rtl92e_eeprom_xfer(struct net_device *dev, u16 data, int tx_len) -{ - u16 ret = 0; - int rx_len = 16; - - _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 1); - _rtl92e_eeprom_ck_cycle(dev); - - while (tx_len--) { - _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, - (data >> tx_len) & 0x1); - _rtl92e_eeprom_ck_cycle(dev); - } - - _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, 0); - - while (rx_len--) { - _rtl92e_eeprom_ck_cycle(dev); - ret |= _rtl92e_gpio_get_bit(dev, EPROM_R_BIT) << rx_len; - } - - _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 0); - _rtl92e_eeprom_ck_cycle(dev); - - return ret; -} - -u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr) -{ - struct r8192_priv *priv = rtllib_priv(dev); - u32 ret = 0; - - rtl92e_writeb(dev, EPROM_CMD, - (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT)); - udelay(EPROM_DELAY); - - /* EEPROM is configured as x16 */ - if (priv->epromtype == EEPROM_93C56) - ret = _rtl92e_eeprom_xfer(dev, (addr & 0xFF) | (0x6 << 8), 11); - else - ret = _rtl92e_eeprom_xfer(dev, (addr & 0x3F) | (0x6 << 6), 9); - - rtl92e_writeb(dev, EPROM_CMD, - (EPROM_CMD_NORMAL << EPROM_CMD_OPERATING_MODE_SHIFT)); - return ret; -} diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h deleted file mode 100644 index 66f1979bb1d5..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#define EPROM_DELAY 10 - -u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c deleted file mode 100644 index fab8932e67da..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include <linux/netdevice.h> -#include <linux/ethtool.h> -#include <linux/delay.h> - -#include "rtl_core.h" - -static void _rtl92e_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - strscpy(info->driver, DRV_NAME, sizeof(info->driver)); - strscpy(info->version, DRV_VERSION, sizeof(info->version)); - strscpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info)); -} - -static u32 _rtl92e_ethtool_get_link(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return ((priv->rtllib->link_state == MAC80211_LINKED) || - (priv->rtllib->link_state == MAC80211_LINKED_SCANNING)); -} - -const struct ethtool_ops rtl819x_ethtool_ops = { - .get_drvinfo = _rtl92e_ethtool_get_drvinfo, - .get_link = _rtl92e_ethtool_get_link, -}; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c deleted file mode 100644 index 1aa73561581b..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_pci.h" -#include "rtl_core.h" - -static void _rtl92e_parse_pci_configuration(struct pci_dev *pdev, - struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - u8 tmp; - u16 link_ctrl_reg; - - pcie_capability_read_word(priv->pdev, PCI_EXP_LNKCTL, &link_ctrl_reg); - - pci_read_config_byte(pdev, 0x98, &tmp); - tmp |= BIT(4); - pci_write_config_byte(pdev, 0x98, tmp); - - tmp = 0x17; - pci_write_config_byte(pdev, 0x70f, tmp); -} - -bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - u16 device_id; - u8 revision_id; - u16 irq_line; - - device_id = pdev->device; - revision_id = pdev->revision; - pci_read_config_word(pdev, 0x3C, &irq_line); - - priv->card_8192 = NIC_8192E; - - if (device_id == 0x8192) { - switch (revision_id) { - case HAL_HW_PCI_REVISION_ID_8192PCIE: - dev_info(&pdev->dev, - "Adapter(8192 PCI-E) is found - DeviceID=%x\n", - device_id); - priv->card_8192 = NIC_8192E; - break; - case HAL_HW_PCI_REVISION_ID_8192SE: - dev_info(&pdev->dev, - "Adapter(8192SE) is found - DeviceID=%x\n", - device_id); - priv->card_8192 = NIC_8192SE; - break; - default: - dev_info(&pdev->dev, - "UNKNOWN nic type(%4x:%4x)\n", - pdev->vendor, pdev->device); - priv->card_8192 = NIC_UNKNOWN; - return false; - } - } - - if (priv->card_8192 != NIC_8192E) { - dev_info(&pdev->dev, - "Detect info(%x) and hardware info(%x) not match!\n", - NIC_8192E, priv->card_8192); - dev_info(&pdev->dev, - "Please select proper driver before install!!!!\n"); - return false; - } - - _rtl92e_parse_pci_configuration(pdev, dev); - - return true; -} diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h deleted file mode 100644 index 3e39c4835ac8..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL_PCI_H -#define _RTL_PCI_H - -#include <linux/types.h> -#include <linux/pci.h> - -struct net_device; - -bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c deleted file mode 100644 index d124b5eee0cc..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_core.h" -#include "r8192E_hw.h" -#include "r8190P_rtl8256.h" -#include "rtl_pm.h" - -int rtl92e_suspend(struct device *dev_d) -{ - struct net_device *dev = dev_get_drvdata(dev_d); - struct r8192_priv *priv = rtllib_priv(dev); - u32 ulRegRead; - - netdev_info(dev, "============> r8192E suspend call.\n"); - del_timer_sync(&priv->gpio_polling_timer); - cancel_delayed_work_sync(&priv->gpio_change_rf_wq); - priv->polling_timer_on = 0; - - if (!netif_running(dev)) { - netdev_info(dev, - "RTL819XE:UI is open out of suspend function\n"); - goto out_pci_suspend; - } - - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - netif_device_detach(dev); - - if (!priv->rtllib->bSupportRemoteWakeUp) { - rtl92e_set_rf_state(dev, rf_off, RF_CHANGE_BY_INIT); - ulRegRead = rtl92e_readl(dev, CPU_GEN); - ulRegRead |= CPU_GEN_SYSTEM_RESET; - rtl92e_writel(dev, CPU_GEN, ulRegRead); - } else { - rtl92e_writel(dev, WFCRC0, 0xffffffff); - rtl92e_writel(dev, WFCRC1, 0xffffffff); - rtl92e_writel(dev, WFCRC2, 0xffffffff); - rtl92e_writeb(dev, PMR, 0x5); - rtl92e_writeb(dev, MAC_BLK_CTRL, 0xa); - } -out_pci_suspend: - netdev_info(dev, "WOL is %s\n", priv->rtllib->bSupportRemoteWakeUp ? - "Supported" : "Not supported"); - device_set_wakeup_enable(dev_d, priv->rtllib->bSupportRemoteWakeUp); - - mdelay(20); - - return 0; -} - -int rtl92e_resume(struct device *dev_d) -{ - struct pci_dev *pdev = to_pci_dev(dev_d); - struct net_device *dev = dev_get_drvdata(dev_d); - struct r8192_priv *priv = rtllib_priv(dev); - u32 val; - - netdev_info(dev, "================>r8192E resume call.\n"); - - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - device_wakeup_disable(dev_d); - - if (priv->polling_timer_on == 0) - rtl92e_check_rfctrl_gpio_timer(&priv->gpio_polling_timer); - - if (!netif_running(dev)) { - netdev_info(dev, - "RTL819XE:UI is open out of resume function\n"); - goto out; - } - - netif_device_attach(dev); - if (dev->netdev_ops->ndo_open) - dev->netdev_ops->ndo_open(dev); - - if (!priv->rtllib->bSupportRemoteWakeUp) - rtl92e_set_rf_state(dev, rf_on, RF_CHANGE_BY_INIT); - -out: - return 0; -} - diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h deleted file mode 100644 index fd8611495975..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef R8192E_PM_H -#define R8192E_PM_H - -#include <linux/types.h> -#include <linux/pci.h> - -int rtl92e_suspend(struct device *dev_d); -int rtl92e_resume(struct device *dev_d); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c deleted file mode 100644 index 7b6247acf6f4..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtl_ps.h" -#include "rtl_core.h" -#include "r8192E_phy.h" -#include "r8192E_phyreg.h" -#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */ -#include "r8192E_cmdpkt.h" -#include <linux/jiffies.h> - -static void _rtl92e_hw_sleep(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - unsigned long flags = 0; - - spin_lock_irqsave(&priv->rf_ps_lock, flags); - if (priv->rf_change_in_progress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - return; - } - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - rtl92e_set_rf_state(dev, rf_sleep, RF_CHANGE_BY_PS); -} - -void rtl92e_hw_sleep_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, hw_sleep_wq); - struct net_device *dev = ieee->dev; - - _rtl92e_hw_sleep(dev); -} - -void rtl92e_hw_wakeup(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - unsigned long flags = 0; - - spin_lock_irqsave(&priv->rf_ps_lock, flags); - if (priv->rf_change_in_progress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - schedule_delayed_work(&priv->rtllib->hw_wakeup_wq, - msecs_to_jiffies(10)); - return; - } - spin_unlock_irqrestore(&priv->rf_ps_lock, flags); - rtl92e_set_rf_state(dev, rf_on, RF_CHANGE_BY_PS); -} - -void rtl92e_hw_wakeup_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, hw_wakeup_wq); - struct net_device *dev = ieee->dev; - - rtl92e_hw_wakeup(dev); -} - -#define MIN_SLEEP_TIME 50 -#define MAX_SLEEP_TIME 10000 -void rtl92e_enter_sleep(struct net_device *dev, u64 time) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - u32 tmp; - unsigned long flags; - unsigned long timeout; - - spin_lock_irqsave(&priv->ps_lock, flags); - - time -= msecs_to_jiffies(8 + 16 + 7); - - timeout = jiffies + msecs_to_jiffies(MIN_SLEEP_TIME); - if (time_before((unsigned long)time, timeout)) { - spin_unlock_irqrestore(&priv->ps_lock, flags); - netdev_info(dev, "too short to sleep::%lld < %ld\n", - time - jiffies, msecs_to_jiffies(MIN_SLEEP_TIME)); - return; - } - timeout = jiffies + msecs_to_jiffies(MAX_SLEEP_TIME); - if (time_after((unsigned long)time, timeout)) { - netdev_info(dev, "========>too long to sleep:%lld > %ld\n", - time - jiffies, msecs_to_jiffies(MAX_SLEEP_TIME)); - spin_unlock_irqrestore(&priv->ps_lock, flags); - return; - } - tmp = time - jiffies; - schedule_delayed_work(&priv->rtllib->hw_wakeup_wq, tmp); - schedule_delayed_work(&priv->rtllib->hw_sleep_wq, 0); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void _rtl92e_ps_update_rf_state(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - &priv->rtllib->pwr_save_ctrl; - - psc->bSwRfProcessing = true; - rtl92e_set_rf_state(dev, psc->eInactivePowerState, RF_CHANGE_BY_IPS); - - psc->bSwRfProcessing = false; -} - -void rtl92e_ips_enter(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - &priv->rtllib->pwr_save_ctrl; - enum rt_rf_power_state rt_state; - - rt_state = priv->rtllib->rf_power_state; - if (rt_state == rf_on && !psc->bSwRfProcessing && - (priv->rtllib->link_state != MAC80211_LINKED)) { - psc->eInactivePowerState = rf_off; - _rtl92e_ps_update_rf_state(dev); - } -} - -void rtl92e_ips_leave(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - &priv->rtllib->pwr_save_ctrl; - enum rt_rf_power_state rt_state; - - rt_state = priv->rtllib->rf_power_state; - if (rt_state != rf_on && !psc->bSwRfProcessing && - priv->rtllib->rf_off_reason <= RF_CHANGE_BY_IPS) { - psc->eInactivePowerState = rf_on; - _rtl92e_ps_update_rf_state(dev); - } -} - -void rtl92e_ips_leave_wq(void *data) -{ - struct rtllib_device *ieee = container_of(data, struct rtllib_device, ips_leave_wq); - struct net_device *dev = ieee->dev; - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); -} - -void rtl92e_rtllib_ips_leave_wq(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - enum rt_rf_power_state rt_state; - - rt_state = priv->rtllib->rf_power_state; - if (rt_state == rf_off) { - if (priv->rtllib->rf_off_reason > RF_CHANGE_BY_IPS) { - netdev_warn(dev, "%s(): RF is OFF.\n", - __func__); - return; - } - netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n", - __func__); - schedule_work(&priv->rtllib->ips_leave_wq); - } -} - -void rtl92e_rtllib_ips_leave(struct net_device *dev) -{ - struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); - - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); -} - -static bool _rtl92e_ps_set_mode(struct net_device *dev, u8 rtPsMode) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - priv->rtllib->ps = rtPsMode; - if (priv->rtllib->sta_sleep != LPS_IS_WAKE && - rtPsMode == RTLLIB_PS_DISABLED) { - unsigned long flags; - - rtl92e_hw_wakeup(dev); - priv->rtllib->sta_sleep = LPS_IS_WAKE; - - spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags); - rtllib_sta_ps_send_null_frame(priv->rtllib, 0); - spin_unlock_irqrestore(&(priv->rtllib->mgmt_tx_lock), flags); - } - - return true; -} - -void rtl92e_leisure_ps_enter(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - &priv->rtllib->pwr_save_ctrl; - - if (!((priv->rtllib->iw_mode == IW_MODE_INFRA) && - (priv->rtllib->link_state == MAC80211_LINKED))) - return; - - if (psc->bLeisurePs) { - if (psc->lps_idle_count >= RT_CHECK_FOR_HANG_PERIOD) { - if (priv->rtllib->ps == RTLLIB_PS_DISABLED) - _rtl92e_ps_set_mode(dev, RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST); - } else { - psc->lps_idle_count++; - } - } -} - -void rtl92e_leisure_ps_leave(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rt_pwr_save_ctrl *psc = (struct rt_pwr_save_ctrl *) - &priv->rtllib->pwr_save_ctrl; - - if (psc->bLeisurePs) { - if (priv->rtllib->ps != RTLLIB_PS_DISABLED) - _rtl92e_ps_set_mode(dev, RTLLIB_PS_DISABLED); - } -} diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h deleted file mode 100644 index 70fe5d39be9a..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL_PS_H -#define _RTL_PS_H - -#include <linux/types.h> - -struct net_device; - -#define RT_CHECK_FOR_HANG_PERIOD 2 - -void rtl92e_hw_wakeup(struct net_device *dev); -void rtl92e_enter_sleep(struct net_device *dev, u64 time); -void rtl92e_rtllib_ips_leave_wq(struct net_device *dev); -void rtl92e_rtllib_ips_leave(struct net_device *dev); -void rtl92e_ips_leave_wq(void *data); - -void rtl92e_ips_enter(struct net_device *dev); -void rtl92e_ips_leave(struct net_device *dev); - -void rtl92e_leisure_ps_enter(struct net_device *dev); -void rtl92e_leisure_ps_leave(struct net_device *dev); - -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c deleted file mode 100644 index fe3a42a4fcd5..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ /dev/null @@ -1,867 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include <linux/string.h> -#include "rtl_core.h" -#include "rtl_wx.h" - -#define RATE_COUNT 12 -static u32 rtl8192_rates[] = { - 1000000, 2000000, 5500000, 11000000, 6000000, 9000000, 12000000, - 18000000, 24000000, 36000000, 48000000, 54000000 -}; - -#ifndef ENETDOWN -#define ENETDOWN 1 -#endif - -static int _rtl92e_wx_get_freq(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_freq(priv->rtllib, a, wrqu, b); -} - -static int _rtl92e_wx_get_mode(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_mode(priv->rtllib, a, wrqu, b); -} - -static int _rtl92e_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_rate(priv->rtllib, info, wrqu, extra); -} - -static int _rtl92e_wx_set_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_rts(priv->rtllib, info, wrqu, extra); -} - -static int _rtl92e_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) { - netdev_warn(dev, "%s(): Can't set Power: Radio is Off.\n", - __func__); - return 0; - } - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_power(priv->rtllib, info, wrqu, extra); -} - -static int _rtl92e_wx_set_mode(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - enum rt_rf_power_state rt_state; - int ret; - - if (priv->hw_radio_off) - return 0; - rt_state = priv->rtllib->rf_power_state; - mutex_lock(&priv->wx_mutex); - if (wrqu->mode == IW_MODE_MONITOR) { - if (rt_state == rf_off) { - if (priv->rtllib->rf_off_reason > - RF_CHANGE_BY_IPS) { - netdev_warn(dev, "%s(): RF is OFF.\n", - __func__); - mutex_unlock(&priv->wx_mutex); - return -1; - } - netdev_info(dev, - "=========>%s(): rtl92e_ips_leave\n", - __func__); - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); - } - } - ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b); - - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct r8192_priv *priv = rtllib_priv(dev); - u16 val; - int i; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* ~130 Mb/s real (802.11n) */ - range->throughput = 130 * 1000 * 1000; - - range->max_qual.qual = 100; - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ - range->avg_qual.level = 0; - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - - range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES); - - for (i = 0; i < range->num_bitrates; i++) - range->bitrate[i] = rtl8192_rates[i]; - - range->max_rts = DEFAULT_RTS_THRESHOLD; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->min_pmp = 0; - range->max_pmp = 5000000; - range->min_pmt = 0; - range->max_pmt = 65535 * 1000; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; - - for (i = 0, val = 0; i < 14; i++) { - if ((priv->rtllib->active_channel_map)[i + 1]) { - s32 freq_khz; - - range->freq[val].i = i + 1; - freq_khz = ieee80211_channel_to_freq_khz(i + 1, NL80211_BAND_2GHZ); - range->freq[val].m = freq_khz * 100; - range->freq[val].e = 1; - val++; - } - - if (val == IW_MAX_FREQUENCIES) - break; - } - range->num_frequency = val; - range->num_channels = val; - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE; - - /* Event capability (kernel + driver) */ - - return 0; -} - -static int _rtl92e_wx_set_scan(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - enum rt_rf_power_state rt_state; - int ret; - - if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { - if ((ieee->link_state >= RTLLIB_ASSOCIATING) && - (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) - return 0; - if ((priv->rtllib->link_state == MAC80211_LINKED) && - (priv->rtllib->cnt_after_link < 2)) - return 0; - } - - if (priv->hw_radio_off) { - netdev_info(dev, "================>%s(): hwradio off\n", - __func__); - return 0; - } - rt_state = priv->rtllib->rf_power_state; - if (!priv->up) - return -ENETDOWN; - if (priv->rtllib->link_detect_info.busy_traffic) - return -EAGAIN; - - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)b; - - if (req->essid_len) { - int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); - - ieee->current_network.ssid_len = len; - memcpy(ieee->current_network.ssid, req->essid, len); - } - } - - mutex_lock(&priv->wx_mutex); - - priv->rtllib->first_ie_in_scan = true; - - if (priv->rtllib->link_state != MAC80211_LINKED) { - if (rt_state == rf_off) { - if (priv->rtllib->rf_off_reason > - RF_CHANGE_BY_IPS) { - netdev_warn(dev, "%s(): RF is OFF.\n", - __func__); - mutex_unlock(&priv->wx_mutex); - return -1; - } - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); - } - rtllib_stop_scan(priv->rtllib); - if (priv->rtllib->rf_power_state != rf_off) { - priv->rtllib->actscanning = true; - - ieee->scan_operation_backup_handler(ieee->dev, SCAN_OPT_BACKUP); - - rtllib_start_scan_syncro(priv->rtllib); - - ieee->scan_operation_backup_handler(ieee->dev, SCAN_OPT_RESTORE); - } - ret = 0; - } else { - priv->rtllib->actscanning = true; - ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b); - } - - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_get_scan(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (!priv->up) - return -ENETDOWN; - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_set_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - - if (priv->hw_radio_off) { - netdev_info(dev, - "=========>%s():hw radio off,or Rf state is rf_off, return\n", - __func__); - return 0; - } - mutex_lock(&priv->wx_mutex); - ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_get_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_set_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (wrqu->data.length > IW_ESSID_MAX_SIZE) - return -E2BIG; - mutex_lock(&priv->wx_mutex); - wrqu->data.length = min_t(size_t, wrqu->data.length, - sizeof(priv->nick)); - memset(priv->nick, 0, sizeof(priv->nick)); - memcpy(priv->nick, extra, wrqu->data.length); - mutex_unlock(&priv->wx_mutex); - return 0; -} - -static int _rtl92e_wx_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - mutex_lock(&priv->wx_mutex); - wrqu->data.length = strlen(priv->nick); - memcpy(extra, priv->nick, wrqu->data.length); - wrqu->data.flags = 1; /* active */ - mutex_unlock(&priv->wx_mutex); - return 0; -} - -static int _rtl92e_wx_set_freq(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b); - - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra); -} - -static int _rtl92e_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - if (wrqu->frag.disabled) { - priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; - } else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - - priv->rtllib->fts = wrqu->frag.value & ~0x1; - } - - return 0; -} - -static int _rtl92e_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - wrqu->frag.value = priv->rtllib->fts; - wrqu->frag.fixed = 0; /* no auto select */ - wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); - - return 0; -} - -static int _rtl92e_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, char *extra) -{ - int ret; - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra); - - mutex_unlock(&priv->wx_mutex); - - return ret; -} - -static int _rtl92e_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_wap(priv->rtllib, info, wrqu, extra); -} - -static int _rtl92e_wx_get_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key); -} - -static int _rtl92e_wx_set_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int ret; - - struct rtllib_device *ieee = priv->rtllib; - u32 hwkey[4] = {0, 0, 0, 0}; - u8 mask = 0xff; - u32 key_idx = 0; - u8 zero_addr[4][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; - int i; - - if (priv->hw_radio_off) - return 0; - - if (!priv->up) - return -ENETDOWN; - - priv->rtllib->wx_set_enc = 1; - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); - mutex_lock(&priv->wx_mutex); - - ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key); - mutex_unlock(&priv->wx_mutex); - - if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { - ieee->pairwise_key_type = KEY_TYPE_NA; - ieee->group_key_type = KEY_TYPE_NA; - rtl92e_cam_reset(dev); - memset(priv->rtllib->swcamtable, 0, - sizeof(struct sw_cam_table) * 32); - goto end_hw_sec; - } - if (wrqu->encoding.length != 0) { - for (i = 0; i < 4; i++) { - hwkey[i] |= key[4 * i + 0] & mask; - if (i == 1 && (4 * i + 1) == wrqu->encoding.length) - mask = 0x00; - if (i == 3 && (4 * i + 1) == wrqu->encoding.length) - mask = 0x00; - hwkey[i] |= (key[4 * i + 1] & mask) << 8; - hwkey[i] |= (key[4 * i + 2] & mask) << 16; - hwkey[i] |= (key[4 * i + 3] & mask) << 24; - } - - switch (wrqu->encoding.flags & IW_ENCODE_INDEX) { - case 0: - key_idx = ieee->crypt_info.tx_keyidx; - break; - case 1: - key_idx = 0; - break; - case 2: - key_idx = 1; - break; - case 3: - key_idx = 2; - break; - case 4: - key_idx = 3; - break; - default: - break; - } - if (wrqu->encoding.length == 0x5) { - ieee->pairwise_key_type = KEY_TYPE_WEP40; - rtl92e_enable_hw_security_config(dev); - } - - else if (wrqu->encoding.length == 0xd) { - ieee->pairwise_key_type = KEY_TYPE_WEP104; - rtl92e_enable_hw_security_config(dev); - rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104, - zero_addr[key_idx], 0, hwkey); - rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104, - zero_addr[key_idx], hwkey); - } else { - netdev_info(dev, - "wrong type in WEP, not WEP40 and WEP104\n"); - } - } - -end_hw_sec: - priv->rtllib->wx_set_enc = 0; - return ret; -} - -#define R8192_MAX_RETRY 255 -static int _rtl92e_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - int err = 0; - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - if (wrqu->retry.flags & IW_RETRY_LIFETIME || - wrqu->retry.disabled) { - err = -EINVAL; - goto exit; - } - if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { - err = -EINVAL; - goto exit; - } - - if (wrqu->retry.value > R8192_MAX_RETRY) { - err = -EINVAL; - goto exit; - } - if (wrqu->retry.flags & IW_RETRY_MAX) - priv->retry_rts = wrqu->retry.value; - else - priv->retry_data = wrqu->retry.value; - - rtl92e_commit(dev); -exit: - mutex_unlock(&priv->wx_mutex); - - return err; -} - -static int _rtl92e_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = rtllib_priv(dev); - - wrqu->retry.disabled = 0; /* can't be disabled */ - - if ((wrqu->retry.flags & IW_RETRY_TYPE) == - IW_RETRY_LIFETIME) - return -EINVAL; - - if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - wrqu->retry.value = priv->retry_rts; - } else { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - wrqu->retry.value = priv->retry_data; - } - return 0; -} - -static int _rtl92e_wx_set_encode_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - - priv->rtllib->wx_set_enc = 1; - mutex_lock(&priv->rtllib->ips_mutex); - rtl92e_ips_leave(dev); - mutex_unlock(&priv->rtllib->ips_mutex); - - ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); - { - const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 zero[ETH_ALEN] = {0}; - u32 key[4] = {0}; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - struct iw_point *encoding = &wrqu->encoding; - u8 idx = 0, alg = 0, group = 0; - - if ((encoding->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - ieee->pairwise_key_type = KEY_TYPE_NA; - ieee->group_key_type = KEY_TYPE_NA; - rtl92e_cam_reset(dev); - memset(priv->rtllib->swcamtable, 0, - sizeof(struct sw_cam_table) * 32); - goto end_hw_sec; - } - alg = (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP : - ext->alg; - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) - idx--; - group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; - - if ((!group) || (alg == KEY_TYPE_WEP40)) { - if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) - alg = KEY_TYPE_WEP104; - ieee->pairwise_key_type = alg; - rtl92e_enable_hw_security_config(dev); - } - memcpy((u8 *)key, ext->key, 16); - - if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { - if (ext->key_len == 13) - ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; - rtl92e_set_key(dev, idx, idx, alg, zero, 0, key); - rtl92e_set_swcam(dev, idx, idx, alg, zero, key); - } else if (group) { - ieee->group_key_type = alg; - rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0, - key); - rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, key); - } else { - if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && - ieee->ht_info->current_ht_support) - rtl92e_writeb(dev, 0x173, 1); - rtl92e_set_key(dev, 4, idx, alg, - (u8 *)ieee->ap_mac_addr, 0, key); - rtl92e_set_swcam(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr, key); - } - } - -end_hw_sec: - priv->rtllib->wx_set_enc = 0; - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - int ret = 0; - - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - ret = rtllib_wx_set_auth(priv->rtllib, info, &data->param, extra); - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra); - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - int ret = 0; - - struct r8192_priv *priv = rtllib_priv(dev); - - if (priv->hw_radio_off) - return 0; - - mutex_lock(&priv->wx_mutex); - ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length); - mutex_unlock(&priv->wx_mutex); - return ret; -} - -static int _rtl92e_wx_get_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - int ret = 0; - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - - if (ieee->wpa_ie_len == 0 || !ieee->wpa_ie) { - data->data.length = 0; - return 0; - } - - if (data->data.length < ieee->wpa_ie_len) - return -E2BIG; - - data->data.length = ieee->wpa_ie_len; - memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); - return ret; -} - -#define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT) -static iw_handler r8192_wx_handlers[] = { - [IW_IOCTL(SIOCGIWNAME)] = _rtl92e_wx_get_name, - [IW_IOCTL(SIOCSIWFREQ)] = _rtl92e_wx_set_freq, - [IW_IOCTL(SIOCGIWFREQ)] = _rtl92e_wx_get_freq, - [IW_IOCTL(SIOCSIWMODE)] = _rtl92e_wx_set_mode, - [IW_IOCTL(SIOCGIWMODE)] = _rtl92e_wx_get_mode, - [IW_IOCTL(SIOCGIWRANGE)] = _rtl92e_wx_get_range, - [IW_IOCTL(SIOCSIWAP)] = _rtl92e_wx_set_wap, - [IW_IOCTL(SIOCGIWAP)] = _rtl92e_wx_get_wap, - [IW_IOCTL(SIOCSIWSCAN)] = _rtl92e_wx_set_scan, - [IW_IOCTL(SIOCGIWSCAN)] = _rtl92e_wx_get_scan, - [IW_IOCTL(SIOCSIWESSID)] = _rtl92e_wx_set_essid, - [IW_IOCTL(SIOCGIWESSID)] = _rtl92e_wx_get_essid, - [IW_IOCTL(SIOCSIWNICKN)] = _rtl92e_wx_set_nick, - [IW_IOCTL(SIOCGIWNICKN)] = _rtl92e_wx_get_nick, - [IW_IOCTL(SIOCSIWRATE)] = _rtl92e_wx_set_rate, - [IW_IOCTL(SIOCGIWRATE)] = _rtl92e_wx_get_rate, - [IW_IOCTL(SIOCSIWRTS)] = _rtl92e_wx_set_rts, - [IW_IOCTL(SIOCGIWRTS)] = _rtl92e_wx_get_rts, - [IW_IOCTL(SIOCSIWFRAG)] = _rtl92e_wx_set_frag, - [IW_IOCTL(SIOCGIWFRAG)] = _rtl92e_wx_get_frag, - [IW_IOCTL(SIOCSIWRETRY)] = _rtl92e_wx_set_retry, - [IW_IOCTL(SIOCGIWRETRY)] = _rtl92e_wx_get_retry, - [IW_IOCTL(SIOCSIWENCODE)] = _rtl92e_wx_set_enc, - [IW_IOCTL(SIOCGIWENCODE)] = _rtl92e_wx_get_enc, - [IW_IOCTL(SIOCSIWPOWER)] = _rtl92e_wx_set_power, - [IW_IOCTL(SIOCGIWPOWER)] = _rtl92e_wx_get_power, - [IW_IOCTL(SIOCSIWGENIE)] = _rtl92e_wx_set_gen_ie, - [IW_IOCTL(SIOCGIWGENIE)] = _rtl92e_wx_get_gen_ie, - [IW_IOCTL(SIOCSIWMLME)] = _rtl92e_wx_set_mlme, - [IW_IOCTL(SIOCSIWAUTH)] = _rtl92e_wx_set_auth, - [IW_IOCTL(SIOCSIWENCODEEXT)] = _rtl92e_wx_set_encode_ext, -}; - -static struct iw_statistics *_rtl92e_get_wireless_stats(struct net_device *dev) -{ - struct r8192_priv *priv = rtllib_priv(dev); - struct rtllib_device *ieee = priv->rtllib; - struct iw_statistics *wstats = &priv->wstats; - int tmp_level = 0; - int tmp_qual = 0; - int tmp_noise = 0; - - if (ieee->link_state < MAC80211_LINKED) { - wstats->qual.qual = 10; - wstats->qual.level = 0; - wstats->qual.noise = 0x100 - 100; /* -100 dBm */ - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; - } - - tmp_level = (&ieee->current_network)->stats.rssi; - tmp_qual = (&ieee->current_network)->stats.signal; - tmp_noise = (&ieee->current_network)->stats.noise; - - wstats->qual.level = tmp_level; - wstats->qual.qual = tmp_qual; - wstats->qual.noise = tmp_noise; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; -} - -const struct iw_handler_def r8192_wx_handlers_def = { - .standard = r8192_wx_handlers, - .num_standard = ARRAY_SIZE(r8192_wx_handlers), - .get_wireless_stats = _rtl92e_get_wireless_stats, -}; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h deleted file mode 100644 index d70a747ac1dd..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef R819x_WX_H -#define R819x_WX_H - -struct iw_handler_def; - -extern const struct iw_handler_def r8192_wx_handlers_def; -#endif diff --git a/drivers/staging/rtl8192e/rtl8192e/table.c b/drivers/staging/rtl8192e/rtl8192e/table.c deleted file mode 100644 index 0b5cc6049232..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/table.c +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "table.h" - -u32 RTL8192E_PHY_REG_1T2R_ARR[RTL8192E_PHY_REG_1T2R_ARR_LEN] = { - 0x800, 0x00000000, - 0x804, 0x00000001, - 0x808, 0x0000fc00, - 0x80c, 0x0000001c, - 0x810, 0x801010aa, - 0x814, 0x008514d0, - 0x818, 0x00000040, - 0x81c, 0x00000000, - 0x820, 0x00000004, - 0x824, 0x00690000, - 0x828, 0x00000004, - 0x82c, 0x00e90000, - 0x830, 0x00000004, - 0x834, 0x00690000, - 0x838, 0x00000004, - 0x83c, 0x00e90000, - 0x840, 0x00000000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x65a965a9, - 0x85c, 0x65a965a9, - 0x860, 0x001f0010, - 0x864, 0x007f0010, - 0x868, 0x001f0010, - 0x86c, 0x007f0010, - 0x870, 0x0f100f70, - 0x874, 0x0f100f70, - 0x878, 0x00000000, - 0x87c, 0x00000000, - 0x880, 0x6870e36c, - 0x884, 0xe3573600, - 0x888, 0x4260c340, - 0x88c, 0x0000ff00, - 0x890, 0x00000000, - 0x894, 0xfffffffe, - 0x898, 0x4c42382f, - 0x89c, 0x00656056, - 0x8b0, 0x00000000, - 0x8e0, 0x00000000, - 0x8e4, 0x00000000, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x31121311, - 0xa00, 0x00d0c7d8, - 0xa04, 0x811f0008, - 0xa08, 0x80cd8300, - 0xa0c, 0x2e62740f, - 0xa10, 0x95009b78, - 0xa14, 0x11145008, - 0xa18, 0x00881117, - 0xa1c, 0x89140fa0, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00000000, - 0xc00, 0x00000040, - 0xc04, 0x00005433, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08000000, - 0xc1c, 0x40000100, - 0xc20, 0x08000000, - 0xc24, 0x40000100, - 0xc28, 0x08000000, - 0xc2c, 0x40000100, - 0xc30, 0x6de9ac44, - 0xc34, 0x465c52cd, - 0xc38, 0x497f5994, - 0xc3c, 0x0a969764, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020000, - 0xc4c, 0x00000300, - 0xc50, 0x69543420, - 0xc54, 0x433c0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x69543420, - 0xc64, 0x433c0094, - 0xc68, 0x69543420, - 0xc6c, 0x433c0094, - 0xc70, 0x2c7f000d, - 0xc74, 0x0186175b, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20000000, - 0xc88, 0x40000100, - 0xc8c, 0x20200000, - 0xc90, 0x40000100, - 0xc94, 0x00000000, - 0xc98, 0x40000100, - 0xc9c, 0x00000000, - 0xca0, 0x00492492, - 0xca4, 0x00000000, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x00492492, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xd00, 0x00000750, - 0xd04, 0x00000403, - 0xd08, 0x0000907f, - 0xd0c, 0x00000001, - 0xd10, 0xa0633333, - 0xd14, 0x33333c63, - 0xd18, 0x6a8f5b6b, - 0xd1c, 0x00000000, - 0xd20, 0x00000000, - 0xd24, 0x00000000, - 0xd28, 0x00000000, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x00000000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x024dbd02, - 0xd58, 0x00000000, - 0xd5c, 0x04032064, - 0xe00, 0x161a1a1a, - 0xe04, 0x12121416, - 0xe08, 0x00001800, - 0xe0c, 0x00000000, - 0xe10, 0x161a1a1a, - 0xe14, 0x12121416, - 0xe18, 0x161a1a1a, - 0xe1c, 0x12121416, -}; - -u32 RTL8192E_RADIO_A_ARR[RTL8192E_RADIO_A_ARR_LEN] = { - 0x019, 0x00000003, - 0x000, 0x000000bf, - 0x001, 0x00000ee0, - 0x002, 0x0000004c, - 0x003, 0x000007f1, - 0x004, 0x00000975, - 0x005, 0x00000c58, - 0x006, 0x00000ae6, - 0x007, 0x000000ca, - 0x008, 0x00000e1c, - 0x009, 0x000007f0, - 0x00a, 0x000009d0, - 0x00b, 0x000001ba, - 0x00c, 0x00000240, - 0x00e, 0x00000020, - 0x00f, 0x00000990, - 0x012, 0x00000806, - 0x014, 0x000005ab, - 0x015, 0x00000f80, - 0x016, 0x00000020, - 0x017, 0x00000597, - 0x018, 0x0000050a, - 0x01a, 0x00000f80, - 0x01b, 0x00000f5e, - 0x01c, 0x00000008, - 0x01d, 0x00000607, - 0x01e, 0x000006cc, - 0x01f, 0x00000000, - 0x020, 0x000001a5, - 0x01f, 0x00000001, - 0x020, 0x00000165, - 0x01f, 0x00000002, - 0x020, 0x000000c6, - 0x01f, 0x00000003, - 0x020, 0x00000086, - 0x01f, 0x00000004, - 0x020, 0x00000046, - 0x01f, 0x00000005, - 0x020, 0x000001e6, - 0x01f, 0x00000006, - 0x020, 0x000001a6, - 0x01f, 0x00000007, - 0x020, 0x00000166, - 0x01f, 0x00000008, - 0x020, 0x000000c7, - 0x01f, 0x00000009, - 0x020, 0x00000087, - 0x01f, 0x0000000a, - 0x020, 0x000000f7, - 0x01f, 0x0000000b, - 0x020, 0x000000d7, - 0x01f, 0x0000000c, - 0x020, 0x000000b7, - 0x01f, 0x0000000d, - 0x020, 0x00000097, - 0x01f, 0x0000000e, - 0x020, 0x00000077, - 0x01f, 0x0000000f, - 0x020, 0x00000057, - 0x01f, 0x00000010, - 0x020, 0x00000037, - 0x01f, 0x00000011, - 0x020, 0x000000fb, - 0x01f, 0x00000012, - 0x020, 0x000000db, - 0x01f, 0x00000013, - 0x020, 0x000000bb, - 0x01f, 0x00000014, - 0x020, 0x000000ff, - 0x01f, 0x00000015, - 0x020, 0x000000e3, - 0x01f, 0x00000016, - 0x020, 0x000000c3, - 0x01f, 0x00000017, - 0x020, 0x000000a3, - 0x01f, 0x00000018, - 0x020, 0x00000083, - 0x01f, 0x00000019, - 0x020, 0x00000063, - 0x01f, 0x0000001a, - 0x020, 0x00000043, - 0x01f, 0x0000001b, - 0x020, 0x00000023, - 0x01f, 0x0000001c, - 0x020, 0x00000003, - 0x01f, 0x0000001d, - 0x020, 0x000001e3, - 0x01f, 0x0000001e, - 0x020, 0x000001c3, - 0x01f, 0x0000001f, - 0x020, 0x000001a3, - 0x01f, 0x00000020, - 0x020, 0x00000183, - 0x01f, 0x00000021, - 0x020, 0x00000163, - 0x01f, 0x00000022, - 0x020, 0x00000143, - 0x01f, 0x00000023, - 0x020, 0x00000123, - 0x01f, 0x00000024, - 0x020, 0x00000103, - 0x023, 0x00000203, - 0x024, 0x00000100, - 0x00b, 0x000001ba, - 0x02c, 0x000003d7, - 0x02d, 0x00000ff0, - 0x000, 0x00000037, - 0x004, 0x00000160, - 0x007, 0x00000080, - 0x002, 0x0000088d, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x016, 0x00000200, - 0x016, 0x00000380, - 0x016, 0x00000020, - 0x016, 0x000001a0, - 0x000, 0x000000bf, - 0x00d, 0x0000001f, - 0x00d, 0x00000c9f, - 0x002, 0x0000004d, - 0x000, 0x00000cbf, - 0x004, 0x00000975, - 0x007, 0x00000700, -}; - -u32 RTL8192E_RADIO_B_ARR[RTL8192E_RADIO_B_ARR_LEN] = { - 0x019, 0x00000003, - 0x000, 0x000000bf, - 0x001, 0x000006e0, - 0x002, 0x0000004c, - 0x003, 0x000007f1, - 0x004, 0x00000975, - 0x005, 0x00000c58, - 0x006, 0x00000ae6, - 0x007, 0x000000ca, - 0x008, 0x00000e1c, - 0x000, 0x000000b7, - 0x00a, 0x00000850, - 0x000, 0x000000bf, - 0x00b, 0x000001ba, - 0x00c, 0x00000240, - 0x00e, 0x00000020, - 0x015, 0x00000f80, - 0x016, 0x00000020, - 0x017, 0x00000597, - 0x018, 0x0000050a, - 0x01a, 0x00000e00, - 0x01b, 0x00000f5e, - 0x01d, 0x00000607, - 0x01e, 0x000006cc, - 0x00b, 0x000001ba, - 0x023, 0x00000203, - 0x024, 0x00000100, - 0x000, 0x00000037, - 0x004, 0x00000160, - 0x016, 0x00000200, - 0x016, 0x00000380, - 0x016, 0x00000020, - 0x016, 0x000001a0, - 0x00d, 0x00000ccc, - 0x000, 0x000000bf, - 0x002, 0x0000004d, - 0x000, 0x00000cbf, - 0x004, 0x00000975, - 0x007, 0x00000700, -}; - -u32 RTL8192E_MACPHY_ARR[] = { - 0x03c, 0xffff0000, 0x00000f0f, - 0x340, 0xffffffff, 0x161a1a1a, - 0x344, 0xffffffff, 0x12121416, - 0x348, 0x0000ffff, 0x00001818, - 0x12c, 0xffffffff, 0x04000802, - 0x318, 0x00000fff, 0x00000100, -}; - -u32 RTL8192E_MACPHY_ARR_PG[] = { - 0x03c, 0xffff0000, 0x00000f0f, - 0xe00, 0xffffffff, 0x06090909, - 0xe04, 0xffffffff, 0x00030306, - 0xe08, 0x0000ff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0f, - 0xe14, 0xffffffff, 0x06070809, - 0xe18, 0xffffffff, 0x0a0c0d0f, - 0xe1c, 0xffffffff, 0x06070809, - 0x12c, 0xffffffff, 0x04000802, - 0x318, 0x00000fff, 0x00000800, -}; - -u32 RTL8192E_AGCTAB_ARR[RTL8192E_AGCTAB_ARR_LEN] = { - 0xc78, 0x7d000001, - 0xc78, 0x7d010001, - 0xc78, 0x7d020001, - 0xc78, 0x7d030001, - 0xc78, 0x7d040001, - 0xc78, 0x7d050001, - 0xc78, 0x7c060001, - 0xc78, 0x7b070001, - 0xc78, 0x7a080001, - 0xc78, 0x79090001, - 0xc78, 0x780a0001, - 0xc78, 0x770b0001, - 0xc78, 0x760c0001, - 0xc78, 0x750d0001, - 0xc78, 0x740e0001, - 0xc78, 0x730f0001, - 0xc78, 0x72100001, - 0xc78, 0x71110001, - 0xc78, 0x70120001, - 0xc78, 0x6f130001, - 0xc78, 0x6e140001, - 0xc78, 0x6d150001, - 0xc78, 0x6c160001, - 0xc78, 0x6b170001, - 0xc78, 0x6a180001, - 0xc78, 0x69190001, - 0xc78, 0x681a0001, - 0xc78, 0x671b0001, - 0xc78, 0x661c0001, - 0xc78, 0x651d0001, - 0xc78, 0x641e0001, - 0xc78, 0x491f0001, - 0xc78, 0x48200001, - 0xc78, 0x47210001, - 0xc78, 0x46220001, - 0xc78, 0x45230001, - 0xc78, 0x44240001, - 0xc78, 0x43250001, - 0xc78, 0x28260001, - 0xc78, 0x27270001, - 0xc78, 0x26280001, - 0xc78, 0x25290001, - 0xc78, 0x242a0001, - 0xc78, 0x232b0001, - 0xc78, 0x222c0001, - 0xc78, 0x212d0001, - 0xc78, 0x202e0001, - 0xc78, 0x0a2f0001, - 0xc78, 0x08300001, - 0xc78, 0x06310001, - 0xc78, 0x05320001, - 0xc78, 0x04330001, - 0xc78, 0x03340001, - 0xc78, 0x02350001, - 0xc78, 0x01360001, - 0xc78, 0x00370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7d400001, - 0xc78, 0x7d410001, - 0xc78, 0x7d420001, - 0xc78, 0x7d430001, - 0xc78, 0x7d440001, - 0xc78, 0x7d450001, - 0xc78, 0x7c460001, - 0xc78, 0x7b470001, - 0xc78, 0x7a480001, - 0xc78, 0x79490001, - 0xc78, 0x784a0001, - 0xc78, 0x774b0001, - 0xc78, 0x764c0001, - 0xc78, 0x754d0001, - 0xc78, 0x744e0001, - 0xc78, 0x734f0001, - 0xc78, 0x72500001, - 0xc78, 0x71510001, - 0xc78, 0x70520001, - 0xc78, 0x6f530001, - 0xc78, 0x6e540001, - 0xc78, 0x6d550001, - 0xc78, 0x6c560001, - 0xc78, 0x6b570001, - 0xc78, 0x6a580001, - 0xc78, 0x69590001, - 0xc78, 0x685a0001, - 0xc78, 0x675b0001, - 0xc78, 0x665c0001, - 0xc78, 0x655d0001, - 0xc78, 0x645e0001, - 0xc78, 0x495f0001, - 0xc78, 0x48600001, - 0xc78, 0x47610001, - 0xc78, 0x46620001, - 0xc78, 0x45630001, - 0xc78, 0x44640001, - 0xc78, 0x43650001, - 0xc78, 0x28660001, - 0xc78, 0x27670001, - 0xc78, 0x26680001, - 0xc78, 0x25690001, - 0xc78, 0x246a0001, - 0xc78, 0x236b0001, - 0xc78, 0x226c0001, - 0xc78, 0x216d0001, - 0xc78, 0x206e0001, - 0xc78, 0x0a6f0001, - 0xc78, 0x08700001, - 0xc78, 0x06710001, - 0xc78, 0x05720001, - 0xc78, 0x04730001, - 0xc78, 0x03740001, - 0xc78, 0x02750001, - 0xc78, 0x01760001, - 0xc78, 0x00770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x2e00001e, - 0xc78, 0x2e01001e, - 0xc78, 0x2e02001e, - 0xc78, 0x2e03001e, - 0xc78, 0x2e04001e, - 0xc78, 0x2e05001e, - 0xc78, 0x3006001e, - 0xc78, 0x3407001e, - 0xc78, 0x3908001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3f0a001e, - 0xc78, 0x420b001e, - 0xc78, 0x440c001e, - 0xc78, 0x450d001e, - 0xc78, 0x460e001e, - 0xc78, 0x460f001e, - 0xc78, 0x4710001e, - 0xc78, 0x4811001e, - 0xc78, 0x4912001e, - 0xc78, 0x4a13001e, - 0xc78, 0x4b14001e, - 0xc78, 0x4b15001e, - 0xc78, 0x4c16001e, - 0xc78, 0x4d17001e, - 0xc78, 0x4e18001e, - 0xc78, 0x4f19001e, - 0xc78, 0x4f1a001e, - 0xc78, 0x501b001e, - 0xc78, 0x511c001e, - 0xc78, 0x521d001e, - 0xc78, 0x521e001e, - 0xc78, 0x531f001e, - 0xc78, 0x5320001e, - 0xc78, 0x5421001e, - 0xc78, 0x5522001e, - 0xc78, 0x5523001e, - 0xc78, 0x5624001e, - 0xc78, 0x5725001e, - 0xc78, 0x5726001e, - 0xc78, 0x5827001e, - 0xc78, 0x5828001e, - 0xc78, 0x5929001e, - 0xc78, 0x592a001e, - 0xc78, 0x5a2b001e, - 0xc78, 0x5b2c001e, - 0xc78, 0x5c2d001e, - 0xc78, 0x5c2e001e, - 0xc78, 0x5d2f001e, - 0xc78, 0x5e30001e, - 0xc78, 0x5f31001e, - 0xc78, 0x6032001e, - 0xc78, 0x6033001e, - 0xc78, 0x6134001e, - 0xc78, 0x6235001e, - 0xc78, 0x6336001e, - 0xc78, 0x6437001e, - 0xc78, 0x6438001e, - 0xc78, 0x6539001e, - 0xc78, 0x663a001e, - 0xc78, 0x673b001e, - 0xc78, 0x673c001e, - 0xc78, 0x683d001e, - 0xc78, 0x693e001e, - 0xc78, 0x6a3f001e, -}; diff --git a/drivers/staging/rtl8192e/rtl8192e/table.h b/drivers/staging/rtl8192e/rtl8192e/table.h deleted file mode 100644 index 82be44a9d4e8..000000000000 --- a/drivers/staging/rtl8192e/rtl8192e/table.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef __INC_HAL8192PciE_FW_IMG_H -#define __INC_HAL8192PciE_FW_IMG_H - -/*Created on 2008/11/18, 3: 7*/ - -#include <linux/types.h> - -#define RTL8192E_PHY_REG_1T2R_ARR_LEN 296 -extern u32 RTL8192E_PHY_REG_1T2R_ARR[RTL8192E_PHY_REG_1T2R_ARR_LEN]; -#define RTL8192E_RADIO_A_ARR_LEN 246 -extern u32 RTL8192E_RADIO_A_ARR[RTL8192E_RADIO_A_ARR_LEN]; -#define RTL8192E_RADIO_B_ARR_LEN 78 -extern u32 RTL8192E_RADIO_B_ARR[RTL8192E_RADIO_B_ARR_LEN]; -#define RTL8192E_MACPHY_ARR_LEN 18 -extern u32 RTL8192E_MACPHY_ARR[RTL8192E_MACPHY_ARR_LEN]; -#define RTL8192E_MACPHY_ARR_PG_LEN 30 -extern u32 RTL8192E_MACPHY_ARR_PG[RTL8192E_MACPHY_ARR_PG_LEN]; -#define RTL8192E_AGCTAB_ARR_LEN 384 -extern u32 RTL8192E_AGCTAB_ARR[RTL8192E_AGCTAB_ARR_LEN]; - -#endif diff --git a/drivers/staging/rtl8192e/rtl819x_BA.h b/drivers/staging/rtl8192e/rtl819x_BA.h deleted file mode 100644 index 8a35d7a3eee1..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_BA.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _BATYPE_H_ -#define _BATYPE_H_ - -#define BA_SETUP_TIMEOUT 200 - -#define BA_POLICY_DELAYED 0 -#define BA_POLICY_IMMEDIATE 1 - -#define ADDBA_STATUS_SUCCESS 0 -#define ADDBA_STATUS_REFUSED 37 -#define ADDBA_STATUS_INVALID_PARAM 38 - -#define DELBA_REASON_END_BA 37 -#define DELBA_REASON_UNKNOWN_BA 38 -#define DELBA_REASON_TIMEOUT 39 -union sequence_control { - u16 short_data; - struct { - u16 frag_num:4; - u16 seq_num:12; - } field; -}; - -union ba_param_set { - u8 char_data[2]; - u16 short_data; - struct { - u16 amsdu_support:1; - u16 ba_policy:1; - u16 tid:4; - u16 buffer_size:10; - } field; -}; - -union delba_param_set { - u8 char_data[2]; - u16 short_data; - struct { - u16 reserved:11; - u16 initiator:1; - u16 tid:4; - } field; -}; - -struct ba_record { - struct timer_list timer; - u8 b_valid; - u8 dialog_token; - union ba_param_set ba_param_set; - u16 ba_timeout_value; - union sequence_control ba_start_seq_ctrl; -}; - -#endif diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c deleted file mode 100644 index c400d4f8ff9a..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_BAProc.c +++ /dev/null @@ -1,544 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include <asm/byteorder.h> -#include <linux/unaligned.h> -#include <linux/etherdevice.h> -#include "rtllib.h" -#include "rtl819x_BA.h" - -static void activate_ba_entry(struct ba_record *ba, u16 time) -{ - ba->b_valid = true; - if (time != 0) - mod_timer(&ba->timer, jiffies + msecs_to_jiffies(time)); -} - -static void deactivate_ba_entry(struct rtllib_device *ieee, struct ba_record *ba) -{ - ba->b_valid = false; - del_timer_sync(&ba->timer); -} - -static u8 tx_ts_delete_ba(struct rtllib_device *ieee, struct tx_ts_record *ts) -{ - struct ba_record *admitted_ba = &ts->tx_admitted_ba_record; - struct ba_record *pending_ba = &ts->tx_pending_ba_record; - u8 send_del_ba = false; - - if (pending_ba->b_valid) { - deactivate_ba_entry(ieee, pending_ba); - send_del_ba = true; - } - - if (admitted_ba->b_valid) { - deactivate_ba_entry(ieee, admitted_ba); - send_del_ba = true; - } - return send_del_ba; -} - -static u8 rx_ts_delete_ba(struct rtllib_device *ieee, struct rx_ts_record *ts) -{ - struct ba_record *ba = &ts->rx_admitted_ba_record; - u8 send_del_ba = false; - - if (ba->b_valid) { - deactivate_ba_entry(ieee, ba); - send_del_ba = true; - } - - return send_del_ba; -} - -void rtllib_reset_ba_entry(struct ba_record *ba) -{ - ba->b_valid = false; - ba->ba_param_set.short_data = 0; - ba->ba_timeout_value = 0; - ba->dialog_token = 0; - ba->ba_start_seq_ctrl.short_data = 0; -} - -static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *dst, - struct ba_record *ba, - u16 status_code, u8 type) -{ - struct sk_buff *skb = NULL; - struct ieee80211_hdr_3addr *ba_req = NULL; - u8 *tag = NULL; - u16 len = ieee->tx_headroom + 9; - - netdev_dbg(ieee->dev, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n", - __func__, type, dst, ieee->dev); - - if (!ba) { - netdev_warn(ieee->dev, "ba is NULL\n"); - return NULL; - } - skb = dev_alloc_skb(len + sizeof(struct ieee80211_hdr_3addr)); - if (!skb) - return NULL; - - memset(skb->data, 0, sizeof(struct ieee80211_hdr_3addr)); - - skb_reserve(skb, ieee->tx_headroom); - - ba_req = skb_put(skb, sizeof(struct ieee80211_hdr_3addr)); - - ether_addr_copy(ba_req->addr1, dst); - ether_addr_copy(ba_req->addr2, ieee->dev->dev_addr); - - ether_addr_copy(ba_req->addr3, ieee->current_network.bssid); - ba_req->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION); - - tag = skb_put(skb, 9); - *tag++ = ACT_CAT_BA; - *tag++ = type; - *tag++ = ba->dialog_token; - - if (type == ACT_ADDBARSP) { - put_unaligned_le16(status_code, tag); - tag += 2; - } - - put_unaligned_le16(ba->ba_param_set.short_data, tag); - tag += 2; - - put_unaligned_le16(ba->ba_timeout_value, tag); - tag += 2; - - if (type == ACT_ADDBAREQ) { - memcpy(tag, (u8 *)&ba->ba_start_seq_ctrl, 2); - tag += 2; - } - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", DUMP_PREFIX_NONE, skb->data, - __func__, skb->len); -#endif - return skb; -} - -static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst, - struct ba_record *ba, - enum tr_select tx_rx_select, u16 reason_code) -{ - union delba_param_set del_ba_param_set; - struct sk_buff *skb = NULL; - struct ieee80211_hdr_3addr *del_ba = NULL; - u8 *tag = NULL; - u16 len = 6 + ieee->tx_headroom; - - if (net_ratelimit()) - netdev_dbg(ieee->dev, "%s(): reason_code(%d) sentd to: %pM\n", - __func__, reason_code, dst); - - memset(&del_ba_param_set, 0, 2); - - del_ba_param_set.field.initiator = (tx_rx_select == TX_DIR) ? 1 : 0; - del_ba_param_set.field.tid = ba->ba_param_set.field.tid; - - skb = dev_alloc_skb(len + sizeof(struct ieee80211_hdr_3addr)); - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - del_ba = skb_put(skb, sizeof(struct ieee80211_hdr_3addr)); - - ether_addr_copy(del_ba->addr1, dst); - ether_addr_copy(del_ba->addr2, ieee->dev->dev_addr); - ether_addr_copy(del_ba->addr3, ieee->current_network.bssid); - del_ba->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION); - - tag = skb_put(skb, 6); - - *tag++ = ACT_CAT_BA; - *tag++ = ACT_DELBA; - - put_unaligned_le16(del_ba_param_set.short_data, tag); - tag += 2; - - put_unaligned_le16(reason_code, tag); - tag += 2; - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", DUMP_PREFIX_NONE, skb->data, - __func__, skb->len); -#endif - return skb; -} - -static void rtllib_send_add_ba_req(struct rtllib_device *ieee, u8 *dst, - struct ba_record *ba) -{ - struct sk_buff *skb; - - skb = rtllib_ADDBA(ieee, dst, ba, 0, ACT_ADDBAREQ); - - if (skb) - softmac_mgmt_xmit(skb, ieee); - else - netdev_dbg(ieee->dev, "Failed to generate ADDBAReq packet.\n"); -} - -static void rtllib_send_add_ba_rsp(struct rtllib_device *ieee, u8 *dst, - struct ba_record *ba, u16 status_code) -{ - struct sk_buff *skb; - - skb = rtllib_ADDBA(ieee, dst, ba, status_code, ACT_ADDBARSP); - if (skb) - softmac_mgmt_xmit(skb, ieee); - else - netdev_dbg(ieee->dev, "Failed to generate ADDBARsp packet.\n"); -} - -static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst, - struct ba_record *ba, enum tr_select tx_rx_select, - u16 reason_code) -{ - struct sk_buff *skb; - - skb = rtllib_DELBA(ieee, dst, ba, tx_rx_select, reason_code); - if (skb) - softmac_mgmt_xmit(skb, ieee); - else - netdev_dbg(ieee->dev, "Failed to generate DELBA packet.\n"); -} - -int rtllib_rx_add_ba_req(struct rtllib_device *ieee, struct sk_buff *skb) -{ - struct ieee80211_hdr_3addr *req = NULL; - u16 rc = 0; - u8 *dst = NULL, *dialog_token = NULL, *tag = NULL; - struct ba_record *ba = NULL; - union ba_param_set *ba_param_set = NULL; - u16 *ba_timeout_value = NULL; - union sequence_control *ba_start_seq_ctrl = NULL; - struct rx_ts_record *ts = NULL; - - if (skb->len < sizeof(struct ieee80211_hdr_3addr) + 9) { - netdev_warn(ieee->dev, "Invalid skb len in BAREQ(%d / %d)\n", - (int)skb->len, - (int)(sizeof(struct ieee80211_hdr_3addr) + 9)); - return -1; - } - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", DUMP_PREFIX_NONE, __func__, - skb->data, skb->len); -#endif - - req = (struct ieee80211_hdr_3addr *)skb->data; - tag = (u8 *)req; - dst = (u8 *)(&req->addr2[0]); - tag += sizeof(struct ieee80211_hdr_3addr); - dialog_token = tag + 2; - ba_param_set = (union ba_param_set *)(tag + 3); - ba_timeout_value = (u16 *)(tag + 5); - ba_start_seq_ctrl = (union sequence_control *)(req + 7); - - if (!ieee->current_network.qos_data.active || - !ieee->ht_info->current_ht_support || - (ieee->ht_info->iot_action & HT_IOT_ACT_REJECT_ADDBA_REQ)) { - rc = ADDBA_STATUS_REFUSED; - netdev_warn(ieee->dev, - "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", - ieee->current_network.qos_data.active, - ieee->ht_info->current_ht_support); - goto on_add_ba_req_fail; - } - if (!rtllib_get_ts(ieee, (struct ts_common_info **)&ts, dst, - (u8)(ba_param_set->field.tid), RX_DIR, true)) { - rc = ADDBA_STATUS_REFUSED; - netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__); - goto on_add_ba_req_fail; - } - ba = &ts->rx_admitted_ba_record; - - if (ba_param_set->field.ba_policy == BA_POLICY_DELAYED) { - rc = ADDBA_STATUS_INVALID_PARAM; - netdev_warn(ieee->dev, "%s(): BA Policy is not correct\n", - __func__); - goto on_add_ba_req_fail; - } - - rtllib_flush_rx_ts_pending_pkts(ieee, ts); - - deactivate_ba_entry(ieee, ba); - ba->dialog_token = *dialog_token; - ba->ba_param_set = *ba_param_set; - ba->ba_timeout_value = *ba_timeout_value; - ba->ba_start_seq_ctrl = *ba_start_seq_ctrl; - - if (ieee->get_half_nmode_support_by_aps_handler(ieee->dev) || - (ieee->ht_info->iot_action & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT)) - ba->ba_param_set.field.buffer_size = 1; - else - ba->ba_param_set.field.buffer_size = 32; - - activate_ba_entry(ba, 0); - rtllib_send_add_ba_rsp(ieee, dst, ba, ADDBA_STATUS_SUCCESS); - - return 0; - -on_add_ba_req_fail: - { - struct ba_record BA; - - BA.ba_param_set = *ba_param_set; - BA.ba_timeout_value = *ba_timeout_value; - BA.dialog_token = *dialog_token; - BA.ba_param_set.field.ba_policy = BA_POLICY_IMMEDIATE; - rtllib_send_add_ba_rsp(ieee, dst, &BA, rc); - return 0; - } -} - -int rtllib_rx_add_ba_rsp(struct rtllib_device *ieee, struct sk_buff *skb) -{ - struct ieee80211_hdr_3addr *rsp = NULL; - struct ba_record *pending_ba, *admitted_ba; - struct tx_ts_record *ts = NULL; - u8 *dst = NULL, *dialog_token = NULL, *tag = NULL; - u16 *status_code = NULL, *ba_timeout_value = NULL; - union ba_param_set *ba_param_set = NULL; - u16 reason_code; - - if (skb->len < sizeof(struct ieee80211_hdr_3addr) + 9) { - netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n", - (int)skb->len, - (int)(sizeof(struct ieee80211_hdr_3addr) + 9)); - return -1; - } - rsp = (struct ieee80211_hdr_3addr *)skb->data; - tag = (u8 *)rsp; - dst = (u8 *)(&rsp->addr2[0]); - tag += sizeof(struct ieee80211_hdr_3addr); - dialog_token = tag + 2; - status_code = (u16 *)(tag + 3); - ba_param_set = (union ba_param_set *)(tag + 5); - ba_timeout_value = (u16 *)(tag + 7); - - if (!ieee->current_network.qos_data.active || - !ieee->ht_info->current_ht_support || - !ieee->ht_info->current_ampdu_enable) { - netdev_warn(ieee->dev, - "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n", - ieee->current_network.qos_data.active, - ieee->ht_info->current_ht_support, - ieee->ht_info->current_ampdu_enable); - reason_code = DELBA_REASON_UNKNOWN_BA; - goto on_add_ba_rsp_reject; - } - - if (!rtllib_get_ts(ieee, (struct ts_common_info **)&ts, dst, - (u8)(ba_param_set->field.tid), TX_DIR, false)) { - netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__); - reason_code = DELBA_REASON_UNKNOWN_BA; - goto on_add_ba_rsp_reject; - } - - ts->add_ba_req_in_progress = false; - pending_ba = &ts->tx_pending_ba_record; - admitted_ba = &ts->tx_admitted_ba_record; - - if (admitted_ba->b_valid) { - netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n", - __func__); - return -1; - } else if (!pending_ba->b_valid || - (*dialog_token != pending_ba->dialog_token)) { - netdev_warn(ieee->dev, - "%s(): ADDBA Rsp. BA invalid, DELBA!\n", - __func__); - reason_code = DELBA_REASON_UNKNOWN_BA; - goto on_add_ba_rsp_reject; - } else { - netdev_dbg(ieee->dev, - "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", - __func__, *status_code); - deactivate_ba_entry(ieee, pending_ba); - } - - if (*status_code == ADDBA_STATUS_SUCCESS) { - if (ba_param_set->field.ba_policy == BA_POLICY_DELAYED) { - ts->add_ba_req_delayed = true; - deactivate_ba_entry(ieee, admitted_ba); - reason_code = DELBA_REASON_END_BA; - goto on_add_ba_rsp_reject; - } - - admitted_ba->dialog_token = *dialog_token; - admitted_ba->ba_timeout_value = *ba_timeout_value; - admitted_ba->ba_start_seq_ctrl = pending_ba->ba_start_seq_ctrl; - admitted_ba->ba_param_set = *ba_param_set; - deactivate_ba_entry(ieee, admitted_ba); - activate_ba_entry(admitted_ba, *ba_timeout_value); - } else { - ts->add_ba_req_delayed = true; - ts->disable_add_ba = true; - reason_code = DELBA_REASON_END_BA; - goto on_add_ba_rsp_reject; - } - - return 0; - -on_add_ba_rsp_reject: - { - struct ba_record BA; - - BA.ba_param_set = *ba_param_set; - rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, reason_code); - return 0; - } -} - -int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) -{ - struct ieee80211_hdr_3addr *delba = NULL; - union delba_param_set *del_ba_param_set = NULL; - u8 *dst = NULL; - - if (skb->len < sizeof(struct ieee80211_hdr_3addr) + 6) { - netdev_warn(ieee->dev, "Invalid skb len in DELBA(%d / %d)\n", - (int)skb->len, - (int)(sizeof(struct ieee80211_hdr_3addr) + 6)); - return -1; - } - - if (!ieee->current_network.qos_data.active || - !ieee->ht_info->current_ht_support) { - netdev_warn(ieee->dev, - "received DELBA while QOS or HT is not supported(%d, %d)\n", - ieee->current_network. qos_data.active, - ieee->ht_info->current_ht_support); - return -1; - } - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", DUMP_PREFIX_NONE, skb->data, - __func__, skb->len); -#endif - delba = (struct ieee80211_hdr_3addr *)skb->data; - dst = (u8 *)(&delba->addr2[0]); - del_ba_param_set = (union delba_param_set *)&delba->seq_ctrl + 2; - - if (del_ba_param_set->field.initiator == 1) { - struct rx_ts_record *ts; - - if (!rtllib_get_ts(ieee, (struct ts_common_info **)&ts, dst, - (u8)del_ba_param_set->field.tid, RX_DIR, false)) { - netdev_warn(ieee->dev, - "%s(): can't get TS for RXTS. dst:%pM TID:%d\n", - __func__, dst, - (u8)del_ba_param_set->field.tid); - return -1; - } - - rx_ts_delete_ba(ieee, ts); - } else { - struct tx_ts_record *ts; - - if (!rtllib_get_ts(ieee, (struct ts_common_info **)&ts, dst, - (u8)del_ba_param_set->field.tid, TX_DIR, false)) { - netdev_warn(ieee->dev, "%s(): can't get TS for TXTS\n", - __func__); - return -1; - } - - ts->using_ba = false; - ts->add_ba_req_in_progress = false; - ts->add_ba_req_delayed = false; - del_timer_sync(&ts->ts_add_ba_timer); - tx_ts_delete_ba(ieee, ts); - } - return 0; -} - -void rtllib_ts_init_add_ba(struct rtllib_device *ieee, struct tx_ts_record *ts, - u8 policy, u8 overwrite_pending) -{ - struct ba_record *ba = &ts->tx_pending_ba_record; - - if (ba->b_valid && !overwrite_pending) - return; - - deactivate_ba_entry(ieee, ba); - - ba->dialog_token++; - ba->ba_param_set.field.amsdu_support = 0; - ba->ba_param_set.field.ba_policy = policy; - ba->ba_param_set.field.tid = ts->ts_common_info.tspec.ts_id; - ba->ba_param_set.field.buffer_size = 32; - ba->ba_timeout_value = 0; - ba->ba_start_seq_ctrl.field.seq_num = (ts->tx_cur_seq + 3) % 4096; - - activate_ba_entry(ba, BA_SETUP_TIMEOUT); - - rtllib_send_add_ba_req(ieee, ts->ts_common_info.addr, ba); -} - -void rtllib_ts_init_del_ba(struct rtllib_device *ieee, - struct ts_common_info *ts_common_info, - enum tr_select tx_rx_select) -{ - if (tx_rx_select == TX_DIR) { - struct tx_ts_record *ts = - (struct tx_ts_record *)ts_common_info; - - if (tx_ts_delete_ba(ieee, ts)) - rtllib_send_DELBA(ieee, ts_common_info->addr, - (ts->tx_admitted_ba_record.b_valid) ? - (&ts->tx_admitted_ba_record) : - (&ts->tx_pending_ba_record), - tx_rx_select, DELBA_REASON_END_BA); - } else if (tx_rx_select == RX_DIR) { - struct rx_ts_record *ts = - (struct rx_ts_record *)ts_common_info; - if (rx_ts_delete_ba(ieee, ts)) - rtllib_send_DELBA(ieee, ts_common_info->addr, - &ts->rx_admitted_ba_record, - tx_rx_select, DELBA_REASON_END_BA); - } -} - -void rtllib_ba_setup_timeout(struct timer_list *t) -{ - struct tx_ts_record *ts = from_timer(ts, t, - tx_pending_ba_record.timer); - - ts->add_ba_req_in_progress = false; - ts->add_ba_req_delayed = true; - ts->tx_pending_ba_record.b_valid = false; -} - -void rtllib_tx_ba_inact_timeout(struct timer_list *t) -{ - struct tx_ts_record *ts = from_timer(ts, t, - tx_admitted_ba_record.timer); - struct rtllib_device *ieee = container_of(ts, struct rtllib_device, - tx_ts_records[ts->num]); - tx_ts_delete_ba(ieee, ts); - rtllib_send_DELBA(ieee, ts->ts_common_info.addr, - &ts->tx_admitted_ba_record, TX_DIR, - DELBA_REASON_TIMEOUT); -} - -void rtllib_rx_ba_inact_timeout(struct timer_list *t) -{ - struct rx_ts_record *ts = from_timer(ts, t, - rx_admitted_ba_record.timer); - struct rtllib_device *ieee = container_of(ts, struct rtllib_device, - rx_ts_records[ts->num]); - - rx_ts_delete_ba(ieee, ts); - rtllib_send_DELBA(ieee, ts->ts_common_info.addr, - &ts->rx_admitted_ba_record, RX_DIR, - DELBA_REASON_TIMEOUT); -} diff --git a/drivers/staging/rtl8192e/rtl819x_HT.h b/drivers/staging/rtl8192e/rtl819x_HT.h deleted file mode 100644 index a6e0077630c7..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_HT.h +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _RTL819XU_HTTYPE_H_ -#define _RTL819XU_HTTYPE_H_ - -#define MIMO_PS_STATIC 0 - -#define sHTCLng 4 - -enum ht_channel_width { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_20_40 = 1, -}; - -enum ht_extchnl_offset { - HT_EXTCHNL_OFFSET_NO_EXT = 0, - HT_EXTCHNL_OFFSET_UPPER = 1, - HT_EXTCHNL_OFFSET_NO_DEF = 2, - HT_EXTCHNL_OFFSET_LOWER = 3, -}; - -struct ht_capab_ele { - u8 adv_coding:1; - u8 chl_width:1; - u8 mimo_pwr_save:2; - u8 green_field:1; - u8 short_gi_20mhz:1; - u8 short_gi_40mhz:1; - u8 tx_stbc:1; - u8 rx_stbc:2; - u8 delay_ba:1; - u8 max_amsdu_size:1; - u8 dss_cck:1; - u8 PSMP:1; - u8 Rsvd1:1; - u8 lsig_txop_protect:1; - - u8 max_rx_ampdu_factor:2; - u8 mpdu_density:3; - u8 Rsvd2:3; - - u8 MCS[16]; - - u16 ext_ht_cap_info; - - u8 TxBFCap[4]; - - u8 ASCap; - -} __packed; - -struct ht_info_ele { - u8 ControlChl; - - u8 ExtChlOffset:2; - u8 RecommemdedTxWidth:1; - u8 RIFS:1; - u8 PSMPAccessOnly:1; - u8 SrvIntGranularity:3; - - u8 opt_mode:2; - u8 NonGFDevPresent:1; - u8 Revd1:5; - u8 Revd2:8; - - u8 Rsvd3:6; - u8 DualBeacon:1; - u8 DualCTSProtect:1; - - u8 SecondaryBeacon:1; - u8 LSigTxopProtectFull:1; - u8 PcoActive:1; - u8 PcoPhase:1; - u8 Rsvd4:4; - - u8 BasicMSC[16]; -} __packed; - -enum ht_spec_ver { - HT_SPEC_VER_IEEE = 0, - HT_SPEC_VER_EWC = 1, -}; - -enum ht_aggre_mode { - HT_AGG_AUTO = 0, - HT_AGG_FORCE_ENABLE = 1, - HT_AGG_FORCE_DISABLE = 2, -}; - -struct rt_hi_throughput { - u8 enable_ht; - u8 current_ht_support; - u8 cur_bw_40mhz; - u8 cur_short_gi_40mhz; - u8 cur_short_gi_20mhz; - enum ht_spec_ver peer_ht_spec_ver; - struct ht_capab_ele self_ht_cap; - u8 peer_ht_cap_buf[32]; - u8 peer_ht_info_buf[32]; - u8 ampdu_enable; - u8 current_ampdu_enable; - u8 ampdu_factor; - u8 current_ampdu_factor; - u8 current_mpdu_density; - u8 forced_ampdu_factor; - u8 forced_mpdu_density; - u8 current_op_mode; - enum ht_extchnl_offset cur_sta_ext_chnl_offset; - u8 cur_tx_bw40mhz; - u8 sw_bw_in_progress; - u8 current_rt2rt_aggregation; - u8 current_rt2rt_long_slot_time; - u8 sz_rt2rt_agg_buf[10]; - u8 cur_rx_reorder_enable; - u8 rx_reorder_win_size; - u8 rx_reorder_pending_time; - u16 rx_reorder_drop_counter; - u8 iot_peer; - u32 iot_action; - u8 iot_ra_func; -} __packed; - -struct bss_ht { - u8 bd_support_ht; - - u8 bd_ht_cap_buf[32]; - u16 bd_ht_cap_len; - u8 bd_ht_info_buf[32]; - u16 bd_ht_info_len; - - enum ht_spec_ver bd_ht_spec_ver; - enum ht_channel_width bd_bandwidth; - - u8 bd_rt2rt_aggregation; - u8 bd_rt2rt_long_slot_time; - u8 rt2rt_ht_mode; - u8 bd_ht_1r; -}; - -extern u8 MCS_FILTER_ALL[16]; -extern u8 MCS_FILTER_1SS[16]; - -#define RATE_ADPT_1SS_MASK 0xFF -#define RATE_ADPT_2SS_MASK 0xF0 -#define RATE_ADPT_MCS32_MASK 0x01 - -enum ht_aggre_size { - HT_AGG_SIZE_8K = 0, - HT_AGG_SIZE_16K = 1, - HT_AGG_SIZE_32K = 2, - HT_AGG_SIZE_64K = 3, -}; - -enum ht_iot_peer { - HT_IOT_PEER_UNKNOWN = 0, - HT_IOT_PEER_REALTEK = 1, - HT_IOT_PEER_REALTEK_92SE = 2, - HT_IOT_PEER_BROADCOM = 3, - HT_IOT_PEER_RALINK = 4, - HT_IOT_PEER_ATHEROS = 5, - HT_IOT_PEER_CISCO = 6, - HT_IOT_PEER_MARVELL = 7, - HT_IOT_PEER_92U_SOFTAP = 8, - HT_IOT_PEER_SELF_SOFTAP = 9, - HT_IOT_PEER_AIRGO = 10, - HT_IOT_PEER_MAX = 11, -}; - -enum ht_iot_action { - HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001, - HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002, - HT_IOT_ACT_DISABLE_MCS14 = 0x00000004, - HT_IOT_ACT_DISABLE_MCS15 = 0x00000008, - HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010, - HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020, - HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040, - HT_IOT_ACT_CDD_FSYNC = 0x00000080, - HT_IOT_ACT_PURE_N_MODE = 0x00000100, - HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, - HT_IOT_ACT_FORCED_RTS = 0x00000400, - HT_IOT_ACT_AMSDU_ENABLE = 0x00000800, - HT_IOT_ACT_REJECT_ADDBA_REQ = 0x00001000, - HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT = 0x00002000, - HT_IOT_ACT_EDCA_BIAS_ON_RX = 0x00004000, - - HT_IOT_ACT_HYBRID_AGGREGATION = 0x00010000, - HT_IOT_ACT_DISABLE_SHORT_GI = 0x00020000, - HT_IOT_ACT_DISABLE_HIGH_POWER = 0x00040000, - HT_IOT_ACT_DISABLE_TX_40_MHZ = 0x00080000, - HT_IOT_ACT_TX_NO_AGGREGATION = 0x00100000, - HT_IOT_ACT_DISABLE_TX_2SS = 0x00200000, - - HT_IOT_ACT_MID_HIGHPOWER = 0x00400000, - HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000, - - HT_IOT_ACT_DISABLE_CCK_RATE = 0x01000000, - HT_IOT_ACT_FORCED_ENABLE_BE_TXOP = 0x02000000, - HT_IOT_ACT_WA_IOT_Broadcom = 0x04000000, - - HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI = 0x08000000, - -}; - -enum ht_iot_rafunc { - HT_IOT_RAFUNC_DISABLE_ALL = 0x00, - HT_IOT_RAFUNC_PEER_1R = 0x01, - HT_IOT_RAFUNC_TX_AMSDU = 0x02, -}; - -enum rt_ht_capability { - RT_HT_CAP_USE_TURBO_AGGR = 0x01, - RT_HT_CAP_USE_LONG_PREAMBLE = 0x02, - RT_HT_CAP_USE_AMPDU = 0x04, - RT_HT_CAP_USE_WOW = 0x8, - RT_HT_CAP_USE_SOFTAP = 0x10, - RT_HT_CAP_USE_92SE = 0x20, -}; - -#endif diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c deleted file mode 100644 index 9c9c0bc0cfde..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ /dev/null @@ -1,699 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtllib.h" -#include "rtl819x_HT.h" -u8 MCS_FILTER_ALL[16] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -u8 MCS_FILTER_1SS[16] = { - 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -; - -u16 MCS_DATA_RATE[2][2][77] = { - {{13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, - 260, 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, - 468, 520, 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, - 182, 208, 156, 195, 195, 234, 273, 273, 312, 130, 156, 181, 156, - 181, 208, 234, 208, 234, 260, 260, 286, 195, 234, 273, 234, 273, - 312, 351, 312, 351, 390, 390, 429}, - {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, - 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, - 578, 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, - 173, 217, 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, - 231, 260, 289, 289, 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, - 433, 433, 477} }, - {{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, - 540, 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, - 864, 972, 1080, 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, - 378, 378, 432, 324, 405, 405, 486, 567, 567, 648, 270, 324, 378, 324, - 378, 432, 486, 432, 486, 540, 540, 594, 405, 486, 567, 486, 567, 648, - 729, 648, 729, 810, 810, 891}, - {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, - 600, 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, - 960, 1080, 1200, 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, - 420, 420, 480, 360, 450, 450, 540, 630, 630, 720, 300, 360, 420, 360, - 420, 480, 540, 480, 540, 600, 600, 660, 450, 540, 630, 540, 630, 720, - 810, 720, 810, 900, 900, 990} } -}; - -static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf}; - -static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70}; - -static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e}; - -static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; - -static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf}; - -static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc}; - -static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e}; - -static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02}; - -static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0}; - -static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91}; - -static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94}; - -static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4}; - -void ht_update_default_setting(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - ht_info->ampdu_enable = 1; - ht_info->ampdu_factor = 2; - - ieee->tx_dis_rate_fallback = 0; - ieee->tx_use_drv_assinged_rate = 0; - - ieee->tx_enable_fw_calc_dur = 1; - - ht_info->rx_reorder_win_size = 64; - ht_info->rx_reorder_pending_time = 30; -} - -static u16 ht_mcs_to_data_rate(struct rtllib_device *ieee, u8 mcs_rate) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - u8 is40MHz = (ht_info->cur_bw_40mhz) ? 1 : 0; - u8 isShortGI = (ht_info->cur_bw_40mhz) ? - ((ht_info->cur_short_gi_40mhz) ? 1 : 0) : - ((ht_info->cur_short_gi_20mhz) ? 1 : 0); - return MCS_DATA_RATE[is40MHz][isShortGI][(mcs_rate & 0x7f)]; -} - -u16 tx_count_to_data_rate(struct rtllib_device *ieee, u8 data_rate) -{ - u16 cck_of_dm_rate[12] = {0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, - 0x24, 0x30, 0x48, 0x60, 0x6c}; - u8 is40MHz = 0; - u8 isShortGI = 0; - - if (data_rate < 12) - return cck_of_dm_rate[data_rate]; - if (data_rate >= 0x10 && data_rate <= 0x1f) { - is40MHz = 0; - isShortGI = 0; - } else if (data_rate >= 0x20 && data_rate <= 0x2f) { - is40MHz = 1; - isShortGI = 0; - } else if (data_rate >= 0x30 && data_rate <= 0x3f) { - is40MHz = 0; - isShortGI = 1; - } else if (data_rate >= 0x40 && data_rate <= 0x4f) { - is40MHz = 1; - isShortGI = 1; - } - return MCS_DATA_RATE[is40MHz][isShortGI][data_rate & 0xf]; -} - -bool is_ht_half_nmode_aps(struct rtllib_device *ieee) -{ - bool retValue = false; - struct rtllib_network *net = &ieee->current_network; - - if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) || - (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) || - (memcmp(net->bssid, PCI_RALINK, 3) == 0) || - (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) || - (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) || - (net->ralink_cap_exist)) - retValue = true; - else if (!memcmp(net->bssid, UNKNOWN_BORADCOM, 3) || - !memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) || - !memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) || - (net->broadcom_cap_exist)) - retValue = true; - else if (net->bssht.bd_rt2rt_aggregation) - retValue = true; - else - retValue = false; - - return retValue; -} - -static void ht_iot_peer_determine(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - struct rtllib_network *net = &ieee->current_network; - - if (net->bssht.bd_rt2rt_aggregation) { - ht_info->iot_peer = HT_IOT_PEER_REALTEK; - if (net->bssht.rt2rt_ht_mode & RT_HT_CAP_USE_92SE) - ht_info->iot_peer = HT_IOT_PEER_REALTEK_92SE; - if (net->bssht.rt2rt_ht_mode & RT_HT_CAP_USE_SOFTAP) - ht_info->iot_peer = HT_IOT_PEER_92U_SOFTAP; - } else if (net->broadcom_cap_exist) { - ht_info->iot_peer = HT_IOT_PEER_BROADCOM; - } else if (!memcmp(net->bssid, UNKNOWN_BORADCOM, 3) || - !memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) || - !memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)) { - ht_info->iot_peer = HT_IOT_PEER_BROADCOM; - } else if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) || - (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) || - (memcmp(net->bssid, PCI_RALINK, 3) == 0) || - (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) || - (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) || - net->ralink_cap_exist) { - ht_info->iot_peer = HT_IOT_PEER_RALINK; - } else if ((net->atheros_cap_exist) || - (memcmp(net->bssid, DLINK_ATHEROS_1, 3) == 0) || - (memcmp(net->bssid, DLINK_ATHEROS_2, 3) == 0)) { - ht_info->iot_peer = HT_IOT_PEER_ATHEROS; - } else if ((memcmp(net->bssid, CISCO_BROADCOM, 3) == 0) || - net->cisco_cap_exist) { - ht_info->iot_peer = HT_IOT_PEER_CISCO; - } else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) || - net->marvell_cap_exist) { - ht_info->iot_peer = HT_IOT_PEER_MARVELL; - } else if (net->airgo_cap_exist) { - ht_info->iot_peer = HT_IOT_PEER_AIRGO; - } else { - ht_info->iot_peer = HT_IOT_PEER_UNKNOWN; - } - - netdev_dbg(ieee->dev, "IOTPEER: %x\n", ht_info->iot_peer); -} - -static u8 ht_iot_act_is_mgnt_use_cck_6m(struct rtllib_device *ieee, - struct rtllib_network *network) -{ - u8 retValue = 0; - - if (ieee->ht_info->iot_peer == HT_IOT_PEER_BROADCOM) - retValue = 1; - - return retValue; -} - -static u8 ht_iot_act_is_ccd_fsync(struct rtllib_device *ieee) -{ - u8 retValue = 0; - - if (ieee->ht_info->iot_peer == HT_IOT_PEER_BROADCOM) - retValue = 1; - return retValue; -} - -static void ht_iot_act_determine_ra_func(struct rtllib_device *ieee, bool bPeerRx2ss) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - ht_info->iot_ra_func &= HT_IOT_RAFUNC_DISABLE_ALL; - - if (ht_info->iot_peer == HT_IOT_PEER_RALINK && !bPeerRx2ss) - ht_info->iot_ra_func |= HT_IOT_RAFUNC_PEER_1R; - - if (ht_info->iot_action & HT_IOT_ACT_AMSDU_ENABLE) - ht_info->iot_ra_func |= HT_IOT_RAFUNC_TX_AMSDU; -} - -void ht_reset_iot_setting(struct rt_hi_throughput *ht_info) -{ - ht_info->iot_action = 0; - ht_info->iot_peer = HT_IOT_PEER_UNKNOWN; - ht_info->iot_ra_func = 0; -} - -void ht_construct_capability_element(struct rtllib_device *ieee, u8 *pos_ht_cap, - u8 *len, u8 is_encrypt, bool assoc) -{ - struct rt_hi_throughput *ht = ieee->ht_info; - struct ht_capab_ele *cap_ele = NULL; - - if (!pos_ht_cap || !ht) { - netdev_warn(ieee->dev, - "%s(): pos_ht_cap and ht_info are null\n", __func__); - return; - } - memset(pos_ht_cap, 0, *len); - - if ((assoc) && (ht->peer_ht_spec_ver == HT_SPEC_VER_EWC)) { - static const u8 EWC11NHTCap[] = { 0x00, 0x90, 0x4c, 0x33 }; - - memcpy(pos_ht_cap, EWC11NHTCap, sizeof(EWC11NHTCap)); - cap_ele = (struct ht_capab_ele *)&pos_ht_cap[4]; - *len = 30 + 2; - } else { - cap_ele = (struct ht_capab_ele *)pos_ht_cap; - *len = 26 + 2; - } - - cap_ele->adv_coding = 0; - if (ieee->get_half_nmode_support_by_aps_handler(ieee->dev)) - cap_ele->chl_width = 0; - else - cap_ele->chl_width = 1; - - cap_ele->mimo_pwr_save = 3; - cap_ele->green_field = 0; - cap_ele->short_gi_20mhz = 1; - cap_ele->short_gi_40mhz = 1; - - cap_ele->tx_stbc = 1; - cap_ele->rx_stbc = 0; - cap_ele->delay_ba = 0; - cap_ele->max_amsdu_size = (MAX_RECEIVE_BUFFER_SIZE >= 7935) ? 1 : 0; - cap_ele->dss_cck = 1; - cap_ele->PSMP = 0; - cap_ele->lsig_txop_protect = 0; - - netdev_dbg(ieee->dev, - "TX HT cap/info ele BW=%d max_amsdu_size:%d dss_cck:%d\n", - cap_ele->chl_width, cap_ele->max_amsdu_size, cap_ele->dss_cck); - - if (is_encrypt) { - cap_ele->mpdu_density = 7; - cap_ele->max_rx_ampdu_factor = 2; - } else { - cap_ele->max_rx_ampdu_factor = 3; - cap_ele->mpdu_density = 0; - } - - memcpy(cap_ele->MCS, ieee->reg_dot11ht_oper_rate_set, 16); - memset(&cap_ele->ext_ht_cap_info, 0, 2); - memset(cap_ele->TxBFCap, 0, 4); - - cap_ele->ASCap = 0; - - if (assoc) { - if (ht->iot_action & HT_IOT_ACT_DISABLE_MCS15) - cap_ele->MCS[1] &= 0x7f; - - if (ht->iot_action & HT_IOT_ACT_DISABLE_MCS14) - cap_ele->MCS[1] &= 0xbf; - - if (ht->iot_action & HT_IOT_ACT_DISABLE_ALL_2SS) - cap_ele->MCS[1] &= 0x00; - - if (ht->iot_action & HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI) - cap_ele->short_gi_40mhz = 0; - - if (ieee->get_half_nmode_support_by_aps_handler(ieee->dev)) { - cap_ele->chl_width = 0; - cap_ele->MCS[1] = 0; - } - } -} - -void ht_construct_rt2rt_agg_element(struct rtllib_device *ieee, u8 *posRT2RTAgg, - u8 *len) -{ - if (!posRT2RTAgg) { - netdev_warn(ieee->dev, "%s(): posRT2RTAgg is null\n", __func__); - return; - } - memset(posRT2RTAgg, 0, *len); - *posRT2RTAgg++ = 0x00; - *posRT2RTAgg++ = 0xe0; - *posRT2RTAgg++ = 0x4c; - *posRT2RTAgg++ = 0x02; - *posRT2RTAgg++ = 0x01; - - *posRT2RTAgg = 0x30; - - if (ieee->bSupportRemoteWakeUp) - *posRT2RTAgg |= RT_HT_CAP_USE_WOW; - - *len = 6 + 2; -} - -static u8 ht_pick_mcs_rate(struct rtllib_device *ieee, u8 *pOperateMCS) -{ - u8 i; - - if (!pOperateMCS) { - netdev_warn(ieee->dev, "%s(): pOperateMCS is null\n", __func__); - return false; - } - - switch (ieee->mode) { - case WIRELESS_MODE_B: - case WIRELESS_MODE_G: - for (i = 0; i <= 15; i++) - pOperateMCS[i] = 0; - break; - case WIRELESS_MODE_N_24G: - pOperateMCS[0] &= RATE_ADPT_1SS_MASK; - pOperateMCS[1] &= RATE_ADPT_2SS_MASK; - pOperateMCS[3] &= RATE_ADPT_MCS32_MASK; - break; - default: - break; - } - - return true; -} - -u8 ht_get_highest_mcs_rate(struct rtllib_device *ieee, u8 *pMCSRateSet, - u8 *pMCSFilter) -{ - u8 i, j; - u8 bitMap; - u8 mcsRate = 0; - u8 availableMcsRate[16]; - - if (!pMCSRateSet || !pMCSFilter) { - netdev_warn(ieee->dev, - "%s(): pMCSRateSet and pMCSFilter are null\n", - __func__); - return false; - } - for (i = 0; i < 16; i++) - availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i]; - - for (i = 0; i < 16; i++) { - if (availableMcsRate[i] != 0) - break; - } - if (i == 16) - return false; - - for (i = 0; i < 16; i++) { - if (availableMcsRate[i] != 0) { - bitMap = availableMcsRate[i]; - for (j = 0; j < 8; j++) { - if ((bitMap % 2) != 0) { - if (ht_mcs_to_data_rate(ieee, (8 * i + j)) > - ht_mcs_to_data_rate(ieee, mcsRate)) - mcsRate = 8 * i + j; - } - bitMap >>= 1; - } - } - } - return mcsRate | 0x80; -} - -static u8 ht_filter_mcs_rate(struct rtllib_device *ieee, u8 *pSupportMCS, - u8 *pOperateMCS) -{ - u8 i; - - for (i = 0; i <= 15; i++) - pOperateMCS[i] = ieee->reg_dot11tx_ht_oper_rate_set[i] & - pSupportMCS[i]; - - ht_pick_mcs_rate(ieee, pOperateMCS); - - if (ieee->get_half_nmode_support_by_aps_handler(ieee->dev)) - pOperateMCS[1] = 0; - - for (i = 2; i <= 15; i++) - pOperateMCS[i] = 0; - - return true; -} - -void ht_set_connect_bw_mode(struct rtllib_device *ieee, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset); - -void ht_on_assoc_rsp(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - struct ht_capab_ele *pPeerHTCap = NULL; - struct ht_info_ele *pPeerHTInfo = NULL; - u8 *pMcsFilter = NULL; - - static const u8 EWC11NHTCap[] = { 0x00, 0x90, 0x4c, 0x33 }; - static const u8 EWC11NHTInfo[] = { 0x00, 0x90, 0x4c, 0x34 }; - - if (!ht_info->current_ht_support) { - netdev_warn(ieee->dev, "%s(): HT_DISABLE\n", __func__); - return; - } - netdev_dbg(ieee->dev, "%s(): HT_ENABLE\n", __func__); - - if (!memcmp(ht_info->peer_ht_cap_buf, EWC11NHTCap, sizeof(EWC11NHTCap))) - pPeerHTCap = (struct ht_capab_ele *)(&ht_info->peer_ht_cap_buf[4]); - else - pPeerHTCap = (struct ht_capab_ele *)(ht_info->peer_ht_cap_buf); - - if (!memcmp(ht_info->peer_ht_info_buf, EWC11NHTInfo, sizeof(EWC11NHTInfo))) - pPeerHTInfo = (struct ht_info_ele *) - (&ht_info->peer_ht_info_buf[4]); - else - pPeerHTInfo = (struct ht_info_ele *)(ht_info->peer_ht_info_buf); - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", __func__, DUMP_PREFIX_NONE, - pPeerHTCap, sizeof(struct ht_capab_ele)); -#endif - ht_set_connect_bw_mode(ieee, (enum ht_channel_width)(pPeerHTCap->chl_width), - (enum ht_extchnl_offset)(pPeerHTInfo->ExtChlOffset)); - ht_info->cur_tx_bw40mhz = ((pPeerHTInfo->RecommemdedTxWidth == 1) ? - true : false); - - ht_info->cur_short_gi_20mhz = ((pPeerHTCap->short_gi_20mhz == 1) ? true : false); - ht_info->cur_short_gi_40mhz = ((pPeerHTCap->short_gi_40mhz == 1) ? true : false); - - ht_info->current_ampdu_enable = ht_info->ampdu_enable; - if (ieee->rtllib_ap_sec_type && - (ieee->rtllib_ap_sec_type(ieee) & (SEC_ALG_WEP | SEC_ALG_TKIP))) { - if ((ht_info->iot_peer == HT_IOT_PEER_ATHEROS) || - (ht_info->iot_peer == HT_IOT_PEER_UNKNOWN)) - ht_info->current_ampdu_enable = false; - } - - if (ieee->current_network.bssht.bd_rt2rt_aggregation) { - if (ieee->pairwise_key_type != KEY_TYPE_NA) - ht_info->current_ampdu_factor = - pPeerHTCap->max_rx_ampdu_factor; - else - ht_info->current_ampdu_factor = HT_AGG_SIZE_64K; - } else { - ht_info->current_ampdu_factor = min_t(u32, pPeerHTCap->max_rx_ampdu_factor, - HT_AGG_SIZE_32K); - } - - ht_info->current_mpdu_density = pPeerHTCap->mpdu_density; - if (ht_info->iot_action & HT_IOT_ACT_TX_USE_AMSDU_8K) - ht_info->current_ampdu_enable = false; - - ht_info->cur_rx_reorder_enable = 1; - - if (pPeerHTCap->MCS[0] == 0) - pPeerHTCap->MCS[0] = 0xff; - - ht_iot_act_determine_ra_func(ieee, ((pPeerHTCap->MCS[1]) != 0)); - - ht_filter_mcs_rate(ieee, pPeerHTCap->MCS, ieee->dot11ht_oper_rate_set); - - pMcsFilter = MCS_FILTER_ALL; - ieee->HTHighestOperaRate = ht_get_highest_mcs_rate(ieee, - ieee->dot11ht_oper_rate_set, - pMcsFilter); - ieee->ht_curr_op_rate = ieee->HTHighestOperaRate; - - ht_info->current_op_mode = pPeerHTInfo->opt_mode; -} - -void ht_initialize_ht_info(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - ht_info->current_ht_support = false; - - ht_info->cur_bw_40mhz = false; - ht_info->cur_tx_bw40mhz = false; - - ht_info->cur_short_gi_20mhz = false; - ht_info->cur_short_gi_40mhz = false; - - ht_info->current_mpdu_density = 0; - ht_info->current_ampdu_factor = ht_info->ampdu_factor; - - memset((void *)(&ht_info->self_ht_cap), 0, - sizeof(ht_info->self_ht_cap)); - memset((void *)(&ht_info->peer_ht_cap_buf), 0, - sizeof(ht_info->peer_ht_cap_buf)); - memset((void *)(&ht_info->peer_ht_info_buf), 0, - sizeof(ht_info->peer_ht_info_buf)); - - ht_info->sw_bw_in_progress = false; - - ht_info->peer_ht_spec_ver = HT_SPEC_VER_IEEE; - - ht_info->current_rt2rt_aggregation = false; - ht_info->current_rt2rt_long_slot_time = false; - - ht_info->iot_peer = 0; - ht_info->iot_action = 0; - ht_info->iot_ra_func = 0; - - { - u8 *RegHTSuppRateSets = &ieee->reg_ht_supp_rate_set[0]; - - RegHTSuppRateSets[0] = 0xFF; - RegHTSuppRateSets[1] = 0xFF; - RegHTSuppRateSets[4] = 0x01; - } -} - -void ht_initialize_bss_desc(struct bss_ht *bss_ht) -{ - bss_ht->bd_support_ht = false; - memset(bss_ht->bd_ht_cap_buf, 0, sizeof(bss_ht->bd_ht_cap_buf)); - bss_ht->bd_ht_cap_len = 0; - memset(bss_ht->bd_ht_info_buf, 0, sizeof(bss_ht->bd_ht_info_buf)); - bss_ht->bd_ht_info_len = 0; - - bss_ht->bd_ht_spec_ver = HT_SPEC_VER_IEEE; - - bss_ht->bd_rt2rt_aggregation = false; - bss_ht->bd_rt2rt_long_slot_time = false; - bss_ht->rt2rt_ht_mode = (enum rt_ht_capability)0; -} - -void ht_reset_self_and_save_peer_setting(struct rtllib_device *ieee, - struct rtllib_network *network) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - u8 bIOTAction = 0; - - /* unmark enable_ht flag here is the same reason why unmarked in - * function rtllib_softmac_new_net. WB 2008.09.10 - */ - if (network->bssht.bd_support_ht) { - ht_info->current_ht_support = true; - ht_info->peer_ht_spec_ver = network->bssht.bd_ht_spec_ver; - - if (network->bssht.bd_ht_cap_len > 0 && - network->bssht.bd_ht_cap_len <= sizeof(ht_info->peer_ht_cap_buf)) - memcpy(ht_info->peer_ht_cap_buf, - network->bssht.bd_ht_cap_buf, - network->bssht.bd_ht_cap_len); - - if (network->bssht.bd_ht_info_len > 0 && - network->bssht.bd_ht_info_len <= - sizeof(ht_info->peer_ht_info_buf)) - memcpy(ht_info->peer_ht_info_buf, - network->bssht.bd_ht_info_buf, - network->bssht.bd_ht_info_len); - - ht_info->current_rt2rt_aggregation = - network->bssht.bd_rt2rt_aggregation; - ht_info->current_rt2rt_long_slot_time = - network->bssht.bd_rt2rt_long_slot_time; - - ht_iot_peer_determine(ieee); - - ht_info->iot_action = 0; - bIOTAction = ht_iot_act_is_mgnt_use_cck_6m(ieee, network); - if (bIOTAction) - ht_info->iot_action |= HT_IOT_ACT_MGNT_USE_CCK_6M; - bIOTAction = ht_iot_act_is_ccd_fsync(ieee); - if (bIOTAction) - ht_info->iot_action |= HT_IOT_ACT_CDD_FSYNC; - } else { - ht_info->current_ht_support = false; - ht_info->current_rt2rt_aggregation = false; - ht_info->current_rt2rt_long_slot_time = false; - - ht_info->iot_action = 0; - ht_info->iot_ra_func = 0; - } -} - -void HT_update_self_and_peer_setting(struct rtllib_device *ieee, - struct rtllib_network *network) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - struct ht_info_ele *pPeerHTInfo = - (struct ht_info_ele *)network->bssht.bd_ht_info_buf; - - if (ht_info->current_ht_support) { - if (network->bssht.bd_ht_info_len != 0) - ht_info->current_op_mode = pPeerHTInfo->opt_mode; - } -} -EXPORT_SYMBOL(HT_update_self_and_peer_setting); - -u8 ht_c_check(struct rtllib_device *ieee, u8 *frame) -{ - if (ieee->ht_info->current_ht_support) { - if ((is_qos_data_frame(frame) && frame_order(frame)) == 1) { - netdev_dbg(ieee->dev, "HT CONTROL FILED EXIST!!\n"); - return true; - } - } - return false; -} - -static void ht_set_connect_bw_mode_callback(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - if (ht_info->cur_bw_40mhz) { - if (ht_info->cur_sta_ext_chnl_offset == HT_EXTCHNL_OFFSET_UPPER) - ieee->set_chan(ieee->dev, - ieee->current_network.channel + 2); - else if (ht_info->cur_sta_ext_chnl_offset == - HT_EXTCHNL_OFFSET_LOWER) - ieee->set_chan(ieee->dev, - ieee->current_network.channel - 2); - else - ieee->set_chan(ieee->dev, - ieee->current_network.channel); - - ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20_40, - ht_info->cur_sta_ext_chnl_offset); - } else { - ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20, - HT_EXTCHNL_OFFSET_NO_EXT); - } - - ht_info->sw_bw_in_progress = false; -} - -void ht_set_connect_bw_mode(struct rtllib_device *ieee, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - if (ieee->get_half_nmode_support_by_aps_handler(ieee->dev)) - bandwidth = HT_CHANNEL_WIDTH_20; - - if (ht_info->sw_bw_in_progress) { - pr_info("%s: sw_bw_in_progress!!\n", __func__); - return; - } - if (bandwidth == HT_CHANNEL_WIDTH_20_40) { - if (ieee->current_network.channel < 2 && - Offset == HT_EXTCHNL_OFFSET_LOWER) - Offset = HT_EXTCHNL_OFFSET_NO_EXT; - if (Offset == HT_EXTCHNL_OFFSET_UPPER || - Offset == HT_EXTCHNL_OFFSET_LOWER) { - ht_info->cur_bw_40mhz = true; - ht_info->cur_sta_ext_chnl_offset = Offset; - } else { - ht_info->cur_bw_40mhz = false; - ht_info->cur_sta_ext_chnl_offset = HT_EXTCHNL_OFFSET_NO_EXT; - } - } else { - ht_info->cur_bw_40mhz = false; - ht_info->cur_sta_ext_chnl_offset = HT_EXTCHNL_OFFSET_NO_EXT; - } - - netdev_dbg(ieee->dev, "%s():ht_info->bCurBW40MHz:%x\n", __func__, - ht_info->cur_bw_40mhz); - - ht_info->sw_bw_in_progress = true; - - ht_set_connect_bw_mode_callback(ieee); -} diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h deleted file mode 100644 index dc991100742f..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_Qos.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef __INC_QOS_TYPE_H -#define __INC_QOS_TYPE_H - -struct qos_tsinfo { - u8 ts_id:4; - u8 ucDirection:2; -}; - -struct octet_string { - u8 *octet; - u16 Length; -}; - -#define AC0_BE 0 -#define AC1_BK 1 -#define AC2_VI 2 -#define AC3_VO 3 - -enum direction_value { - DIR_UP = 0, - DIR_DOWN = 1, - DIR_DIRECT = 2, - DIR_BI_DIR = 3, -}; - -union aci_aifsn { - u8 charData; - - struct { - u8 AIFSN:4; - u8 acm:1; - u8 ACI:2; - u8 Reserved:1; - } f; -}; - -#endif diff --git a/drivers/staging/rtl8192e/rtl819x_TS.h b/drivers/staging/rtl8192e/rtl819x_TS.h deleted file mode 100644 index 5b0e4cb572d2..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_TS.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#ifndef _TSTYPE_H_ -#define _TSTYPE_H_ -#include "rtl819x_Qos.h" -#define TS_ADDBA_DELAY 60 - -#define TOTAL_TS_NUM 16 - -enum tr_select { - TX_DIR = 0, - RX_DIR = 1, -}; - -struct ts_common_info { - struct list_head list; - u8 addr[ETH_ALEN]; - struct qos_tsinfo tspec; -}; - -struct tx_ts_record { - struct ts_common_info ts_common_info; - u16 tx_cur_seq; - struct ba_record tx_pending_ba_record; - struct ba_record tx_admitted_ba_record; - u8 add_ba_req_in_progress; - u8 add_ba_req_delayed; - u8 using_ba; - u8 disable_add_ba; - struct timer_list ts_add_ba_timer; - u8 num; -}; - -struct rx_ts_record { - struct ts_common_info ts_common_info; - u16 rx_indicate_seq; - u16 rx_timeout_indicate_seq; - struct list_head rx_pending_pkt_list; - struct timer_list rx_pkt_pending_timer; - struct ba_record rx_admitted_ba_record; - u16 rx_last_seq_num; - u8 rx_last_frag_num; - u8 num; -}; - -#endif diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c deleted file mode 100644 index 89092cd434de..000000000000 --- a/drivers/staging/rtl8192e/rtl819x_TSProc.c +++ /dev/null @@ -1,450 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. - * - * Contact Information: wlanfae <wlanfae@realtek.com> - */ -#include "rtllib.h" -#include <linux/etherdevice.h> -#include "rtl819x_TS.h" - -static void RxPktPendingTimeout(struct timer_list *t) -{ - struct rx_ts_record *ts = from_timer(ts, t, rx_pkt_pending_timer); - struct rtllib_device *ieee = container_of(ts, struct rtllib_device, - rx_ts_records[ts->num]); - - struct rx_reorder_entry *reorder_entry = NULL; - - unsigned long flags = 0; - u8 index = 0; - bool pkt_in_buf = false; - - spin_lock_irqsave(&(ieee->reorder_spinlock), flags); - if (ts->rx_timeout_indicate_seq != 0xffff) { - while (!list_empty(&ts->rx_pending_pkt_list)) { - reorder_entry = (struct rx_reorder_entry *) - list_entry(ts->rx_pending_pkt_list.prev, - struct rx_reorder_entry, list); - if (index == 0) - ts->rx_indicate_seq = reorder_entry->seq_num; - - if (SN_LESS(reorder_entry->seq_num, - ts->rx_indicate_seq) || - SN_EQUAL(reorder_entry->seq_num, - ts->rx_indicate_seq)) { - list_del_init(&reorder_entry->list); - - if (SN_EQUAL(reorder_entry->seq_num, - ts->rx_indicate_seq)) - ts->rx_indicate_seq = - (ts->rx_indicate_seq + 1) % 4096; - - netdev_dbg(ieee->dev, - "%s(): Indicate seq_num: %d\n", - __func__, reorder_entry->seq_num); - ieee->stats_IndicateArray[index] = - reorder_entry->prxb; - index++; - - list_add_tail(&reorder_entry->list, - &ieee->RxReorder_Unused_List); - } else { - pkt_in_buf = true; - break; - } - } - } - - if (index > 0) { - ts->rx_timeout_indicate_seq = 0xffff; - - if (index > REORDER_WIN_SIZE) { - netdev_warn(ieee->dev, - "%s(): Rx Reorder struct buffer full\n", - __func__); - spin_unlock_irqrestore(&(ieee->reorder_spinlock), - flags); - return; - } - rtllib_indicate_packets(ieee, ieee->stats_IndicateArray, index); - pkt_in_buf = false; - } - - if (pkt_in_buf && (ts->rx_timeout_indicate_seq == 0xffff)) { - ts->rx_timeout_indicate_seq = ts->rx_indicate_seq; - mod_timer(&ts->rx_pkt_pending_timer, jiffies + - msecs_to_jiffies(ieee->ht_info->rx_reorder_pending_time) - ); - } - spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); -} - -static void TsAddBaProcess(struct timer_list *t) -{ - struct tx_ts_record *ts = from_timer(ts, t, ts_add_ba_timer); - u8 num = ts->num; - struct rtllib_device *ieee = container_of(ts, struct rtllib_device, - tx_ts_records[num]); - - rtllib_ts_init_add_ba(ieee, ts, BA_POLICY_IMMEDIATE, false); - netdev_dbg(ieee->dev, "%s(): ADDBA Req is started\n", __func__); -} - -static void ResetTsCommonInfo(struct ts_common_info *ts_common_info) -{ - eth_zero_addr(ts_common_info->addr); - memset(&ts_common_info->tspec, 0, sizeof(struct qos_tsinfo)); -} - -static void ResetTxTsEntry(struct tx_ts_record *ts) -{ - ResetTsCommonInfo(&ts->ts_common_info); - ts->tx_cur_seq = 0; - ts->add_ba_req_in_progress = false; - ts->add_ba_req_delayed = false; - ts->using_ba = false; - ts->disable_add_ba = false; - rtllib_reset_ba_entry(&ts->tx_admitted_ba_record); - rtllib_reset_ba_entry(&ts->tx_pending_ba_record); -} - -static void ResetRxTsEntry(struct rx_ts_record *ts) -{ - ResetTsCommonInfo(&ts->ts_common_info); - ts->rx_indicate_seq = 0xffff; - ts->rx_timeout_indicate_seq = 0xffff; - rtllib_reset_ba_entry(&ts->rx_admitted_ba_record); -} - -void rtllib_ts_init(struct rtllib_device *ieee) -{ - struct tx_ts_record *pTxTS = ieee->tx_ts_records; - struct rx_ts_record *rxts = ieee->rx_ts_records; - struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry; - u8 count = 0; - - INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List); - INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List); - INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List); - - for (count = 0; count < TOTAL_TS_NUM; count++) { - pTxTS->num = count; - timer_setup(&pTxTS->ts_add_ba_timer, TsAddBaProcess, 0); - - timer_setup(&pTxTS->tx_pending_ba_record.timer, rtllib_ba_setup_timeout, - 0); - timer_setup(&pTxTS->tx_admitted_ba_record.timer, - rtllib_tx_ba_inact_timeout, 0); - - ResetTxTsEntry(pTxTS); - list_add_tail(&pTxTS->ts_common_info.list, - &ieee->Tx_TS_Unused_List); - pTxTS++; - } - - INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List); - INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List); - INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List); - for (count = 0; count < TOTAL_TS_NUM; count++) { - rxts->num = count; - INIT_LIST_HEAD(&rxts->rx_pending_pkt_list); - timer_setup(&rxts->rx_admitted_ba_record.timer, - rtllib_rx_ba_inact_timeout, 0); - - timer_setup(&rxts->rx_pkt_pending_timer, RxPktPendingTimeout, 0); - - ResetRxTsEntry(rxts); - list_add_tail(&rxts->ts_common_info.list, - &ieee->Rx_TS_Unused_List); - rxts++; - } - INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); - for (count = 0; count < REORDER_ENTRY_NUM; count++) { - list_add_tail(&pRxReorderEntry->list, - &ieee->RxReorder_Unused_List); - if (count == (REORDER_ENTRY_NUM - 1)) - break; - pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; - } -} - -static struct ts_common_info *SearchAdmitTRStream(struct rtllib_device *ieee, - u8 *addr, u8 TID, - enum tr_select tx_rx_select) -{ - u8 dir; - bool search_dir[4] = {0}; - struct list_head *psearch_list; - struct ts_common_info *pRet = NULL; - - if (tx_rx_select == TX_DIR) { - search_dir[DIR_UP] = true; - search_dir[DIR_BI_DIR] = true; - search_dir[DIR_DIRECT] = true; - } else { - search_dir[DIR_DOWN] = true; - search_dir[DIR_BI_DIR] = true; - search_dir[DIR_DIRECT] = true; - } - - if (tx_rx_select == TX_DIR) - psearch_list = &ieee->Tx_TS_Admit_List; - else - psearch_list = &ieee->Rx_TS_Admit_List; - - for (dir = 0; dir <= DIR_BI_DIR; dir++) { - if (!search_dir[dir]) - continue; - list_for_each_entry(pRet, psearch_list, list) { - if (memcmp(pRet->addr, addr, 6) == 0 && - pRet->tspec.ts_id == TID && - pRet->tspec.ucDirection == dir) - break; - } - if (&pRet->list != psearch_list) - break; - } - - if (pRet && &pRet->list != psearch_list) - return pRet; - return NULL; -} - -static void MakeTSEntry(struct ts_common_info *ts_common_info, u8 *addr, - struct qos_tsinfo *pTSPEC) -{ - if (!ts_common_info) - return; - - memcpy(ts_common_info->addr, addr, 6); - - if (pTSPEC) - memcpy((u8 *)(&(ts_common_info->tspec)), (u8 *)pTSPEC, - sizeof(struct qos_tsinfo)); -} - -bool rtllib_get_ts(struct rtllib_device *ieee, struct ts_common_info **ppTS, - u8 *addr, u8 TID, enum tr_select tx_rx_select, bool add_new_ts) -{ - u8 UP = 0; - struct qos_tsinfo tspec; - struct qos_tsinfo *ts_info = &tspec; - struct list_head *pUnusedList; - struct list_head *pAddmitList; - enum direction_value Dir; - - if (is_multicast_ether_addr(addr)) { - netdev_warn(ieee->dev, "Get TS for Broadcast or Multicast\n"); - return false; - } - if (ieee->current_network.qos_data.supported == 0) { - UP = 0; - } else { - switch (TID) { - case 0: - case 3: - UP = 0; - break; - case 1: - case 2: - UP = 2; - break; - case 4: - case 5: - UP = 5; - break; - case 6: - case 7: - UP = 7; - break; - default: - netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n", - __func__, TID); - return false; - } - } - - *ppTS = SearchAdmitTRStream(ieee, addr, UP, tx_rx_select); - if (*ppTS) - return true; - - if (!add_new_ts) { - netdev_dbg(ieee->dev, "add new TS failed(tid:%d)\n", UP); - return false; - } - - pUnusedList = (tx_rx_select == TX_DIR) ? - (&ieee->Tx_TS_Unused_List) : - (&ieee->Rx_TS_Unused_List); - - pAddmitList = (tx_rx_select == TX_DIR) ? - (&ieee->Tx_TS_Admit_List) : - (&ieee->Rx_TS_Admit_List); - - Dir = ((tx_rx_select == TX_DIR) ? DIR_UP : DIR_DOWN); - - if (!list_empty(pUnusedList)) { - (*ppTS) = list_entry(pUnusedList->next, - struct ts_common_info, list); - list_del_init(&(*ppTS)->list); - if (tx_rx_select == TX_DIR) { - struct tx_ts_record *tmp = - container_of(*ppTS, - struct tx_ts_record, - ts_common_info); - ResetTxTsEntry(tmp); - } else { - struct rx_ts_record *ts = - container_of(*ppTS, - struct rx_ts_record, - ts_common_info); - ResetRxTsEntry(ts); - } - - netdev_dbg(ieee->dev, - "to init current TS, UP:%d, Dir:%d, addr: %pM ppTs=%p\n", - UP, Dir, addr, *ppTS); - ts_info->ts_id = UP; - ts_info->ucDirection = Dir; - - MakeTSEntry(*ppTS, addr, &tspec); - list_add_tail(&((*ppTS)->list), pAddmitList); - - return true; - } - - netdev_warn(ieee->dev, - "There is not enough dir=%d(0=up down=1) TS record to be used!", - Dir); - return false; -} - -static void RemoveTsEntry(struct rtllib_device *ieee, - struct ts_common_info *pTs, enum tr_select tx_rx_select) -{ - rtllib_ts_init_del_ba(ieee, pTs, tx_rx_select); - - if (tx_rx_select == RX_DIR) { - struct rx_reorder_entry *pRxReorderEntry; - struct rx_ts_record *ts = (struct rx_ts_record *)pTs; - - if (timer_pending(&ts->rx_pkt_pending_timer)) - del_timer_sync(&ts->rx_pkt_pending_timer); - - while (!list_empty(&ts->rx_pending_pkt_list)) { - pRxReorderEntry = (struct rx_reorder_entry *) - list_entry(ts->rx_pending_pkt_list.prev, - struct rx_reorder_entry, list); - netdev_dbg(ieee->dev, "%s(): Delete seq_num %d!\n", - __func__, pRxReorderEntry->seq_num); - list_del_init(&pRxReorderEntry->list); - { - int i = 0; - struct rtllib_rxb *prxb = pRxReorderEntry->prxb; - - if (unlikely(!prxb)) - return; - for (i = 0; i < prxb->nr_subframes; i++) - dev_kfree_skb(prxb->subframes[i]); - kfree(prxb); - prxb = NULL; - } - list_add_tail(&pRxReorderEntry->list, - &ieee->RxReorder_Unused_List); - } - } else { - struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs; - - del_timer_sync(&pTxTS->ts_add_ba_timer); - } -} - -void remove_peer_ts(struct rtllib_device *ieee, u8 *addr) -{ - struct ts_common_info *ts, *pTmpTS; - - netdev_info(ieee->dev, "===========>%s, %pM\n", __func__, addr); - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Tx_TS_Pending_List, list) { - if (memcmp(ts->addr, addr, 6) == 0) { - RemoveTsEntry(ieee, ts, TX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Tx_TS_Unused_List); - } - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Tx_TS_Admit_List, list) { - if (memcmp(ts->addr, addr, 6) == 0) { - netdev_info(ieee->dev, - "====>remove Tx_TS_admin_list\n"); - RemoveTsEntry(ieee, ts, TX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Tx_TS_Unused_List); - } - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Rx_TS_Pending_List, list) { - if (memcmp(ts->addr, addr, 6) == 0) { - RemoveTsEntry(ieee, ts, RX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Rx_TS_Unused_List); - } - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Rx_TS_Admit_List, list) { - if (memcmp(ts->addr, addr, 6) == 0) { - RemoveTsEntry(ieee, ts, RX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Rx_TS_Unused_List); - } - } -} -EXPORT_SYMBOL(remove_peer_ts); - -void remove_all_ts(struct rtllib_device *ieee) -{ - struct ts_common_info *ts, *pTmpTS; - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Tx_TS_Pending_List, list) { - RemoveTsEntry(ieee, ts, TX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Tx_TS_Unused_List); - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Tx_TS_Admit_List, list) { - RemoveTsEntry(ieee, ts, TX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Tx_TS_Unused_List); - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Rx_TS_Pending_List, list) { - RemoveTsEntry(ieee, ts, RX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Rx_TS_Unused_List); - } - - list_for_each_entry_safe(ts, pTmpTS, &ieee->Rx_TS_Admit_List, list) { - RemoveTsEntry(ieee, ts, RX_DIR); - list_del_init(&ts->list); - list_add_tail(&ts->list, &ieee->Rx_TS_Unused_List); - } -} - -void rtllib_ts_start_add_ba_process(struct rtllib_device *ieee, struct tx_ts_record *pTxTS) -{ - if (pTxTS->add_ba_req_in_progress == false) { - pTxTS->add_ba_req_in_progress = true; - - if (pTxTS->add_ba_req_delayed) { - netdev_dbg(ieee->dev, "Start ADDBA after 60 sec!!\n"); - mod_timer(&pTxTS->ts_add_ba_timer, jiffies + - msecs_to_jiffies(TS_ADDBA_DELAY)); - } else { - netdev_dbg(ieee->dev, "Immediately Start ADDBA\n"); - mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); - } - } else { - netdev_dbg(ieee->dev, "BA timer is already added\n"); - } -} diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h deleted file mode 100644 index d6615f787d53..000000000000 --- a/drivers/staging/rtl8192e/rtllib.h +++ /dev/null @@ -1,1799 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Merged with mainline rtllib.h in Aug 2004. Original ieee802_11 - * remains copyright by the original authors - * - * Portions of the merged code are based on Host AP (software wireless - * LAN access point) driver for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * <jketreno@linux.intel.com> - * Copyright (c) 2004, Intel Corporation - * - * Modified for Realtek's wi-fi cards by Andrea Merello - * <andrea.merello@gmail.com> - */ -#ifndef RTLLIB_H -#define RTLLIB_H -#include <linux/if_ether.h> /* ETH_ALEN */ -#include <linux/kernel.h> /* ARRAY_SIZE */ -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/jiffies.h> -#include <linux/timer.h> -#include <linux/sched.h> -#include <linux/mutex.h> - -#include <linux/delay.h> -#include <linux/wireless.h> - -#include "rtl819x_HT.h" -#include "rtl819x_BA.h" -#include "rtl819x_TS.h" - -#include <linux/netdevice.h> -#include <linux/if_arp.h> /* ARPHRD_ETHER */ -#include <net/cfg80211.h> -#include <net/lib80211.h> - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY -#endif -#include <net/iw_handler.h> - -#ifndef IW_MODE_MONITOR -#define IW_MODE_MONITOR 6 -#endif - -#ifndef IWEVCUSTOM -#define IWEVCUSTOM 0x8c02 -#endif - -#ifndef IW_CUSTOM_MAX -/* Max number of char in custom event - use multiple of them if needed */ -#define IW_CUSTOM_MAX 256 /* In bytes */ -#endif - -#define container_of_dwork_rsl(x, y, z) \ - container_of(to_delayed_work(x), y, z) - -static inline void *netdev_priv_rsl(struct net_device *dev) -{ - return netdev_priv(dev); -} - -#define KEY_TYPE_NA 0x0 -#define KEY_TYPE_WEP40 0x1 -#define KEY_TYPE_TKIP 0x2 -#define KEY_TYPE_CCMP 0x4 -#define KEY_TYPE_WEP104 0x5 -/* added for rtl819x tx procedure */ -#define MAX_QUEUE_SIZE 0x10 - -#define BK_QUEUE 0 -#define BE_QUEUE 1 -#define VI_QUEUE 2 -#define VO_QUEUE 3 -#define HCCA_QUEUE 4 -#define TXCMD_QUEUE 5 -#define MGNT_QUEUE 6 -#define HIGH_QUEUE 7 -#define BEACON_QUEUE 8 - -#define IE_CISCO_FLAG_POSITION 0x08 -#define SUPPORT_CKIP_MIC 0x08 -#define SUPPORT_CKIP_PK 0x10 -#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) -#define RT_IN_PS_LEVEL(psc, _PS_FLAG) \ - ((psc->cur_ps_level & _PS_FLAG) ? true : false) -#define RT_CLEAR_PS_LEVEL(psc, _PS_FLAG) \ - (psc->cur_ps_level &= (~(_PS_FLAG))) - -/* defined for skb cb field */ -/* At most 28 byte */ -struct cb_desc { - /* Tx Desc Related flags (8-9) */ - u8 last_ini_pkt:1; - u8 cmd_or_init:1; - u8 tx_dis_rate_fallback:1; - u8 tx_use_drv_assinged_rate:1; - u8 hw_sec:1; - - u8 stuck_count; - - /* Tx Firmware Related flags (10-11)*/ - u8 cts_enable:1; - u8 rts_enable:1; - u8 use_short_gi:1; - u8 use_short_preamble:1; - u8 tx_enable_fw_calc_dur:1; - u8 ampdu_enable:1; - u8 rtsstbc:1; - u8 RTSSC:1; - - u8 rts_bw:1; - u8 packet_bw:1; - u8 rts_use_short_preamble:1; - u8 rts_use_short_gi:1; - u8 multicast:1; - u8 broadcast:1; - u8 drv_agg_enable:1; - u8 reserved2:1; - - /* Tx Desc related element(12-19) */ - u8 rata_index; - u8 queue_index; - u16 txbuf_size; - u8 ratr_index; - u8 bAMSDU:1; - u8 bFromAggrQ:1; - u8 reserved6:6; - u8 priority; - - /* Tx firmware related element(20-27) */ - u8 data_rate; - u8 rts_rate; - u8 ampdu_factor; - u8 ampdu_density; - u8 DrvAggrNum; - u8 bdhcp; - u16 pkt_size; - u8 bIsSpecialDataFrame; - - u8 bBTTxPacket; - u8 bIsBTProbRsp; -}; - -enum sw_chnl_cmd_id { - cmd_id_end, - cmd_id_set_tx_power_level, - cmd_id_bbreg_write10, - cmd_id_write_port_ulong, - cmd_id_write_port_ushort, - cmd_id_write_port_uchar, - cmd_id_rf_write_reg, -}; - -struct sw_chnl_cmd { - enum sw_chnl_cmd_id cmd_id; - u32 para1; - u32 para2; - u32 ms_delay; -}; - -/*--------------------------Define -------------------------------------------*/ -#define MGN_1M 0x02 -#define MGN_2M 0x04 -#define MGN_5_5M 0x0b -#define MGN_11M 0x16 - -#define MGN_6M 0x0c -#define MGN_9M 0x12 -#define MGN_12M 0x18 -#define MGN_18M 0x24 -#define MGN_24M 0x30 -#define MGN_36M 0x48 -#define MGN_48M 0x60 -#define MGN_54M 0x6c - -#define MGN_MCS0 0x80 -#define MGN_MCS1 0x81 -#define MGN_MCS2 0x82 -#define MGN_MCS3 0x83 -#define MGN_MCS4 0x84 -#define MGN_MCS5 0x85 -#define MGN_MCS6 0x86 -#define MGN_MCS7 0x87 -#define MGN_MCS8 0x88 -#define MGN_MCS9 0x89 -#define MGN_MCS10 0x8a -#define MGN_MCS11 0x8b -#define MGN_MCS12 0x8c -#define MGN_MCS13 0x8d -#define MGN_MCS14 0x8e -#define MGN_MCS15 0x8f - -enum hw_variables { - HW_VAR_ETHER_ADDR, - HW_VAR_MULTICAST_REG, - HW_VAR_BASIC_RATE, - HW_VAR_BSSID, - HW_VAR_MEDIA_STATUS, - HW_VAR_SECURITY_CONF, - HW_VAR_BEACON_INTERVAL, - HW_VAR_ATIM_WINDOW, - HW_VAR_LISTEN_INTERVAL, - HW_VAR_CS_COUNTER, - HW_VAR_DEFAULTKEY0, - HW_VAR_DEFAULTKEY1, - HW_VAR_DEFAULTKEY2, - HW_VAR_DEFAULTKEY3, - HW_VAR_SIFS, - HW_VAR_DIFS, - HW_VAR_EIFS, - HW_VAR_SLOT_TIME, - HW_VAR_ACK_PREAMBLE, - HW_VAR_CW_CONFIG, - HW_VAR_CW_VALUES, - HW_VAR_RATE_FALLBACK_CONTROL, - HW_VAR_CONTENTION_WINDOW, - HW_VAR_RETRY_COUNT, - HW_VAR_TR_SWITCH, - HW_VAR_COMMAND, - HW_VAR_WPA_CONFIG, - HW_VAR_AMPDU_MIN_SPACE, - HW_VAR_SHORTGI_DENSITY, - HW_VAR_AMPDU_FACTOR, - HW_VAR_MCS_RATE_AVAILABLE, - HW_VAR_AC_PARAM, - HW_VAR_ACM_CTRL, - HW_VAR_DIS_Req_Qsize, - HW_VAR_CCX_CHNL_LOAD, - HW_VAR_CCX_NOISE_HISTOGRAM, - HW_VAR_CCX_CLM_NHM, - HW_VAR_TxOPLimit, - HW_VAR_TURBO_MODE, - HW_VAR_RF_STATE, - HW_VAR_RF_OFF_BY_HW, - HW_VAR_BUS_SPEED, - HW_VAR_SET_DEV_POWER, - - HW_VAR_RCR, - HW_VAR_RATR_0, - HW_VAR_RRSR, - HW_VAR_CPU_RST, - HW_VAR_CECHK_BSSID, - HW_VAR_LBK_MODE, - HW_VAR_AES_11N_FIX, - HW_VAR_USB_RX_AGGR, - HW_VAR_USER_CONTROL_TURBO_MODE, - HW_VAR_RETRY_LIMIT, - HW_VAR_INIT_TX_RATE, - HW_VAR_TX_RATE_REG, - HW_VAR_EFUSE_USAGE, - HW_VAR_EFUSE_BYTES, - HW_VAR_AUTOLOAD_STATUS, - HW_VAR_RF_2R_DISABLE, - HW_VAR_SET_RPWM, - HW_VAR_H2C_FW_PWRMODE, - HW_VAR_H2C_FW_JOINBSSRPT, - HW_VAR_1X1_RECV_COMBINE, - HW_VAR_STOP_SEND_BEACON, - HW_VAR_TSF_TIMER, - HW_VAR_IO_CMD, - - HW_VAR_RF_RECOVERY, - HW_VAR_H2C_FW_UPDATE_GTK, - HW_VAR_WF_MASK, - HW_VAR_WF_CRC, - HW_VAR_WF_IS_MAC_ADDR, - HW_VAR_H2C_FW_OFFLOAD, - HW_VAR_RESET_WFCRC, - - HW_VAR_HANDLE_FW_C2H, - HW_VAR_DL_FW_RSVD_PAGE, - HW_VAR_AID, - HW_VAR_HW_SEQ_ENABLE, - HW_VAR_CORRECT_TSF, - HW_VAR_BCN_VALID, - HW_VAR_FWLPS_RF_ON, - HW_VAR_DUAL_TSF_RST, - HW_VAR_SWITCH_EPHY_WoWLAN, - HW_VAR_INT_MIGRATION, - HW_VAR_INT_AC, - HW_VAR_RF_TIMING, -}; - -enum rt_op_mode { - RT_OP_MODE_AP, - RT_OP_MODE_INFRASTRUCTURE, - RT_OP_MODE_IBSS, - RT_OP_MODE_NO_LINK, -}; - -#define asifs_time \ - ((priv->rtllib->current_network.mode == WIRELESS_MODE_N_24G) ? 16 : 10) - -#define MGMT_QUEUE_NUM 5 - -#define MAX_IE_LEN 0xff - -#define msleep_interruptible_rsl msleep_interruptible - -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - * 6.2.1.1.2. - * - * The figure in section 7.1.2 suggests a body size of up to 2312 - * bytes is allowed, which is a bit confusing, I suspect this - * represents the 2304 bytes of real data, plus a possible 8 bytes of - * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) - */ -#define RTLLIB_1ADDR_LEN 10 -#define RTLLIB_2ADDR_LEN 16 -#define RTLLIB_3ADDR_LEN 24 -#define RTLLIB_4ADDR_LEN 30 -#define RTLLIB_FCS_LEN 4 - -#define RTLLIB_SKBBUFFER_SIZE 2500 - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -#define RTLLIB_FTYPE_MGMT 0x0000 -#define RTLLIB_FTYPE_CTL 0x0004 -#define RTLLIB_FTYPE_DATA 0x0008 - -#define RTLLIB_SCTL_FRAG 0x000F -#define RTLLIB_SCTL_SEQ 0xFFF0 - -/* QOS control */ -#define RTLLIB_QCTL_TID 0x000F - -#define FC_QOS_BIT BIT(7) -#define is_data_frame(pdu) (((pdu[0] & 0x0C) == 0x08) ? true : false) -#define is_legacy_data_frame(pdu) (is_data_frame(pdu) && (!(pdu[0] & FC_QOS_BIT))) -#define is_qos_data_frame(pframe) \ - ((*(u16 *)pframe & (IEEE80211_STYPE_QOS_DATA | RTLLIB_FTYPE_DATA)) == \ - (IEEE80211_STYPE_QOS_DATA | RTLLIB_FTYPE_DATA)) -#define frame_order(pframe) (*(u16 *)pframe & IEEE80211_FCTL_ORDER) -#define SN_LESS(a, b) (((a - b) & 0x800) != 0) -#define SN_EQUAL(a, b) (a == b) -#define MAX_DEV_ADDR_SIZE 8 - -enum act_category { - ACT_CAT_QOS = 1, - ACT_CAT_DLS = 2, - ACT_CAT_BA = 3, - ACT_CAT_HT = 7, - ACT_CAT_WMM = 17, -}; - -enum ba_action { - ACT_ADDBAREQ = 0, - ACT_ADDBARSP = 1, - ACT_DELBA = 2, -}; - -enum init_gain_op_type { - IG_Backup = 0, - IG_Restore, - IG_Max -}; - -enum wireless_mode { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = 0x01, - WIRELESS_MODE_B = 0x02, - WIRELESS_MODE_G = 0x04, - WIRELESS_MODE_AUTO = 0x08, - WIRELESS_MODE_N_24G = 0x10, -}; - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#define ETH_P_IP 0x0800 /* Internet Protocol packet */ -#define ETH_P_ARP 0x0806 /* Address Resolution packet */ -#endif /* ETH_P_PAE */ - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct rtllib_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - -} __packed; - -enum _REG_PREAMBLE_MODE { - PREAMBLE_LONG = 1, - PREAMBLE_AUTO = 2, - PREAMBLE_SHORT = 3, -}; - -#define SNAP_SIZE sizeof(struct rtllib_snap_hdr) - -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) -#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTLLIB_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) (((seq) & RTLLIB_SCTL_SEQ) >> 4) - -#define RTLLIB_STATMASK_SIGNAL (1 << 0) -#define RTLLIB_STATMASK_RSSI (1 << 1) -#define RTLLIB_STATMASK_NOISE (1 << 2) -#define RTLLIB_STATMASK_WEMASK 0x7 - -#define RTLLIB_CCK_MODULATION (1 << 0) -#define RTLLIB_OFDM_MODULATION (1 << 1) - -#define RTLLIB_CCK_RATE_LEN 4 -#define RTLLIB_CCK_RATE_1MB 0x02 -#define RTLLIB_CCK_RATE_2MB 0x04 -#define RTLLIB_CCK_RATE_5MB 0x0B -#define RTLLIB_CCK_RATE_11MB 0x16 -#define RTLLIB_OFDM_RATE_LEN 8 -#define RTLLIB_OFDM_RATE_6MB 0x0C -#define RTLLIB_OFDM_RATE_9MB 0x12 -#define RTLLIB_OFDM_RATE_12MB 0x18 -#define RTLLIB_OFDM_RATE_18MB 0x24 -#define RTLLIB_OFDM_RATE_24MB 0x30 -#define RTLLIB_OFDM_RATE_36MB 0x48 -#define RTLLIB_OFDM_RATE_48MB 0x60 -#define RTLLIB_OFDM_RATE_54MB 0x6C -#define RTLLIB_BASIC_RATE_MASK 0x80 - -/* this is stolen and modified from the madwifi driver*/ -#define RTLLIB_FC0_TYPE_MASK 0x0c -#define RTLLIB_FC0_TYPE_DATA 0x08 -#define RTLLIB_FC0_SUBTYPE_MASK 0xB0 -#define RTLLIB_FC0_SUBTYPE_QOS 0x80 - -#define RTLLIB_QOS_HAS_SEQ(fc) \ - (((fc) & (RTLLIB_FC0_TYPE_MASK | RTLLIB_FC0_SUBTYPE_MASK)) == \ - (RTLLIB_FC0_TYPE_DATA | RTLLIB_FC0_SUBTYPE_QOS)) - -/* this is stolen from ipw2200 driver */ -#define IEEE_IBSS_MAC_HASH_SIZE 31 - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. - */ -struct rtllib_rx_stats { - s8 rssi; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ - u8 control; - u8 mask; - u16 len; - u16 Length; - u8 signal_quality; - s32 RecvSignalPower; - u8 signal_strength; - u16 hw_error:1; - u16 bCRC:1; - u16 bICV:1; - u16 decrypted:1; - u32 time_stamp_low; - u32 time_stamp_high; - - u8 rx_drv_info_size; - u8 rx_buf_shift; - bool bIsAMPDU; - bool bFirstMPDU; - bool contain_htc; - u32 RxPWDBAll; - u8 RxMIMOSignalStrength[2]; - s8 RxMIMOSignalQuality[2]; - bool bPacketMatchBSSID; - bool bIsCCK; - bool packet_to_self; - bool bPacketBeacon; - bool bToSelfBA; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. - */ -#define RTLLIB_FRAG_CACHE_LEN 4 - -struct rtllib_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct rtllib_device; - -#define SEC_ACTIVE_KEY (1 << 4) -#define SEC_AUTH_MODE (1 << 5) -#define SEC_UNICAST_GROUP (1 << 6) -#define SEC_LEVEL (1 << 7) -#define SEC_ENABLED (1 << 8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define SEC_ALG_NONE 0 -#define SEC_ALG_WEP 1 -#define SEC_ALG_TKIP 2 -#define SEC_ALG_CCMP 4 - -#define WEP_KEY_LEN 13 -#define SCM_KEY_LEN 32 - -struct rtllib_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1, - encrypt:1; - u8 key_sizes[NUM_WEP_KEYS]; - u8 keys[NUM_WEP_KEYS][SCM_KEY_LEN]; - u8 level; - u16 flags; -} __packed; - -/* 802.11 data frame from AP - * ,-------------------------------------------------------------------. - * Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - * |------|------|---------|---------|---------|------|---------|------| - * Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - * | | tion | (BSSID) | | | ence | data | | - * `-------------------------------------------------------------------' - * Total: 28-2340 bytes - */ - -/* Management Frame Information Element Types */ -enum rtllib_mfie { - MFIE_TYPE_SSID = 0, - MFIE_TYPE_RATES = 1, - MFIE_TYPE_FH_SET = 2, - MFIE_TYPE_DS_SET = 3, - MFIE_TYPE_CF_SET = 4, - MFIE_TYPE_TIM = 5, - MFIE_TYPE_IBSS_SET = 6, - MFIE_TYPE_COUNTRY = 7, - MFIE_TYPE_HOP_PARAMS = 8, - MFIE_TYPE_HOP_TABLE = 9, - MFIE_TYPE_REQUEST = 10, - MFIE_TYPE_CHALLENGE = 16, - MFIE_TYPE_POWER_CONSTRAINT = 32, - MFIE_TYPE_POWER_CAPABILITY = 33, - MFIE_TYPE_TPC_REQUEST = 34, - MFIE_TYPE_TPC_REPORT = 35, - MFIE_TYPE_SUPP_CHANNELS = 36, - MFIE_TYPE_CSA = 37, - MFIE_TYPE_MEASURE_REQUEST = 38, - MFIE_TYPE_MEASURE_REPORT = 39, - MFIE_TYPE_QUIET = 40, - MFIE_TYPE_IBSS_DFS = 41, - MFIE_TYPE_ERP = 42, - MFIE_TYPE_HT_CAP = 45, - MFIE_TYPE_RSN = 48, - MFIE_TYPE_RATES_EX = 50, - MFIE_TYPE_HT_INFO = 61, - MFIE_TYPE_AIRONET = 133, - MFIE_TYPE_GENERIC = 221, - MFIE_TYPE_QOS_PARAMETER = 222, -}; - -/* Minimal header; can be used for passing 802.11 frames with sufficient - * information to determine what type of underlying data type is actually - * stored in the data. - */ -struct rtllib_info_element { - u8 id; - u8 len; - u8 data[]; -} __packed; - -struct rtllib_authentication { - struct ieee80211_hdr_3addr header; - __le16 algorithm; - __le16 transaction; - __le16 status; - /*challenge*/ - struct rtllib_info_element info_element[]; -} __packed __aligned(2); - -struct rtllib_disauth { - struct ieee80211_hdr_3addr header; - __le16 reason; -} __packed __aligned(2); - -struct rtllib_disassoc { - struct ieee80211_hdr_3addr header; - __le16 reason; -} __packed __aligned(2); - -struct rtllib_probe_request { - struct ieee80211_hdr_3addr header; - /* SSID, supported rates */ - struct rtllib_info_element info_element[]; -} __packed __aligned(2); - -struct rtllib_probe_response { - struct ieee80211_hdr_3addr header; - u32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - /* SSID, supported rates, FH params, DS params, - * CF params, IBSS params, TIM (if beacon), RSN - */ - struct rtllib_info_element info_element[]; -} __packed __aligned(2); - -/* Alias beacon for probe_response */ -#define rtllib_beacon rtllib_probe_response - -struct rtllib_assoc_request_frame { - struct ieee80211_hdr_3addr header; - __le16 capability; - __le16 listen_interval; - /* SSID, supported rates, RSN */ - struct rtllib_info_element info_element[]; -} __packed __aligned(2); - -struct rtllib_assoc_response_frame { - struct ieee80211_hdr_3addr header; - __le16 capability; - __le16 status; - __le16 aid; - struct rtllib_info_element info_element[]; /* supported rates */ -} __packed __aligned(2); - -struct rtllib_txb { - u8 nr_frags; - u8 encrypted; - u8 queue_index; - u8 rts_included; - u16 reserved; - __le16 frag_size; - __le16 payload_size; - struct sk_buff *fragments[] __counted_by(nr_frags); -}; - -#define MAX_SUBFRAME_COUNT 64 -struct rtllib_rxb { - u8 nr_subframes; - struct sk_buff *subframes[MAX_SUBFRAME_COUNT]; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; -}; - -union frameqos { - u16 shortdata; - u8 chardata[2]; - struct { - u16 tid:4; - u16 eosp:1; - u16 ack_policy:2; - u16 reserved:1; - u16 txop:8; - } field; -}; - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... - */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) -#define MAX_NETWORK_COUNT 96 - -#define MAX_CHANNEL_NUMBER 161 -#define RTLLIB_SOFTMAC_SCAN_TIME 100 -#define RTLLIB_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) - -#define MAX_WPA_IE_LEN 64 -#define MAX_WZC_IE_LEN 256 - -#define NETWORK_EMPTY_ESSID (1 << 0) -#define NETWORK_HAS_OFDM (1 << 1) -#define NETWORK_HAS_CCK (1 << 2) - -/* QoS structure */ -#define NETWORK_HAS_QOS_PARAMETERS (1 << 3) -#define NETWORK_HAS_QOS_INFORMATION (1 << 4) -#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ - NETWORK_HAS_QOS_INFORMATION) -/* 802.11h */ -#define NETWORK_HAS_ERP_VALUE (1 << 10) - -#define QOS_QUEUE_NUM 4 -#define QOS_OUI_LEN 3 -#define QOS_OUI_TYPE 2 -#define QOS_ELEMENT_ID 221 -#define QOS_OUI_INFO_SUB_TYPE 0 -#define QOS_OUI_PARAM_SUB_TYPE 1 -#define QOS_VERSION_1 1 - -struct rtllib_qos_information_element { - u8 element_id; - u8 length; - u8 qui[QOS_OUI_LEN]; - u8 qui_type; - u8 qui_subtype; - u8 version; - u8 ac_info; -} __packed; - -struct rtllib_qos_ac_parameter { - u8 aci_aifsn; - u8 ecw_min_max; - __le16 tx_op_limit; -} __packed; - -struct rtllib_qos_parameter_info { - struct rtllib_qos_information_element info_element; - u8 reserved; - struct rtllib_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; -} __packed; - -struct rtllib_qos_parameters { - __le16 cw_min[QOS_QUEUE_NUM]; - __le16 cw_max[QOS_QUEUE_NUM]; - u8 aifs[QOS_QUEUE_NUM]; - u8 flag[QOS_QUEUE_NUM]; - __le16 tx_op_limit[QOS_QUEUE_NUM]; -} __packed; - -struct rtllib_qos_data { - struct rtllib_qos_parameters parameters; - unsigned int wmm_acm; - int active; - int supported; - u8 param_count; - u8 old_param_count; -}; - -struct rtllib_tim_parameters { - u8 tim_count; - u8 tim_period; -} __packed; - -struct rtllib_wmm_ac_param { - u8 ac_aci_acm_aifsn; - u8 ac_ecwmin_ecwmax; - u16 ac_txop_limit; -}; - -enum eap_type { - EAP_PACKET = 0, - EAPOL_START, - EAPOL_LOGOFF, - EAPOL_KEY, - EAPOL_ENCAP_ASF_ALERT -}; - -static const char * const eap_types[] = { - [EAP_PACKET] = "EAP-Packet", - [EAPOL_START] = "EAPOL-Start", - [EAPOL_LOGOFF] = "EAPOL-Logoff", - [EAPOL_KEY] = "EAPOL-Key", - [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" -}; - -static inline const char *eap_get_type(int type) -{ - return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : - eap_types[type]; -} - -static inline u8 frame_qos_tid(u8 *buf) -{ - struct ieee80211_hdr_3addr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr_3addr *)buf; - fc = le16_to_cpu(hdr->frame_control); - return (u8)((union frameqos *)(buf + (((fc & IEEE80211_FCTL_TODS) && - (fc & IEEE80211_FCTL_FROMDS)) ? 30 : 24)))->field.tid; -} - -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __packed; - -struct rtllib_softmac_stats { - unsigned int rx_ass_ok; - unsigned int rx_ass_err; - unsigned int rx_probe_rq; - unsigned int tx_probe_rs; - unsigned int tx_beacons; - unsigned int rx_auth_rq; - unsigned int rx_auth_rs_ok; - unsigned int rx_auth_rs_err; - unsigned int tx_auth_rq; - unsigned int no_auth_rs; - unsigned int no_ass_rs; - unsigned int tx_ass_rq; - unsigned int rx_ass_rq; - unsigned int tx_probe_rq; - unsigned int reassoc; - unsigned int swtxstop; - unsigned int swtxawake; - unsigned char CurrentShowTxate; - unsigned char last_packet_rate; - unsigned int txretrycount; -}; - -/* These are the data types that can make up management packets - * - * u16 auth_algorithm; - * u16 auth_sequence; - * u16 beacon_interval; - * u16 capability; - * u8 current_ap[ETH_ALEN]; - * u16 listen_interval; - * struct { - * u16 association_id:14, reserved:2; - * } __packed; - * u32 time_stamp[2]; - * u16 reason; - * u16 status; - */ - -#define RTLLIB_DEFAULT_TX_ESSID "Penguin" -#define RTLLIB_DEFAULT_BASIC_RATE 2 - -enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; -#define MAX_SP_Len (WMM_all_frame << 4) -#define RTLLIB_QOS_TID 0x0f -#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) - -#define RTLLIB_DTIM_MBCAST 4 -#define RTLLIB_DTIM_UCAST 2 -#define RTLLIB_DTIM_VALID 1 -#define RTLLIB_DTIM_INVALID 0 - -#define RTLLIB_PS_DISABLED 0 -#define RTLLIB_PS_UNICAST RTLLIB_DTIM_UCAST -#define RTLLIB_PS_MBCAST RTLLIB_DTIM_MBCAST - -#define WME_AC_BK 0x00 -#define WME_AC_BE 0x01 -#define WME_AC_VI 0x02 -#define WME_AC_VO 0x03 -#define WME_AC_PRAM_LEN 16 - -#define MAX_RECEIVE_BUFFER_SIZE 9100 - -#define UP2AC(up) ( \ - ((up) < 1) ? WME_AC_BE : \ - ((up) < 3) ? WME_AC_BK : \ - ((up) < 4) ? WME_AC_BE : \ - ((up) < 6) ? WME_AC_VI : \ - WME_AC_VO) - -#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address - * plus ether type - */ - -enum erp_t { - ERP_NonERPpresent = 0x01, - ERP_UseProtection = 0x02, - ERP_BarkerPreambleMode = 0x04, -}; - -struct rtllib_network { - /* These entries are used to identify a unique network */ - u8 bssid[ETH_ALEN]; - u8 channel; - /* Ensure null-terminated for any debug msgs */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - u8 hidden_ssid[IW_ESSID_MAX_SIZE + 1]; - u8 hidden_ssid_len; - struct rtllib_qos_data qos_data; - - bool with_aironet_ie; - bool ckip_supported; - bool ccx_rm_enable; - u8 ccx_rm_state[2]; - bool mb_ssid_valid; - u8 mb_ssid_mask; - u8 mb_ssid[ETH_ALEN]; - bool with_ccx_ver_num; - u8 bss_ccx_ver_number; - /* These are network statistics */ - struct rtllib_rx_stats stats; - u16 capability; - u8 rates[MAX_RATES_LENGTH]; - u8 rates_len; - u8 rates_ex[MAX_RATES_EX_LENGTH]; - u8 rates_ex_len; - unsigned long last_scanned; - u8 mode; - u32 flags; - u32 time_stamp[2]; - u16 beacon_interval; - u16 listen_interval; - u16 atim_window; - u8 erp_value; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - u8 wzc_ie[MAX_WZC_IE_LEN]; - size_t wzc_ie_len; - - struct rtllib_tim_parameters tim; - u8 dtim_period; - u8 dtim_data; - u64 last_dtim_sta_time; - - u8 wmm_info; - struct rtllib_wmm_ac_param wmm_param[4]; - u8 turbo_enable; - u16 country_ie_len; - u8 country_ie_buf[MAX_IE_LEN]; - struct bss_ht bssht; - bool broadcom_cap_exist; - bool realtek_cap_exit; - bool marvell_cap_exist; - bool ralink_cap_exist; - bool atheros_cap_exist; - bool cisco_cap_exist; - bool airgo_cap_exist; - bool unknown_cap_exist; - bool berp_info_valid; - bool buseprotection; - u8 signal_strength; - u8 RSSI; - struct list_head list; -}; - -enum rtl_link_state { - /* the card is not linked at all */ - MAC80211_NOLINK = 0, - - /* RTLLIB_ASSOCIATING* are for BSS client mode - * the driver shall not perform RX filtering unless - * the state is LINKED. - * The driver shall just check for the state LINKED and - * defaults to NOLINK for ALL the other states (including - * LINKED_SCANNING) - */ - - /* the association procedure will start (wq scheduling)*/ - RTLLIB_ASSOCIATING, - RTLLIB_ASSOCIATING_RETRY, - - /* the association procedure is sending AUTH request*/ - RTLLIB_ASSOCIATING_AUTHENTICATING, - - /* the association procedure has successfully authenticated - * and is sending association request - */ - RTLLIB_ASSOCIATING_AUTHENTICATED, - - /* the link is ok. the card associated to a BSS or linked - * to a ibss cell or acting as an AP and creating the bss - */ - MAC80211_LINKED, - - /* same as LINKED, but the driver shall apply RX filter - * rules as we are in NO_LINK mode. As the card is still - * logically linked, but it is doing a syncro site survey - * then it will be back to LINKED state. - */ - MAC80211_LINKED_SCANNING, -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -#define CFG_RTLLIB_RESERVE_FCS (1 << 0) -#define CFG_RTLLIB_COMPUTE_FCS (1 << 1) - -struct tx_pending { - int frag; - struct rtllib_txb *txb; -}; - -struct bandwidth_autoswitch { - long threshold_20Mhzto40Mhz; - long threshold_40Mhzto20Mhz; - bool forced_tx_20MHz; - bool bautoswitch_enable; -}; - -#define REORDER_WIN_SIZE 128 -#define REORDER_ENTRY_NUM 128 -struct rx_reorder_entry { - struct list_head list; - u16 seq_num; - struct rtllib_rxb *prxb; -}; - -enum fsync_state { - DEFAULT_FSYNC, - HW_FSYNC, - SW_FSYNC -}; - -enum ips_callback_function { - IPS_CALLBACK_NONE = 0, - IPS_CALLBACK_MGNT_LINK_REQUEST = 1, - IPS_CALLBACK_JOIN_REQUEST = 2, -}; - -enum rt_rf_power_state { - rf_on, - rf_sleep, - rf_off -}; - -struct rt_pwr_save_ctrl { - bool bSwRfProcessing; - enum rt_rf_power_state eInactivePowerState; - enum ips_callback_function return_point; - - bool bLeisurePs; - u8 lps_idle_count; - u8 lps_awake_intvl; - - u32 cur_ps_level; -}; - -#define RT_RF_CHANGE_SOURCE u32 - -#define RF_CHANGE_BY_SW BIT(31) -#define RF_CHANGE_BY_HW BIT(30) -#define RF_CHANGE_BY_PS BIT(29) -#define RF_CHANGE_BY_IPS BIT(28) -#define RF_CHANGE_BY_INIT 0 - -enum country_code_type { - COUNTRY_CODE_FCC = 0, - COUNTRY_CODE_IC = 1, - COUNTRY_CODE_ETSI = 2, - COUNTRY_CODE_SPAIN = 3, - COUNTRY_CODE_FRANCE = 4, - COUNTRY_CODE_MKK = 5, - COUNTRY_CODE_MKK1 = 6, - COUNTRY_CODE_ISRAEL = 7, - COUNTRY_CODE_TELEC = 8, - COUNTRY_CODE_MIC = 9, - COUNTRY_CODE_GLOBAL_DOMAIN = 10, - COUNTRY_CODE_WORLD_WIDE_13 = 11, - COUNTRY_CODE_TELEC_NETGEAR = 12, - COUNTRY_CODE_MAX -}; - -enum scan_op_backup_opt { - SCAN_OPT_BACKUP = 0, - SCAN_OPT_RESTORE, - SCAN_OPT_MAX -}; - -#define RT_MAX_LD_SLOT_NUM 10 -struct rt_link_detect { - u32 num_recv_bcn_in_period; - u32 num_recv_data_in_period; - - u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; - u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; - u16 slot_num; - u16 slot_index; - - u32 num_tx_ok_in_period; - u32 num_rx_ok_in_period; - u32 num_rx_unicast_ok_in_period; - bool busy_traffic; - bool bHigherBusyTraffic; - bool bHigherBusyRxTraffic; -}; - -struct sw_cam_table { - u8 macaddr[ETH_ALEN]; - bool bused; - u8 key_buf[16]; - u16 key_type; - u8 useDK; - u8 key_index; - -}; - -#define TOTAL_CAM_ENTRY 32 -struct rate_adaptive { - u8 ratr_state; - u16 reserve; - - u32 high_rssi_thresh_for_ra; - u32 high2low_rssi_thresh_for_ra; - u8 low2high_rssi_thresh_for_ra40M; - u32 low_rssi_thresh_for_ra40M; - u8 low2high_rssi_thresh_for_ra20M; - u32 low_rssi_thresh_for_ra20M; - u32 upper_rssi_threshold_ratr; - u32 middle_rssi_threshold_ratr; - u32 low_rssi_threshold_ratr; - u32 low_rssi_threshold_ratr_40M; - u32 low_rssi_threshold_ratr_20M; - u8 ping_rssi_enable; - u32 ping_rssi_ratr; - u32 ping_rssi_thresh_for_ra; - u8 PreRATRState; - -}; - -#define NUM_PMKID_CACHE 16 -struct rt_pmkid_list { - u8 bssid[ETH_ALEN]; - u8 PMKID[16]; - u8 SsidBuf[33]; - u8 used; -}; - -/*************** DRIVER STATUS *****/ -#define STATUS_SCANNING 0 -/*************** DRIVER STATUS *****/ - -enum { - LPS_IS_WAKE = 0, - LPS_IS_SLEEP = 1, - LPS_WAIT_NULL_DATA_SEND = 2, -}; - -struct rtllib_device { - struct pci_dev *pdev; - struct net_device *dev; - struct rtllib_security sec; - - bool disable_mgnt_queue; - - unsigned long status; - u8 cnt_after_link; - - enum rt_op_mode op_mode; - - /* The last AssocReq/Resp IEs */ - u8 *assocreq_ies, *assocresp_ies; - size_t assocreq_ies_len, assocresp_ies_len; - - bool forced_bg_mode; - - u8 hwsec_active; - bool is_roaming; - bool ieee_up; - bool cannot_notify; - bool bSupportRemoteWakeUp; - bool actscanning; - bool first_ie_in_scan; - bool be_scan_inprogress; - bool beinretry; - enum rt_rf_power_state rf_power_state; - RT_RF_CHANGE_SOURCE rf_off_reason; - bool is_set_key; - bool wx_set_enc; - struct rt_hi_throughput *ht_info; - - spinlock_t reorder_spinlock; - u8 reg_dot11ht_oper_rate_set[16]; - u8 reg_dot11tx_ht_oper_rate_set[16]; - u8 dot11ht_oper_rate_set[16]; - u8 reg_ht_supp_rate_set[16]; - u8 ht_curr_op_rate; - u8 HTHighestOperaRate; - u8 tx_dis_rate_fallback; - u8 tx_use_drv_assinged_rate; - u8 tx_enable_fw_calc_dur; - atomic_t atm_swbw; - - struct list_head Tx_TS_Admit_List; - struct list_head Tx_TS_Pending_List; - struct list_head Tx_TS_Unused_List; - struct tx_ts_record tx_ts_records[TOTAL_TS_NUM]; - struct list_head Rx_TS_Admit_List; - struct list_head Rx_TS_Pending_List; - struct list_head Rx_TS_Unused_List; - struct rx_ts_record rx_ts_records[TOTAL_TS_NUM]; - struct rx_reorder_entry RxReorderEntry[128]; - struct list_head RxReorder_Unused_List; - - /* Bookkeeping structures */ - struct net_device_stats stats; - struct rtllib_softmac_stats softmac_stats; - - /* Probe / Beacon management */ - struct list_head network_free_list; - struct list_head network_list; - struct rtllib_network *networks; - int scans; - int scan_age; - - int iw_mode; /* operating mode (IW_MODE_*) */ - - spinlock_t lock; - spinlock_t wpax_suitlist_lock; - - int tx_headroom; /* Set to size of any additional room needed at front - * of allocated Tx SKBs - */ - u32 config; - - /* WEP and other encryption related settings at the device level */ - int open_wep; /* Set to 1 to allow unencrypted frames */ - int auth_mode; - int reset_on_keychange; /* Set to 1 if the HW needs to be reset on - * WEP key changes - */ - - int ieee802_1x; /* is IEEE 802.1X used */ - - /* WPA data */ - bool half_wireless_n24g_mode; - int wpa_enabled; - int drop_unencrypted; - int tkip_countermeasures; - int privacy_invoked; - size_t wpa_ie_len; - u8 *wpa_ie; - size_t wps_ie_len; - u8 *wps_ie; - u8 ap_mac_addr[ETH_ALEN]; - u16 pairwise_key_type; - u16 group_key_type; - - struct lib80211_crypt_info crypt_info; - - struct sw_cam_table swcamtable[TOTAL_CAM_ENTRY]; - - struct rt_pmkid_list pmkid_list[NUM_PMKID_CACHE]; - - /* Fragmentation structures */ - struct rtllib_frag_entry frag_cache[17][RTLLIB_FRAG_CACHE_LEN]; - unsigned int frag_next_idx[17]; - u16 fts; /* Fragmentation Threshold */ -#define DEFAULT_RTS_THRESHOLD 2346U -#define MIN_RTS_THRESHOLD 1 -#define MAX_RTS_THRESHOLD 2346U - u16 rts; /* RTS threshold */ - - /* Association info */ - u8 bssid[ETH_ALEN]; - - /* This stores infos for the current network. - * Either the network we are associated in INFRASTRUCTURE - * or the network that we are creating in MASTER mode. - * ad-hoc is a mixture ;-). - * Note that in infrastructure mode, even when not associated, - * fields bssid and essid may be valid (if wpa_set and essid_set - * are true) as thy carry the value set by the user via iwconfig - */ - struct rtllib_network current_network; - - enum rtl_link_state link_state; - - int mode; /* A, B, G */ - - /* used for forcing the ibss workqueue to terminate - * without wait for the syncro scan to terminate - */ - short sync_scan_hurryup; - u16 scan_watch_dog; - - /* map of allowed channels. 0 is dummy */ - u8 active_channel_map[MAX_CHANNEL_NUMBER + 1]; - - int rate; /* current rate */ - int basic_rate; - - /* this contains flags for selectively enable softmac support */ - u16 softmac_features; - - /* if the sequence control field is not filled by HW */ - u16 seq_ctrl[5]; - - /* association procedure transaction sequence number */ - u16 associate_seq; - - /* AID for RTXed association responses */ - u16 assoc_id; - - /* power save mode related*/ - u8 ack_tx_to_ieee; - short ps; - short sta_sleep; - int ps_timeout; - int ps_period; - struct work_struct ps_task; - u64 ps_time; - bool polling; - - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - short queue_stop; - short scanning_continue; - short proto_started; - short proto_stoppping; - - struct mutex wx_mutex; - struct mutex scan_mutex; - struct mutex ips_mutex; - - spinlock_t mgmt_tx_lock; - spinlock_t beacon_lock; - - short beacon_txing; - - short wap_set; - short ssid_set; - - /* set on initialization */ - unsigned int wmm_acm; - - /* for discarding duplicated packets in IBSS */ - struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; - - /* for discarding duplicated packets in BSS */ - u16 last_rxseq_num[17]; /* rx seq previous per-tid */ - u16 last_rxfrag_num[17];/* tx frag previous per-tid */ - unsigned long last_packet_time[17]; - - /* for PS mode */ - unsigned long last_rx_ps_time; - bool awake_pkt_sent; - u8 lps_delay_cnt; - - /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ - struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; - int mgmt_queue_head; - int mgmt_queue_tail; - u8 asoc_retry_count; - struct sk_buff_head skb_waitq[MAX_QUEUE_SIZE]; - - bool bdynamic_txpower_enable; - - bool bCTSToSelfEnable; - - u32 fsync_time_interval; - u32 fsync_rate_bitmap; - u8 fsync_rssi_threshold; - bool bfsync_enable; - - u8 fsync_multiple_timeinterval; - u32 fsync_firstdiff_ratethreshold; - u32 fsync_seconddiff_ratethreshold; - enum fsync_state fsync_state; - bool bis_any_nonbepkts; - struct bandwidth_autoswitch bandwidth_auto_switch; - bool FwRWRF; - - struct rt_link_detect link_detect_info; - bool is_aggregate_frame; - struct rt_pwr_save_ctrl pwr_save_ctrl; - - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - struct tx_pending tx_pending; - - /* used if IEEE_SOFTMAC_ASSOCIATE is set */ - struct timer_list associate_timer; - - /* used if IEEE_SOFTMAC_BEACONS is set */ - u8 need_sw_enc; - struct work_struct associate_complete_wq; - struct work_struct ips_leave_wq; - struct delayed_work associate_procedure_wq; - struct delayed_work softmac_scan_wq; - struct delayed_work associate_retry_wq; - struct delayed_work hw_wakeup_wq; - struct delayed_work hw_sleep_wq; - struct delayed_work link_change_wq; - struct work_struct wx_sync_scan_wq; - - union { - struct rtllib_rxb *rfd_array[REORDER_WIN_SIZE]; - struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; - struct rtllib_rxb *prxb_indicate_array[REORDER_WIN_SIZE]; - struct { - struct sw_chnl_cmd PreCommonCmd[MAX_PRECMD_CNT]; - struct sw_chnl_cmd PostCommonCmd[MAX_POSTCMD_CNT]; - struct sw_chnl_cmd RfDependCmd[MAX_RFDEPENDCMD_CNT]; - }; - }; - - /* Callback functions */ - - /* Softmac-generated frames (management) are TXed via this - * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is - * not set. As some cards may have different HW queues that - * one might want to use for data and management frames - * the option to have two callbacks might be useful. - * This function can't sleep. - */ - int (*softmac_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev); - - /* used instead of hard_start_xmit (not softmac_hard_start_xmit) - * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data - * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set - * then also management frames are sent via this callback. - * This function can't sleep. - */ - void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev, int rate); - - /* ask to the driver to retune the radio. - * This function can sleep. the driver should ensure - * the radio has been switched before return. - */ - void (*set_chan)(struct net_device *dev, u8 ch); - - /* indicate the driver that the link state is changed - * for example it may indicate the card is associated now. - * Driver might be interested in this to apply RX filter - * rules or simply light the LINK led - */ - void (*link_change)(struct net_device *dev); - - /* power save mode related */ - void (*sta_wake_up)(struct net_device *dev); - void (*enter_sleep_state)(struct net_device *dev, u64 time); - short (*ps_is_queue_empty)(struct net_device *dev); - int (*handle_beacon)(struct net_device *dev, - struct rtllib_beacon *beacon, - struct rtllib_network *network); - int (*handle_assoc_response)(struct net_device *dev, - struct rtllib_assoc_response_frame *resp, - struct rtllib_network *network); - - /* check whether Tx hw resource available */ - short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); - void (*set_bw_mode_handler)(struct net_device *dev, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset); - bool (*get_nmode_support_by_sec_cfg)(struct net_device *dev); - void (*set_wireless_mode)(struct net_device *dev, u8 wireless_mode); - bool (*get_half_nmode_support_by_aps_handler)(struct net_device *dev); - u8 (*rtllib_ap_sec_type)(struct rtllib_device *ieee); - void (*init_gain_handler)(struct net_device *dev, u8 operation); - void (*scan_operation_backup_handler)(struct net_device *dev, - u8 operation); - void (*set_hw_reg_handler)(struct net_device *dev, u8 variable, u8 *val); - - void (*allow_all_dest_addr_handler)(struct net_device *dev, - bool allow_all_da, - bool write_into_reg); - - void (*rtllib_ips_leave_wq)(struct net_device *dev); - void (*rtllib_ips_leave)(struct net_device *dev); - void (*leisure_ps_leave)(struct net_device *dev); - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_rtllib - */ - u8 priv[]; -}; - -#define IEEE_MODE_MASK (WIRELESS_MODE_B | WIRELESS_MODE_G) - -/* Generate a 802.11 header */ - -/* Uses the channel change callback directly - * instead of [start/stop] scan callbacks - */ -#define IEEE_SOFTMAC_SCAN (1 << 2) - -/* Perform authentication and association handshake */ -#define IEEE_SOFTMAC_ASSOCIATE (1 << 3) - -/* Generate probe requests */ -#define IEEE_SOFTMAC_PROBERQ (1 << 4) - -/* Generate response to probe requests */ -#define IEEE_SOFTMAC_PROBERS (1 << 5) - -/* The ieee802.11 stack will manage the netif queue - * wake/stop for the driver, taking care of 802.11 - * fragmentation. See softmac.c for details. - */ -#define IEEE_SOFTMAC_TX_QUEUE (1 << 7) - -/* Uses only the softmac_data_hard_start_xmit - * even for TX management frames. - */ -#define IEEE_SOFTMAC_SINGLE_QUEUE (1 << 8) - -/* Generate beacons. The stack will enqueue beacons - * to the card - */ -#define IEEE_SOFTMAC_BEACONS (1 << 6) - -static inline void *rtllib_priv(struct net_device *dev) -{ - return ((struct rtllib_device *)netdev_priv(dev))->priv; -} - -static inline int rtllib_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -static inline int rtllib_get_hdrlen(u16 fc) -{ - int hdrlen = RTLLIB_3ADDR_LEN; - - switch (WLAN_FC_GET_TYPE(fc)) { - case RTLLIB_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = RTLLIB_4ADDR_LEN; /* Addr4 */ - if (RTLLIB_QOS_HAS_SEQ(fc)) - hdrlen += 2; /* QOS ctrl*/ - break; - case RTLLIB_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = RTLLIB_1ADDR_LEN; - break; - default: - hdrlen = RTLLIB_2ADDR_LEN; - break; - } - break; - } - - return hdrlen; -} - -static inline int rtllib_is_ofdm_rate(u8 rate) -{ - switch (rate & ~RTLLIB_BASIC_RATE_MASK) { - case RTLLIB_OFDM_RATE_6MB: - case RTLLIB_OFDM_RATE_9MB: - case RTLLIB_OFDM_RATE_12MB: - case RTLLIB_OFDM_RATE_18MB: - case RTLLIB_OFDM_RATE_24MB: - case RTLLIB_OFDM_RATE_36MB: - case RTLLIB_OFDM_RATE_48MB: - case RTLLIB_OFDM_RATE_54MB: - return 1; - } - return 0; -} - -static inline int rtllib_is_cck_rate(u8 rate) -{ - switch (rate & ~RTLLIB_BASIC_RATE_MASK) { - case RTLLIB_CCK_RATE_1MB: - case RTLLIB_CCK_RATE_2MB: - case RTLLIB_CCK_RATE_5MB: - case RTLLIB_CCK_RATE_11MB: - return 1; - } - return 0; -} - -/* rtllib.c */ -void free_rtllib(struct net_device *dev); -struct net_device *alloc_rtllib(int sizeof_priv); - -/* rtllib_tx.c */ - -int rtllib_encrypt_fragment(struct rtllib_device *ieee, - struct sk_buff *frag, - int hdr_len); - -netdev_tx_t rtllib_xmit(struct sk_buff *skb, struct net_device *dev); -void rtllib_txb_free(struct rtllib_txb *txb); - -/* rtllib_rx.c */ -int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats); -int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel); - -/* rtllib_wx.c */ -int rtllib_wx_get_scan(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -int rtllib_wx_set_encode(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -int rtllib_wx_get_encode(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -int rtllib_wx_set_auth(struct rtllib_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra); -int rtllib_wx_set_mlme(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len); - -/* rtllib_softmac.c */ -int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, u16 type, - u16 stype); -void rtllib_softmac_new_net(struct rtllib_device *ieee, - struct rtllib_network *net); - -void send_disassociation(struct rtllib_device *ieee, bool deauth, u16 rsn); -void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee); - -int rtllib_softmac_init(struct rtllib_device *ieee); -void rtllib_softmac_free(struct rtllib_device *ieee); -void rtllib_disassociate(struct rtllib_device *ieee); -void rtllib_stop_scan(struct rtllib_device *ieee); -bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan); -void rtllib_stop_scan_syncro(struct rtllib_device *ieee); -void rtllib_start_scan_syncro(struct rtllib_device *ieee); -void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr); -void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee); -void rtllib_start_protocol(struct rtllib_device *ieee); -void rtllib_stop_protocol(struct rtllib_device *ieee); - -void rtllib_enable_net_monitor_mode(struct net_device *dev, bool init_state); -void rtllib_disable_net_monitor_mode(struct net_device *dev, bool init_state); - -void rtllib_softmac_stop_protocol(struct rtllib_device *ieee); -void rtllib_softmac_start_protocol(struct rtllib_device *ieee); - -void rtllib_reset_queue(struct rtllib_device *ieee); -void rtllib_wake_all_queues(struct rtllib_device *ieee); -void rtllib_stop_all_queues(struct rtllib_device *ieee); - -void notify_wx_assoc_event(struct rtllib_device *ieee); -void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success); - -void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee); -u8 rtllib_ap_sec_type(struct rtllib_device *ieee); - -/* rtllib_softmac_wx.c */ - -int rtllib_wx_get_wap(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *ext); - -int rtllib_wx_set_wap(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *awrq, char *extra); - -int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -int rtllib_wx_set_rate(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_get_rate(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -int rtllib_wx_set_essid(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b); -void rtllib_wx_sync_scan_wq(void *data); - -int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_set_power(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_get_power(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_set_rts(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int rtllib_wx_get_rts(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -#define MAX_RECEIVE_BUFFER_SIZE 9100 - -void ht_set_connect_bw_mode(struct rtllib_device *ieee, - enum ht_channel_width bandwidth, - enum ht_extchnl_offset Offset); -void ht_update_default_setting(struct rtllib_device *ieee); -void ht_construct_capability_element(struct rtllib_device *ieee, - u8 *pos_ht_cap, u8 *len, - u8 is_encrypt, bool assoc); -void ht_construct_rt2rt_agg_element(struct rtllib_device *ieee, - u8 *posRT2RTAgg, u8 *len); -void ht_on_assoc_rsp(struct rtllib_device *ieee); -void ht_initialize_ht_info(struct rtllib_device *ieee); -void ht_initialize_bss_desc(struct bss_ht *bss_ht); -void ht_reset_self_and_save_peer_setting(struct rtllib_device *ieee, - struct rtllib_network *network); -void HT_update_self_and_peer_setting(struct rtllib_device *ieee, - struct rtllib_network *network); -u8 ht_get_highest_mcs_rate(struct rtllib_device *ieee, u8 *pMCSRateSet, - u8 *pMCSFilter); -extern u8 MCS_FILTER_ALL[]; -extern u16 MCS_DATA_RATE[2][2][77]; -u8 ht_c_check(struct rtllib_device *ieee, u8 *frame); -void ht_reset_iot_setting(struct rt_hi_throughput *ht_info); -bool is_ht_half_nmode_aps(struct rtllib_device *ieee); -u16 tx_count_to_data_rate(struct rtllib_device *ieee, u8 nDataRate); -int rtllib_rx_add_ba_req(struct rtllib_device *ieee, struct sk_buff *skb); -int rtllib_rx_add_ba_rsp(struct rtllib_device *ieee, struct sk_buff *skb); -int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb); -void rtllib_ts_init_add_ba(struct rtllib_device *ieee, struct tx_ts_record *ts, - u8 policy, u8 overwrite_pending); -void rtllib_ts_init_del_ba(struct rtllib_device *ieee, - struct ts_common_info *ts_common_info, - enum tr_select tx_rx_select); -void rtllib_ba_setup_timeout(struct timer_list *t); -void rtllib_tx_ba_inact_timeout(struct timer_list *t); -void rtllib_rx_ba_inact_timeout(struct timer_list *t); -void rtllib_reset_ba_entry(struct ba_record *ba); -bool rtllib_get_ts(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *addr, - u8 TID, enum tr_select tx_rx_select, bool add_new_ts); -void rtllib_ts_init(struct rtllib_device *ieee); -void rtllib_ts_start_add_ba_process(struct rtllib_device *ieee, - struct tx_ts_record *pTxTS); -void remove_peer_ts(struct rtllib_device *ieee, u8 *addr); -void remove_all_ts(struct rtllib_device *ieee); - -static inline const char *escape_essid(const char *essid, u8 essid_len) -{ - static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - - if (rtllib_is_empty_essid(essid, essid_len)) { - memcpy(escaped, "<hidden>", sizeof("<hidden>")); - return escaped; - } - - snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); - return escaped; -} - -/* fun with the built-in rtllib stack... */ -bool rtllib_mgnt_disconnect(struct rtllib_device *rtllib, u8 rsn); - -/* For the function is more related to hardware setting, it's better to use the - * ieee handler to refer to it. - */ -void rtllib_flush_rx_ts_pending_pkts(struct rtllib_device *ieee, - struct rx_ts_record *ts); -int rtllib_parse_info_param(struct rtllib_device *ieee, - struct rtllib_info_element *info_element, - u16 length, - struct rtllib_network *network, - struct rtllib_rx_stats *stats); - -void rtllib_indicate_packets(struct rtllib_device *ieee, - struct rtllib_rxb **prxb_indicate_array, u8 index); -#define RT_ASOC_RETRY_LIMIT 5 -u8 mgnt_query_tx_rate_exclude_cck_rates(struct rtllib_device *ieee); - -#endif /* RTLLIB_H */ diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c deleted file mode 100644 index 138733cb00e2..000000000000 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ /dev/null @@ -1,411 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Host AP crypt: host-based CCMP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/if_ether.h> -#include <linux/if_arp.h> -#include <linux/string.h> -#include <linux/wireless.h> -#include "rtllib.h" - -#include <linux/crypto.h> -#include <crypto/aead.h> - -#include <linux/scatterlist.h> - -#define AES_BLOCK_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 - -struct rtllib_ccmp_data { - u8 key[CCMP_TK_LEN]; - int key_set; - - u8 tx_pn[CCMP_PN_LEN]; - u8 rx_pn[CCMP_PN_LEN]; - - u32 dot11rsna_stats_ccmp_format_errors; - u32 dot11rsna_stats_ccmp_replays; - u32 dot11rsna_stats_ccmp_decrypt_errors; - - int key_idx; - - struct crypto_aead *tfm; - - /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_aad[2 * AES_BLOCK_LEN]; - u8 rx_aad[2 * AES_BLOCK_LEN]; -}; - -static void *rtllib_ccmp_init(int key_idx) -{ - struct rtllib_ccmp_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (!priv) - goto fail; - priv->key_idx = key_idx; - - priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm)) { - pr_debug("Could not allocate crypto API aes\n"); - priv->tfm = NULL; - goto fail; - } - return priv; - -fail: - if (priv) { - if (priv->tfm) - crypto_free_aead(priv->tfm); - kfree(priv); - } - - return NULL; -} - -static void rtllib_ccmp_deinit(void *priv) -{ - struct rtllib_ccmp_data *_priv = priv; - - if (_priv && _priv->tfm) - crypto_free_aead(_priv->tfm); - kfree(priv); -} - -static int ccmp_init_iv_and_aad(struct ieee80211_hdr *hdr, - u8 *pn, u8 *iv, u8 *aad) -{ - u8 *pos, qc = 0; - size_t aad_len; - u16 fc; - int a4_included, qc_included; - - fc = le16_to_cpu(hdr->frame_control); - a4_included = ieee80211_has_a4(hdr->frame_control); - - qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) && - (WLAN_FC_GET_STYPE(fc) & 0x80)); - aad_len = 22; - if (a4_included) - aad_len += 6; - if (qc_included) { - pos = (u8 *)&hdr->addr4; - if (a4_included) - pos += 6; - qc = *pos & 0x0f; - aad_len += 2; - } - /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC - * mode authentication are not allowed to collide, yet both are derived - * from the same vector. We only set L := 1 here to indicate that the - * data size can be represented in (L+1) bytes. The CCM layer will take - * care of storing the data length in the top (L+1) bytes and setting - * and clearing the other bits as is required to derive the two IVs. - */ - iv[0] = 0x1; - - /* Nonce: QC | A2 | PN */ - iv[1] = qc; - memcpy(iv + 2, hdr->addr2, ETH_ALEN); - memcpy(iv + 8, pn, CCMP_PN_LEN); - - /* AAD: - * FC with bits 4..6 and 11..13 masked to zero; 14 is always one - * A1 | A2 | A3 - * SC with bits 4..15 (seq#) masked to zero - * A4 (if present) - * QC (if present) - */ - pos = (u8 *)hdr; - aad[0] = pos[0] & 0x8f; - aad[1] = pos[1] & 0xc7; - memcpy(&aad[2], &hdr->addr1, ETH_ALEN); - memcpy(&aad[8], &hdr->addr2, ETH_ALEN); - memcpy(&aad[14], &hdr->addr3, ETH_ALEN); - pos = (u8 *)&hdr->seq_ctrl; - aad[20] = pos[0] & 0x0f; - aad[21] = 0; /* all bits masked */ - memset(aad + 22, 0, 8); - if (a4_included) - memcpy(aad + 22, hdr->addr4, ETH_ALEN); - if (qc_included) { - aad[a4_included ? 28 : 22] = qc; - /* rest of QC masked */ - } - - return aad_len; -} - -static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct rtllib_ccmp_data *key = priv; - int i; - u8 *pos; - struct ieee80211_hdr *hdr; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - if (skb_headroom(skb) < CCMP_HDR_LEN || - skb_tailroom(skb) < CCMP_MIC_LEN || - skb->len < hdr_len) - return -1; - - pos = skb_push(skb, CCMP_HDR_LEN); - memmove(pos, pos + CCMP_HDR_LEN, hdr_len); - pos += hdr_len; - - i = CCMP_PN_LEN - 1; - while (i >= 0) { - key->tx_pn[i]++; - if (key->tx_pn[i] != 0) - break; - i--; - } - - *pos++ = key->tx_pn[5]; - *pos++ = key->tx_pn[4]; - *pos++ = 0; - *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = key->tx_pn[3]; - *pos++ = key->tx_pn[2]; - *pos++ = key->tx_pn[1]; - *pos++ = key->tx_pn[0]; - - hdr = (struct ieee80211_hdr *)skb->data; - if (!tcb_desc->hw_sec) { - struct aead_request *req; - struct scatterlist sg[2]; - u8 *aad = key->tx_aad; - u8 iv[AES_BLOCK_LEN]; - int aad_len, ret; - int data_len = skb->len - hdr_len - CCMP_HDR_LEN; - - req = aead_request_alloc(key->tfm, GFP_ATOMIC); - if (!req) - return -ENOMEM; - - aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); - - skb_put(skb, CCMP_MIC_LEN); - sg_init_table(sg, 2); - sg_set_buf(&sg[0], aad, aad_len); - sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, - data_len + CCMP_MIC_LEN); - - aead_request_set_callback(req, 0, NULL, NULL); - aead_request_set_ad(req, aad_len); - aead_request_set_crypt(req, sg, sg, data_len, iv); - - ret = crypto_aead_encrypt(req); - aead_request_free(req); - - return ret; - } - - return 0; -} - -static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct rtllib_ccmp_data *key = priv; - u8 keyidx, *pos; - struct ieee80211_hdr *hdr; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u8 pn[6]; - - if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { - key->dot11rsna_stats_ccmp_format_errors++; - return -1; - } - - hdr = (struct ieee80211_hdr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - pr_debug("CCMP: received packet without ExtIV flag from %pM\n", - hdr->addr2); - } - key->dot11rsna_stats_ccmp_format_errors++; - return -2; - } - keyidx >>= 6; - if (key->key_idx != keyidx) { - pr_debug("CCMP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n", - key->key_idx, keyidx, priv); - return -6; - } - if (!key->key_set) { - if (net_ratelimit()) { - pr_debug("CCMP: received packet from %pM with keyid=%d that does not have a configured key\n", - hdr->addr2, keyidx); - } - return -3; - } - - pn[0] = pos[7]; - pn[1] = pos[6]; - pn[2] = pos[5]; - pn[3] = pos[4]; - pn[4] = pos[1]; - pn[5] = pos[0]; - pos += 8; - if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { - key->dot11rsna_stats_ccmp_replays++; - return -4; - } - if (!tcb_desc->hw_sec) { - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; - struct aead_request *req; - struct scatterlist sg[2]; - u8 *aad = key->rx_aad; - u8 iv[AES_BLOCK_LEN]; - int aad_len, ret; - - req = aead_request_alloc(key->tfm, GFP_ATOMIC); - if (!req) - return -ENOMEM; - - aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); - - sg_init_table(sg, 2); - sg_set_buf(&sg[0], aad, aad_len); - sg_set_buf(&sg[1], pos, data_len); - - aead_request_set_callback(req, 0, NULL, NULL); - aead_request_set_ad(req, aad_len); - aead_request_set_crypt(req, sg, sg, data_len, iv); - - ret = crypto_aead_decrypt(req); - aead_request_free(req); - - if (ret) { - if (net_ratelimit()) { - pr_debug("CCMP: decrypt failed: STA= %pM\n", - hdr->addr2); - } - key->dot11rsna_stats_ccmp_decrypt_errors++; - return -5; - } - - memcpy(key->rx_pn, pn, CCMP_PN_LEN); - } - /* Remove hdr and MIC */ - memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); - skb_pull(skb, CCMP_HDR_LEN); - skb_trim(skb, skb->len - CCMP_MIC_LEN); - - return keyidx; -} - -static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct rtllib_ccmp_data *data = priv; - int keyidx; - struct crypto_aead *tfm = data->tfm; - - keyidx = data->key_idx; - memset(data, 0, sizeof(*data)); - data->key_idx = keyidx; - data->tfm = tfm; - if (len == CCMP_TK_LEN) { - memcpy(data->key, key, CCMP_TK_LEN); - data->key_set = 1; - if (seq) { - data->rx_pn[0] = seq[5]; - data->rx_pn[1] = seq[4]; - data->rx_pn[2] = seq[3]; - data->rx_pn[3] = seq[2]; - data->rx_pn[4] = seq[1]; - data->rx_pn[5] = seq[0]; - } - if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) || - crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN)) - return -1; - } else if (len == 0) { - data->key_set = 0; - } else { - return -1; - } - - return 0; -} - -static int rtllib_ccmp_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct rtllib_ccmp_data *data = priv; - - if (len < CCMP_TK_LEN) - return -1; - - if (!data->key_set) - return 0; - memcpy(key, data->key, CCMP_TK_LEN); - - if (seq) { - seq[0] = data->tx_pn[5]; - seq[1] = data->tx_pn[4]; - seq[2] = data->tx_pn[3]; - seq[3] = data->tx_pn[2]; - seq[4] = data->tx_pn[1]; - seq[5] = data->tx_pn[0]; - } - - return CCMP_TK_LEN; -} - -static void rtllib_ccmp_print_stats(struct seq_file *m, void *priv) -{ - struct rtllib_ccmp_data *ccmp = priv; - - seq_printf(m, - "key[%d] alg=CCMP key_set=%d tx_pn=%pM rx_pn=%pM format_errors=%d replays=%d decrypt_errors=%d\n", - ccmp->key_idx, ccmp->key_set, - ccmp->tx_pn, ccmp->rx_pn, - ccmp->dot11rsna_stats_ccmp_format_errors, - ccmp->dot11rsna_stats_ccmp_replays, - ccmp->dot11rsna_stats_ccmp_decrypt_errors); -} - -static const struct lib80211_crypto_ops rtllib_crypt_ccmp = { - .name = "R-CCMP", - .init = rtllib_ccmp_init, - .deinit = rtllib_ccmp_deinit, - .encrypt_mpdu = rtllib_ccmp_encrypt, - .decrypt_mpdu = rtllib_ccmp_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = rtllib_ccmp_set_key, - .get_key = rtllib_ccmp_get_key, - .print_stats = rtllib_ccmp_print_stats, - .extra_mpdu_prefix_len = CCMP_HDR_LEN, - .extra_mpdu_postfix_len = CCMP_MIC_LEN, - .owner = THIS_MODULE, -}; - -static int __init rtllib_crypto_ccmp_init(void) -{ - return lib80211_register_crypto_ops(&rtllib_crypt_ccmp); -} - -static void __exit rtllib_crypto_ccmp_exit(void) -{ - lib80211_unregister_crypto_ops(&rtllib_crypt_ccmp); -} - -module_init(rtllib_crypto_ccmp_init); -module_exit(rtllib_crypto_ccmp_exit); - -MODULE_DESCRIPTION("Support module for rtllib CCMP crypto"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c deleted file mode 100644 index e544379bfa91..000000000000 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ /dev/null @@ -1,706 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Host AP crypt: host-based TKIP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - */ - -#include <crypto/arc4.h> -#include <crypto/hash.h> -#include <linux/fips.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/if_ether.h> -#include <linux/if_arp.h> -#include <linux/string.h> -#include <linux/crc32.h> -#include <linux/etherdevice.h> - -#include "rtllib.h" - -struct rtllib_tkip_data { -#define TKIP_KEY_LEN 32 - u8 key[TKIP_KEY_LEN]; - int key_set; - - u32 tx_iv32; - u16 tx_iv16; - u16 tx_ttak[5]; - int tx_phase1_done; - - u32 rx_iv32; - u16 rx_iv16; - bool initialized; - u16 rx_ttak[5]; - int rx_phase1_done; - u32 rx_iv32_new; - u16 rx_iv16_new; - - u32 dot11RSNAStatsTKIPReplays; - u32 dot11RSNAStatsTKIPICVErrors; - u32 dot11RSNAStatsTKIPLocalMICFailures; - - int key_idx; - struct arc4_ctx rx_ctx_arc4; - struct arc4_ctx tx_ctx_arc4; - struct crypto_shash *rx_tfm_michael; - struct crypto_shash *tx_tfm_michael; - /* scratch buffers for virt_to_page() (crypto API) */ - u8 rx_hdr[16]; - u8 tx_hdr[16]; -}; - -static void *rtllib_tkip_init(int key_idx) -{ - struct rtllib_tkip_data *priv; - - if (fips_enabled) - return NULL; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (!priv) - goto fail; - priv->key_idx = key_idx; - - priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); - if (IS_ERR(priv->tx_tfm_michael)) { - pr_debug("Could not allocate crypto API michael_mic\n"); - priv->tx_tfm_michael = NULL; - goto fail; - } - - priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0); - if (IS_ERR(priv->rx_tfm_michael)) { - pr_debug("Could not allocate crypto API michael_mic\n"); - priv->rx_tfm_michael = NULL; - goto fail; - } - return priv; - -fail: - if (priv) { - crypto_free_shash(priv->tx_tfm_michael); - crypto_free_shash(priv->rx_tfm_michael); - kfree(priv); - } - - return NULL; -} - -static void rtllib_tkip_deinit(void *priv) -{ - struct rtllib_tkip_data *_priv = priv; - - if (_priv) { - crypto_free_shash(_priv->tx_tfm_michael); - crypto_free_shash(_priv->rx_tfm_michael); - } - kfree_sensitive(priv); -} - -static inline u16 RotR1(u16 val) -{ - return (val >> 1) | (val << 15); -} - -static inline u8 Lo8(u16 val) -{ - return val & 0xff; -} - -static inline u8 Hi8(u16 val) -{ - return val >> 8; -} - -static inline u16 Lo16(u32 val) -{ - return val & 0xffff; -} - -static inline u16 Hi16(u32 val) -{ - return val >> 16; -} - -static inline u16 Mk16(u8 hi, u8 lo) -{ - return lo | (hi << 8); -} - -static inline u16 Mk16_le(u16 *v) -{ - return *v; -} - -static const u16 Sbox[256] = { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, -}; - -static inline u16 _S_(u16 v) -{ - u16 t = Sbox[Hi8(v)]; - return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); -} - -#define PHASE1_LOOP_COUNT 8 - -static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) -{ - int i, j; - - /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ - TTAK[0] = Lo16(IV32); - TTAK[1] = Hi16(IV32); - TTAK[2] = Mk16(TA[1], TA[0]); - TTAK[3] = Mk16(TA[3], TA[2]); - TTAK[4] = Mk16(TA[5], TA[4]); - - for (i = 0; i < PHASE1_LOOP_COUNT; i++) { - j = 2 * (i & 1); - TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); - TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); - TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); - TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); - TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; - } -} - -static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, - u16 IV16) -{ - /* Make temporary area overlap WEP seed so that the final copy can be - * avoided on little endian hosts. - */ - u16 *PPK = (u16 *)&WEPSeed[4]; - - /* Step 1 - make copy of TTAK and bring in TSC */ - PPK[0] = TTAK[0]; - PPK[1] = TTAK[1]; - PPK[2] = TTAK[2]; - PPK[3] = TTAK[3]; - PPK[4] = TTAK[4]; - PPK[5] = TTAK[4] + IV16; - - /* Step 2 - 96-bit bijective mixing using S-box */ - PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *)&TK[0])); - PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *)&TK[2])); - PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *)&TK[4])); - PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *)&TK[6])); - PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *)&TK[8])); - PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *)&TK[10])); - - PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *)&TK[12])); - PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *)&TK[14])); - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - - /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value - * WEPSeed[0..2] is transmitted as WEP IV - */ - WEPSeed[0] = Hi8(IV16); - WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; - WEPSeed[2] = Lo8(IV16); - WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *)&TK[0])) >> 1); - -#ifdef __BIG_ENDIAN - { - int i; - - for (i = 0; i < 6; i++) - PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); - } -#endif -} - -static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - int len; - u8 *pos; - struct ieee80211_hdr *hdr; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - int ret = 0; - u8 rc4key[16], *icv; - u32 crc; - - if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || - skb->len < hdr_len) - return -1; - - hdr = (struct ieee80211_hdr *)skb->data; - - if (!tcb_desc->hw_sec) { - if (!tkey->tx_phase1_done) { - tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, - tkey->tx_iv32); - tkey->tx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, - tkey->tx_iv16); - } else { - tkey->tx_phase1_done = 1; - } - - len = skb->len - hdr_len; - pos = skb_push(skb, 8); - memmove(pos, pos + 8, hdr_len); - pos += hdr_len; - - if (tcb_desc->hw_sec) { - *pos++ = Hi8(tkey->tx_iv16); - *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; - *pos++ = Lo8(tkey->tx_iv16); - } else { - *pos++ = rc4key[0]; - *pos++ = rc4key[1]; - *pos++ = rc4key[2]; - } - - *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = tkey->tx_iv32 & 0xff; - *pos++ = (tkey->tx_iv32 >> 8) & 0xff; - *pos++ = (tkey->tx_iv32 >> 16) & 0xff; - *pos++ = (tkey->tx_iv32 >> 24) & 0xff; - - if (!tcb_desc->hw_sec) { - icv = skb_put(skb, 4); - crc = ~crc32_le(~0, pos, len); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - arc4_setkey(&tkey->tx_ctx_arc4, rc4key, 16); - arc4_crypt(&tkey->tx_ctx_arc4, pos, pos, len + 4); - } - - tkey->tx_iv16++; - if (tkey->tx_iv16 == 0) { - tkey->tx_phase1_done = 0; - tkey->tx_iv32++; - } - - if (!tcb_desc->hw_sec) - return ret; - return 0; -} - -static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - u8 keyidx, *pos; - u32 iv32; - u16 iv16; - struct ieee80211_hdr *hdr; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u8 rc4key[16]; - u8 icv[4]; - u32 crc; - int plen; - - if (skb->len < hdr_len + 8 + 4) - return -1; - - hdr = (struct ieee80211_hdr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - netdev_dbg(skb->dev, - "Received packet without ExtIV flag from %pM\n", - hdr->addr2); - } - return -2; - } - keyidx >>= 6; - if (tkey->key_idx != keyidx) { - netdev_dbg(skb->dev, - "RX tkey->key_idx=%d frame keyidx=%d priv=%p\n", - tkey->key_idx, keyidx, priv); - return -6; - } - if (!tkey->key_set) { - if (net_ratelimit()) { - netdev_dbg(skb->dev, - "Received packet from %pM with keyid=%d that does not have a configured key\n", - hdr->addr2, keyidx); - } - return -3; - } - iv16 = (pos[0] << 8) | pos[2]; - iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); - pos += 8; - - if (!tcb_desc->hw_sec || (skb->cb[0] == 1)) { - if ((iv32 < tkey->rx_iv32 || - (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) && - tkey->initialized) { - if (net_ratelimit()) { - netdev_dbg(skb->dev, - "Replay detected: STA= %pM previous TSC %08x%04x received TSC %08x%04x\n", - hdr->addr2, tkey->rx_iv32, - tkey->rx_iv16, iv32, iv16); - } - tkey->dot11RSNAStatsTKIPReplays++; - return -4; - } - tkey->initialized = true; - - if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { - tkip_mixing_phase1(tkey->rx_ttak, tkey->key, - hdr->addr2, iv32); - tkey->rx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); - - plen = skb->len - hdr_len - 12; - - arc4_setkey(&tkey->rx_ctx_arc4, rc4key, 16); - arc4_crypt(&tkey->rx_ctx_arc4, pos, pos, plen + 4); - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - if (memcmp(icv, pos + plen, 4) != 0) { - if (iv32 != tkey->rx_iv32) { - /* Previously cached Phase1 result was already - * lost, so it needs to be recalculated for the - * next packet. - */ - tkey->rx_phase1_done = 0; - } - if (net_ratelimit()) { - netdev_dbg(skb->dev, - "ICV error detected: STA= %pM\n", - hdr->addr2); - } - tkey->dot11RSNAStatsTKIPICVErrors++; - return -5; - } - } - - /* Update real counters only after Michael MIC verification has - * completed - */ - tkey->rx_iv32_new = iv32; - tkey->rx_iv16_new = iv16; - - /* Remove IV and ICV */ - memmove(skb->data + 8, skb->data, hdr_len); - skb_pull(skb, 8); - skb_trim(skb, skb->len - 4); - - return keyidx; -} - -static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr, - u8 *data, size_t data_len, u8 *mic) -{ - SHASH_DESC_ON_STACK(desc, tfm_michael); - int err; - - desc->tfm = tfm_michael; - - if (crypto_shash_setkey(tfm_michael, key, 8)) - return -1; - - err = crypto_shash_init(desc); - if (err) - goto out; - err = crypto_shash_update(desc, hdr, 16); - if (err) - goto out; - err = crypto_shash_update(desc, data, data_len); - if (err) - goto out; - err = crypto_shash_final(desc, mic); - -out: - shash_desc_zero(desc); - return err; -} - -static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) -{ - struct ieee80211_hdr *hdr11; - - hdr11 = (struct ieee80211_hdr *)skb->data; - switch (le16_to_cpu(hdr11->frame_control) & - (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_TODS: - ether_addr_copy(hdr, hdr11->addr3); /* DA */ - ether_addr_copy(hdr + ETH_ALEN, hdr11->addr2); /* SA */ - break; - case IEEE80211_FCTL_FROMDS: - ether_addr_copy(hdr, hdr11->addr1); /* DA */ - ether_addr_copy(hdr + ETH_ALEN, hdr11->addr3); /* SA */ - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - ether_addr_copy(hdr, hdr11->addr3); /* DA */ - ether_addr_copy(hdr + ETH_ALEN, hdr11->addr4); /* SA */ - break; - case 0: - ether_addr_copy(hdr, hdr11->addr1); /* DA */ - ether_addr_copy(hdr + ETH_ALEN, hdr11->addr2); /* SA */ - break; - } - - /* priority */ - hdr[12] = 0; - - /* reserved */ - hdr[13] = 0; - hdr[14] = 0; - hdr[15] = 0; -} - -static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - u8 *pos; - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)skb->data; - - if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { - netdev_dbg(skb->dev, - "Invalid packet for Michael MIC add (tailroom=%d hdr_len=%d skb->len=%d)\n", - skb_tailroom(skb), hdr_len, skb->len); - return -1; - } - - michael_mic_hdr(skb, tkey->tx_hdr); - - if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_control))) - tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - pos = skb_put(skb, 8); - if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) - return -1; - - return 0; -} - -static void rtllib_michael_mic_failure(struct net_device *dev, - struct ieee80211_hdr *hdr, - int keyidx) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - - /* TODO: needed parameters: count, keyid, key type, TSC */ - memset(&ev, 0, sizeof(ev)); - ev.flags = keyidx & IW_MICFAILURE_KEY_ID; - if (hdr->addr1[0] & 0x01) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - ev.src_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(ev.src_addr.sa_data, hdr->addr2); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); -} - -static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx, - int hdr_len, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - u8 mic[8]; - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)skb->data; - - if (!tkey->key_set) - return -1; - - michael_mic_hdr(skb, tkey->rx_hdr); - if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_control))) - tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - - if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) - return -1; - - if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)skb->data; - netdev_dbg(skb->dev, - "Michael MIC verification failed for MSDU from %pM keyidx=%d\n", - hdr->addr2, keyidx); - netdev_dbg(skb->dev, "%d\n", - memcmp(mic, skb->data + skb->len - 8, 8) != 0); - if (skb->dev) { - pr_info("skb->dev != NULL\n"); - rtllib_michael_mic_failure(skb->dev, hdr, keyidx); - } - tkey->dot11RSNAStatsTKIPLocalMICFailures++; - return -1; - } - - /* Update TSC counters for RX now that the packet verification has - * completed. - */ - tkey->rx_iv32 = tkey->rx_iv32_new; - tkey->rx_iv16 = tkey->rx_iv16_new; - - skb_trim(skb, skb->len - 8); - - return 0; -} - -static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - int keyidx; - struct crypto_shash *tfm = tkey->tx_tfm_michael; - struct crypto_shash *tfm3 = tkey->rx_tfm_michael; - - keyidx = tkey->key_idx; - memset(tkey, 0, sizeof(*tkey)); - tkey->key_idx = keyidx; - tkey->tx_tfm_michael = tfm; - tkey->rx_tfm_michael = tfm3; - - if (len == TKIP_KEY_LEN) { - memcpy(tkey->key, key, TKIP_KEY_LEN); - tkey->key_set = 1; - tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ - if (seq) { - tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | - (seq[3] << 8) | seq[2]; - tkey->rx_iv16 = (seq[1] << 8) | seq[0]; - } - } else if (len == 0) { - tkey->key_set = 0; - } else { - return -1; - } - - return 0; -} - -static int rtllib_tkip_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct rtllib_tkip_data *tkey = priv; - - if (len < TKIP_KEY_LEN) - return -1; - - if (!tkey->key_set) - return 0; - memcpy(key, tkey->key, TKIP_KEY_LEN); - - if (seq) { - /* Return the sequence number of the last transmitted frame. */ - seq[0] = tkey->tx_iv16; - seq[1] = tkey->tx_iv16 >> 8; - seq[2] = tkey->tx_iv32; - seq[3] = tkey->tx_iv32 >> 8; - seq[4] = tkey->tx_iv32 >> 16; - seq[5] = tkey->tx_iv32 >> 24; - } - - return TKIP_KEY_LEN; -} - -static void rtllib_tkip_print_stats(struct seq_file *m, void *priv) -{ - struct rtllib_tkip_data *tkip = priv; - - seq_printf(m, - "key[%d] alg=TKIP key_set=%d tx_pn=%02x%02x%02x%02x%02x%02x rx_pn=%02x%02x%02x%02x%02x%02x replays=%d icv_errors=%d local_mic_failures=%d\n", - tkip->key_idx, tkip->key_set, - (tkip->tx_iv32 >> 24) & 0xff, - (tkip->tx_iv32 >> 16) & 0xff, - (tkip->tx_iv32 >> 8) & 0xff, - tkip->tx_iv32 & 0xff, - (tkip->tx_iv16 >> 8) & 0xff, - tkip->tx_iv16 & 0xff, - (tkip->rx_iv32 >> 24) & 0xff, - (tkip->rx_iv32 >> 16) & 0xff, - (tkip->rx_iv32 >> 8) & 0xff, - tkip->rx_iv32 & 0xff, - (tkip->rx_iv16 >> 8) & 0xff, - tkip->rx_iv16 & 0xff, - tkip->dot11RSNAStatsTKIPReplays, - tkip->dot11RSNAStatsTKIPICVErrors, - tkip->dot11RSNAStatsTKIPLocalMICFailures); -} - -static const struct lib80211_crypto_ops rtllib_crypt_tkip = { - .name = "R-TKIP", - .init = rtllib_tkip_init, - .deinit = rtllib_tkip_deinit, - .encrypt_mpdu = rtllib_tkip_encrypt, - .decrypt_mpdu = rtllib_tkip_decrypt, - .encrypt_msdu = rtllib_michael_mic_add, - .decrypt_msdu = rtllib_michael_mic_verify, - .set_key = rtllib_tkip_set_key, - .get_key = rtllib_tkip_get_key, - .print_stats = rtllib_tkip_print_stats, - .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */ - .extra_mpdu_postfix_len = 4, /* ICV */ - .extra_msdu_postfix_len = 8, /* MIC */ - .owner = THIS_MODULE, -}; - -static int __init rtllib_crypto_tkip_init(void) -{ - return lib80211_register_crypto_ops(&rtllib_crypt_tkip); -} - -static void __exit rtllib_crypto_tkip_exit(void) -{ - lib80211_unregister_crypto_ops(&rtllib_crypt_tkip); -} - -module_init(rtllib_crypto_tkip_init); -module_exit(rtllib_crypto_tkip_exit); - -MODULE_DESCRIPTION("Support module for rtllib TKIP crypto"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c deleted file mode 100644 index aa18c060d727..000000000000 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Host AP crypt: host-based WEP encryption implementation for Host AP driver - * - * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> - */ - -#include <crypto/arc4.h> -#include <linux/fips.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/skbuff.h> -#include <linux/string.h> -#include "rtllib.h" - -#include <linux/crc32.h> - -struct prism2_wep_data { - u32 iv; -#define WEP_KEY_LEN 13 - u8 key[WEP_KEY_LEN + 1]; - u8 key_len; - u8 key_idx; - struct arc4_ctx rx_ctx_arc4; - struct arc4_ctx tx_ctx_arc4; -}; - -static void *prism2_wep_init(int keyidx) -{ - struct prism2_wep_data *priv; - - if (fips_enabled) - return NULL; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (!priv) - return NULL; - priv->key_idx = keyidx; - - /* start WEP IV from a random value */ - get_random_bytes(&priv->iv, 4); - - return priv; -} - -static void prism2_wep_deinit(void *priv) -{ - kfree_sensitive(priv); -} - -/* Perform WEP encryption on given skb that has at least 4 bytes of headroom - * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, - * so the payload length increases with 8 bytes. - * - * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) - */ -static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - u32 klen, len; - u8 key[WEP_KEY_LEN + 3]; - u8 *pos; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u32 crc; - u8 *icv; - - if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || - skb->len < hdr_len){ - pr_err("Error!!! headroom=%d tailroom=%d skblen=%d hdr_len=%d\n", - skb_headroom(skb), skb_tailroom(skb), skb->len, hdr_len); - return -1; - } - len = skb->len - hdr_len; - pos = skb_push(skb, 4); - memmove(pos, pos + 4, hdr_len); - pos += hdr_len; - - klen = 3 + wep->key_len; - - wep->iv++; - - /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key - * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) - * can be used to speedup attacks, so avoid using them. - */ - if ((wep->iv & 0xff00) == 0xff00) { - u8 B = (wep->iv >> 16) & 0xff; - - if (B >= 3 && B < klen) - wep->iv += 0x0100; - } - - /* Prepend 24-bit IV to RC4 key and TX frame */ - *pos++ = key[0] = (wep->iv >> 16) & 0xff; - *pos++ = key[1] = (wep->iv >> 8) & 0xff; - *pos++ = key[2] = wep->iv & 0xff; - *pos++ = wep->key_idx << 6; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - if (!tcb_desc->hw_sec) { - /* Append little-endian CRC32 and encrypt it to produce ICV */ - crc = ~crc32_le(~0, pos, len); - icv = skb_put(skb, 4); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - arc4_setkey(&wep->tx_ctx_arc4, key, klen); - arc4_crypt(&wep->tx_ctx_arc4, pos, pos, len + 4); - } - - return 0; -} - -/* Perform WEP decryption on given struct buffer. Buffer includes whole WEP - * part of the frame: IV (4 bytes), encrypted payload (including SNAP header), - * ICV (4 bytes). len includes both IV and ICV. - * - * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on - * failure. If frame is OK, IV and ICV will be removed. - */ -static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - u32 klen, plen; - u8 key[WEP_KEY_LEN + 3]; - u8 keyidx, *pos; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + - MAX_DEV_ADDR_SIZE); - u32 crc; - u8 icv[4]; - - if (skb->len < hdr_len + 8) - return -1; - - pos = skb->data + hdr_len; - key[0] = *pos++; - key[1] = *pos++; - key[2] = *pos++; - keyidx = *pos++ >> 6; - if (keyidx != wep->key_idx) - return -1; - - klen = 3 + wep->key_len; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - /* Apply RC4 to data and compute CRC32 over decrypted data */ - plen = skb->len - hdr_len - 8; - - if (!tcb_desc->hw_sec) { - arc4_setkey(&wep->rx_ctx_arc4, key, klen); - arc4_crypt(&wep->rx_ctx_arc4, pos, pos, plen + 4); - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - if (memcmp(icv, pos + plen, 4) != 0) { - /* ICV mismatch - drop frame */ - return -2; - } - } - /* Remove IV and ICV */ - memmove(skb->data + 4, skb->data, hdr_len); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - - return 0; -} - -static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < 0 || len > WEP_KEY_LEN) - return -1; - - memcpy(wep->key, key, len); - wep->key_len = len; - - return 0; -} - -static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < wep->key_len) - return -1; - - memcpy(key, wep->key, wep->key_len); - - return wep->key_len; -} - -static void prism2_wep_print_stats(struct seq_file *m, void *priv) -{ - struct prism2_wep_data *wep = priv; - - seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len); -} - -static const struct lib80211_crypto_ops rtllib_crypt_wep = { - .name = "R-WEP", - .init = prism2_wep_init, - .deinit = prism2_wep_deinit, - .encrypt_mpdu = prism2_wep_encrypt, - .decrypt_mpdu = prism2_wep_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = prism2_wep_set_key, - .get_key = prism2_wep_get_key, - .print_stats = prism2_wep_print_stats, - .extra_mpdu_prefix_len = 4, /* IV */ - .extra_mpdu_postfix_len = 4, /* ICV */ - .owner = THIS_MODULE, -}; - -static int __init rtllib_crypto_wep_init(void) -{ - return lib80211_register_crypto_ops(&rtllib_crypt_wep); -} - -static void __exit rtllib_crypto_wep_exit(void) -{ - lib80211_unregister_crypto_ops(&rtllib_crypt_wep); -} - -module_init(rtllib_crypto_wep_init); -module_exit(rtllib_crypto_wep_exit); - -MODULE_DESCRIPTION("Support module for rtllib WEP crypto"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c deleted file mode 100644 index 469a69726c16..000000000000 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2004 Intel Corporation. All rights reserved. - * - * Portions of this file are based on the WEP enablement code provided by the - * Host AP project hostap-drivers v0.1.3 - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * Contact Information: - * James P. Ketrenos <ipw2100-admin@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include <linux/compiler.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <linux/uaccess.h> -#include <net/arp.h> -#include "rtllib.h" - -static inline int rtllib_networks_allocate(struct rtllib_device *ieee) -{ - if (ieee->networks) - return 0; - - ieee->networks = kcalloc(MAX_NETWORK_COUNT, - sizeof(struct rtllib_network), GFP_KERNEL); - if (!ieee->networks) - return -ENOMEM; - - return 0; -} - -static inline void rtllib_networks_free(struct rtllib_device *ieee) -{ - if (!ieee->networks) - return; - kfree(ieee->networks); - ieee->networks = NULL; -} - -static inline void rtllib_networks_initialize(struct rtllib_device *ieee) -{ - int i; - - INIT_LIST_HEAD(&ieee->network_free_list); - INIT_LIST_HEAD(&ieee->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, - &ieee->network_free_list); -} - -struct net_device *alloc_rtllib(int sizeof_priv) -{ - struct rtllib_device *ieee = NULL; - struct net_device *dev; - int i, err; - - pr_debug("rtllib: Initializing...\n"); - - dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv); - if (!dev) { - pr_err("Unable to allocate net_device.\n"); - return NULL; - } - ieee = (struct rtllib_device *)netdev_priv_rsl(dev); - ieee->dev = dev; - - err = rtllib_networks_allocate(ieee); - if (err) { - pr_err("Unable to allocate beacon storage: %d\n", err); - goto free_netdev; - } - rtllib_networks_initialize(ieee); - - /* Default fragmentation threshold is maximum payload size */ - ieee->fts = DEFAULT_FTS; - ieee->scan_age = DEFAULT_MAX_SCAN_AGE; - ieee->open_wep = 1; - - ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ - - ieee->rtllib_ap_sec_type = rtllib_ap_sec_type; - - spin_lock_init(&ieee->lock); - spin_lock_init(&ieee->wpax_suitlist_lock); - spin_lock_init(&ieee->reorder_spinlock); - atomic_set(&ieee->atm_swbw, 0); - - /* SAM FIXME */ - lib80211_crypt_info_init(&ieee->crypt_info, "RTLLIB", &ieee->lock); - - ieee->wpa_enabled = 0; - ieee->tkip_countermeasures = 0; - ieee->drop_unencrypted = 0; - ieee->privacy_invoked = 0; - ieee->ieee802_1x = 1; - ieee->hwsec_active = 0; - - memset(ieee->swcamtable, 0, sizeof(struct sw_cam_table) * 32); - err = rtllib_softmac_init(ieee); - if (err) - goto free_crypt_info; - - ieee->ht_info = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL); - if (!ieee->ht_info) - goto free_softmac; - - ht_update_default_setting(ieee); - ht_initialize_ht_info(ieee); - rtllib_ts_init(ieee); - for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } - - return dev; - -free_softmac: - rtllib_softmac_free(ieee); -free_crypt_info: - lib80211_crypt_info_free(&ieee->crypt_info); - rtllib_networks_free(ieee); -free_netdev: - free_netdev(dev); - - return NULL; -} -EXPORT_SYMBOL(alloc_rtllib); - -void free_rtllib(struct net_device *dev) -{ - struct rtllib_device *ieee = (struct rtllib_device *) - netdev_priv_rsl(dev); - - kfree(ieee->ht_info); - rtllib_softmac_free(ieee); - - lib80211_crypt_info_free(&ieee->crypt_info); - - rtllib_networks_free(ieee); - free_netdev(dev); -} -EXPORT_SYMBOL(free_rtllib); - -static int __init rtllib_init(void) -{ - return 0; -} - -static void __exit rtllib_exit(void) -{ -} - -module_init(rtllib_init); -module_exit(rtllib_exit); - -MODULE_DESCRIPTION("Support module for rtllib wireless devices"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c deleted file mode 100644 index 8fe224a83dd6..000000000000 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ /dev/null @@ -1,2564 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Original code based Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3 - hostap.o module, common routines - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * Copyright (c) 2004, Intel Corporation - * - * Few modifications for Realtek's Wi-Fi drivers by - * Andrea Merello <andrea.merello@gmail.com> - * - * A special thanks goes to Realtek for their support ! - */ -#include <linux/compiler.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <linux/uaccess.h> -#include <linux/ctype.h> - -#include "rtllib.h" - -static void rtllib_rx_mgt(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *stats); - -static inline void rtllib_monitor_rx(struct rtllib_device *ieee, - struct sk_buff *skb, - struct rtllib_rx_stats *rx_status, - size_t hdr_length) -{ - skb->dev = ieee->dev; - skb_reset_mac_header(skb); - skb_pull(skb, hdr_length); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - -/* Called only as a tasklet (software IRQ) */ -static struct rtllib_frag_entry * -rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, - unsigned int frag, u8 tid, u8 *src, u8 *dst) -{ - struct rtllib_frag_entry *entry; - int i; - - for (i = 0; i < RTLLIB_FRAG_CACHE_LEN; i++) { - entry = &ieee->frag_cache[tid][i]; - if (entry->skb && - time_after(jiffies, entry->first_frag_time + 2 * HZ)) { - netdev_dbg(ieee->dev, - "expiring fragment cache entry seq=%u last_frag=%u\n", - entry->seq, entry->last_frag); - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; - } - - if (entry->skb && entry->seq == seq && - (entry->last_frag + 1 == frag || frag == -1) && - memcmp(entry->src_addr, src, ETH_ALEN) == 0 && - memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) - return entry; - } - - return NULL; -} - -/* Called only as a tasklet (software IRQ) */ -static struct sk_buff * -rtllib_frag_cache_get(struct rtllib_device *ieee, - struct ieee80211_hdr *hdr) -{ - struct sk_buff *skb = NULL; - u16 fc = le16_to_cpu(hdr->frame_control); - u16 sc = le16_to_cpu(hdr->seq_ctrl); - unsigned int frag = WLAN_GET_SEQ_FRAG(sc); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct rtllib_frag_entry *entry; - struct ieee80211_qos_hdr *hdr_3addrqos; - struct ieee80211_qos_hdr_4addr *hdr_4addrqos; - u8 tid; - - if (ieee80211_has_a4(hdr->frame_control) && - RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_qos_hdr_4addr *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else if (RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_qos_hdr *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - if (frag == 0) { - /* Reserve enough space to fit maximum frame length */ - skb = dev_alloc_skb(ieee->dev->mtu + - sizeof(struct ieee80211_hdr) + - 8 /* LLC */ + - 2 /* alignment */ + - 8 /* WEP */ + - ETH_ALEN /* WDS */ + - /* QOS Control */ - (RTLLIB_QOS_HAS_SEQ(fc) ? 2 : 0)); - if (!skb) - return NULL; - - entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; - ieee->frag_next_idx[tid]++; - if (ieee->frag_next_idx[tid] >= RTLLIB_FRAG_CACHE_LEN) - ieee->frag_next_idx[tid] = 0; - - if (entry->skb) - dev_kfree_skb_any(entry->skb); - - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->last_frag = frag; - entry->skb = skb; - ether_addr_copy(entry->src_addr, hdr->addr2); - ether_addr_copy(entry->dst_addr, hdr->addr1); - } else { - /* received a fragment of a frame for which the head fragment - * should have already been received - */ - entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, - hdr->addr1); - if (entry) { - entry->last_frag = frag; - skb = entry->skb; - } - } - - return skb; -} - -/* Called only as a tasklet (software IRQ) */ -static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, - struct ieee80211_hdr *hdr) -{ - u16 fc = le16_to_cpu(hdr->frame_control); - u16 sc = le16_to_cpu(hdr->seq_ctrl); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct rtllib_frag_entry *entry; - struct ieee80211_qos_hdr *hdr_3addrqos; - struct ieee80211_qos_hdr_4addr *hdr_4addrqos; - u8 tid; - - if (ieee80211_has_a4(hdr->frame_control) && - RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_qos_hdr_4addr *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else if (RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_qos_hdr *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - entry = rtllib_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, - hdr->addr1); - - if (!entry) { - netdev_dbg(ieee->dev, - "Couldn't invalidate fragment cache entry (seq=%u)\n", - seq); - return -1; - } - - entry->skb = NULL; - return 0; -} - -/* rtllib_rx_frame_mgtmt - * - * Responsible for handling management control frames - * - * Called by rtllib_rx - */ -static inline int -rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, u16 type, u16 stype) -{ - /* On the struct stats definition there is written that - * this is not mandatory.... but seems that the probe - * response parser uses it - */ - struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)skb->data; - - rx_stats->len = skb->len; - rtllib_rx_mgt(ieee, skb, rx_stats); - if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) { - dev_kfree_skb_any(skb); - return 0; - } - rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype); - - dev_kfree_skb_any(skb); - - return 0; -} - -/* No encapsulation header if EtherType < 0x600 (=length) */ - -/* Called by rtllib_rx_frame_decrypt */ -static int rtllib_is_eapol_frame(struct rtllib_device *ieee, - struct sk_buff *skb, size_t hdrlen) -{ - struct net_device *dev = ieee->dev; - u16 fc, ethertype; - struct ieee80211_hdr *hdr; - u8 *pos; - - if (skb->len < 24) - return 0; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = le16_to_cpu(hdr->frame_control); - - /* check that the frame is unicast frame to us */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && - memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { - /* ToDS frame with own addr BSSID and DA */ - } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - /* FromDS frame with own addr as DA */ - } else { - return 0; - } - - if (skb->len < 24 + 8) - return 0; - - /* check for port access entity Ethernet type */ - pos = skb->data + hdrlen; - ethertype = (pos[6] << 8) | pos[7]; - if (ethertype == ETH_P_PAE) - return 1; - - return 0; -} - -/* Called only as a tasklet (software IRQ), by rtllib_rx */ -static inline int -rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, - struct lib80211_crypt_data *crypt) -{ - struct ieee80211_hdr *hdr; - int res, hdrlen; - - if (!crypt || !crypt->ops->decrypt_mpdu) - return 0; - - if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *) - (skb->cb + MAX_DEV_ADDR_SIZE); - - tcb_desc->hw_sec = 1; - - if (ieee->need_sw_enc) - tcb_desc->hw_sec = 0; - } - - hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_dbg(ieee->dev, "decryption failed (SA= %pM) res=%d\n", - hdr->addr2, res); - if (res == -2) - netdev_dbg(ieee->dev, - "Decryption failed ICV mismatch (key %d)\n", - skb->data[hdrlen + 3] >> 6); - return -1; - } - - return res; -} - -/* Called only as a tasklet (software IRQ), by rtllib_rx */ -static inline int -rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb, - int keyidx, struct lib80211_crypt_data *crypt) -{ - struct ieee80211_hdr *hdr; - int res, hdrlen; - - if (!crypt || !crypt->ops->decrypt_msdu) - return 0; - if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *) - (skb->cb + MAX_DEV_ADDR_SIZE); - - tcb_desc->hw_sec = 1; - - if (ieee->need_sw_enc) - tcb_desc->hw_sec = 0; - } - - hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_dbg(ieee->dev, - "MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n", - hdr->addr2, keyidx); - return -1; - } - - return 0; -} - -/* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5 * HZ) -static int is_duplicate_packet(struct rtllib_device *ieee, - struct ieee80211_hdr *header) -{ - u16 fc = le16_to_cpu(header->frame_control); - u16 sc = le16_to_cpu(header->seq_ctrl); - u16 seq = WLAN_GET_SEQ_SEQ(sc); - u16 frag = WLAN_GET_SEQ_FRAG(sc); - u16 *last_seq, *last_frag; - unsigned long *last_time; - struct ieee80211_qos_hdr *hdr_3addrqos; - struct ieee80211_qos_hdr_4addr *hdr_4addrqos; - u8 tid; - - if (ieee80211_has_a4(header->frame_control) && - RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_qos_hdr_4addr *)header; - tid = le16_to_cpu(hdr_4addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else if (RTLLIB_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_qos_hdr *)header; - tid = le16_to_cpu(hdr_3addrqos->qos_ctrl) & RTLLIB_QCTL_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - switch (ieee->iw_mode) { - case IW_MODE_INFRA: - last_seq = &ieee->last_rxseq_num[tid]; - last_frag = &ieee->last_rxfrag_num[tid]; - last_time = &ieee->last_packet_time[tid]; - break; - default: - return 0; - } - - if ((*last_seq == seq) && - time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) - goto drop; - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - goto drop; - } else { - *last_seq = seq; - } - - *last_frag = frag; - *last_time = jiffies; - return 0; - -drop: - - return 1; -} - -static bool add_reorder_entry(struct rx_ts_record *ts, - struct rx_reorder_entry *reorder_entry) -{ - struct list_head *list = &ts->rx_pending_pkt_list; - - while (list->next != &ts->rx_pending_pkt_list) { - if (SN_LESS(reorder_entry->seq_num, ((struct rx_reorder_entry *) - list_entry(list->next, struct rx_reorder_entry, - list))->seq_num)) - list = list->next; - else if (SN_EQUAL(reorder_entry->seq_num, - ((struct rx_reorder_entry *)list_entry(list->next, - struct rx_reorder_entry, list))->seq_num)) - return false; - else - break; - } - reorder_entry->list.next = list->next; - reorder_entry->list.next->prev = &reorder_entry->list; - reorder_entry->list.prev = list; - list->next = &reorder_entry->list; - - return true; -} - -void rtllib_indicate_packets(struct rtllib_device *ieee, - struct rtllib_rxb **prxb_indicate_array, u8 index) -{ - struct net_device_stats *stats = &ieee->stats; - u8 i = 0, j = 0; - u16 ethertype; - - for (j = 0; j < index; j++) { - struct rtllib_rxb *prxb = prxb_indicate_array[j]; - - for (i = 0; i < prxb->nr_subframes; i++) { - struct sk_buff *sub_skb = prxb->subframes[i]; - - /* convert hdr + possible LLC headers into Ethernet header */ - ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; - if (sub_skb->len >= 8 && - ((memcmp(sub_skb->data, rfc1042_header, - SNAP_SIZE) == 0 && - ethertype != ETH_P_AARP && - ethertype != ETH_P_IPX) || - memcmp(sub_skb->data, bridge_tunnel_header, - SNAP_SIZE) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation - * and replace EtherType - */ - skb_pull(sub_skb, SNAP_SIZE); - memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); - } else { - u16 len; - /* Leave Ethernet header part of hdr and full payload */ - len = sub_skb->len; - memcpy(skb_push(sub_skb, 2), &len, 2); - memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); - } - - /* Indicate the packets to upper layer */ - if (sub_skb) { - stats->rx_packets++; - stats->rx_bytes += sub_skb->len; - - memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); - sub_skb->protocol = eth_type_trans(sub_skb, - ieee->dev); - sub_skb->dev = ieee->dev; - sub_skb->dev->stats.rx_packets++; - sub_skb->dev->stats.rx_bytes += sub_skb->len; - /* 802.11 crc not sufficient */ - sub_skb->ip_summed = CHECKSUM_NONE; - ieee->last_rx_ps_time = jiffies; - netif_rx(sub_skb); - } - } - kfree(prxb); - prxb = NULL; - } -} - -void rtllib_flush_rx_ts_pending_pkts(struct rtllib_device *ieee, - struct rx_ts_record *ts) -{ - struct rx_reorder_entry *pRxReorderEntry; - u8 rfd_cnt = 0; - - del_timer_sync(&ts->rx_pkt_pending_timer); - while (!list_empty(&ts->rx_pending_pkt_list)) { - if (rfd_cnt >= REORDER_WIN_SIZE) { - netdev_info(ieee->dev, - "-------------->%s() error! rfd_cnt >= REORDER_WIN_SIZE\n", - __func__); - break; - } - - pRxReorderEntry = (struct rx_reorder_entry *) - list_entry(ts->rx_pending_pkt_list.prev, - struct rx_reorder_entry, list); - netdev_dbg(ieee->dev, "%s(): Indicate seq_num %d!\n", __func__, - pRxReorderEntry->seq_num); - list_del_init(&pRxReorderEntry->list); - - ieee->rfd_array[rfd_cnt] = pRxReorderEntry->prxb; - - rfd_cnt = rfd_cnt + 1; - list_add_tail(&pRxReorderEntry->list, - &ieee->RxReorder_Unused_List); - } - rtllib_indicate_packets(ieee, ieee->rfd_array, rfd_cnt); - - ts->rx_indicate_seq = 0xffff; -} - -static void rx_reorder_indicate_packet(struct rtllib_device *ieee, - struct rtllib_rxb *prxb, - struct rx_ts_record *ts, u16 seq_num) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - struct rx_reorder_entry *reorder_entry = NULL; - u8 win_size = ht_info->rx_reorder_win_size; - u16 win_end = 0; - u8 index = 0; - bool match_win_start = false, pkt_in_buf = false; - unsigned long flags; - - netdev_dbg(ieee->dev, - "%s(): Seq is %d, ts->rx_indicate_seq is %d, win_size is %d\n", - __func__, seq_num, ts->rx_indicate_seq, win_size); - - spin_lock_irqsave(&(ieee->reorder_spinlock), flags); - - win_end = (ts->rx_indicate_seq + win_size - 1) % 4096; - /* Rx Reorder initialize condition.*/ - if (ts->rx_indicate_seq == 0xffff) - ts->rx_indicate_seq = seq_num; - - /* Drop out the packet which seq_num is smaller than WinStart */ - if (SN_LESS(seq_num, ts->rx_indicate_seq)) { - netdev_dbg(ieee->dev, - "Packet Drop! IndicateSeq: %d, NewSeq: %d\n", - ts->rx_indicate_seq, seq_num); - ht_info->rx_reorder_drop_counter++; - { - int i; - - for (i = 0; i < prxb->nr_subframes; i++) - dev_kfree_skb(prxb->subframes[i]); - kfree(prxb); - prxb = NULL; - } - spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); - return; - } - - /* Sliding window manipulation. Conditions includes: - * 1. Incoming seq_num is equal to WinStart =>Window shift 1 - * 2. Incoming seq_num is larger than the win_end => Window shift N - */ - if (SN_EQUAL(seq_num, ts->rx_indicate_seq)) { - ts->rx_indicate_seq = (ts->rx_indicate_seq + 1) % 4096; - match_win_start = true; - } else if (SN_LESS(win_end, seq_num)) { - if (seq_num >= (win_size - 1)) - ts->rx_indicate_seq = seq_num + 1 - win_size; - else - ts->rx_indicate_seq = 4095 - - (win_size - (seq_num + 1)) + 1; - netdev_dbg(ieee->dev, - "Window Shift! IndicateSeq: %d, NewSeq: %d\n", - ts->rx_indicate_seq, seq_num); - } - - /* Indication process. - * After Packet dropping and Sliding Window shifting as above, we can - * now just indicate the packets with the seq_num smaller than latest - * WinStart and struct buffer other packets. - * - * For Rx Reorder condition: - * 1. All packets with seq_num smaller than WinStart => Indicate - * 2. All packets with seq_num larger than or equal to - * WinStart => Buffer it. - */ - if (match_win_start) { - /* Current packet is going to be indicated.*/ - netdev_dbg(ieee->dev, - "Packets indication! IndicateSeq: %d, NewSeq: %d\n", - ts->rx_indicate_seq, seq_num); - ieee->prxb_indicate_array[0] = prxb; - index = 1; - } else { - /* Current packet is going to be inserted into pending list.*/ - if (!list_empty(&ieee->RxReorder_Unused_List)) { - reorder_entry = (struct rx_reorder_entry *) - list_entry(ieee->RxReorder_Unused_List.next, - struct rx_reorder_entry, list); - list_del_init(&reorder_entry->list); - - /* Make a reorder entry and insert - * into a the packet list. - */ - reorder_entry->seq_num = seq_num; - reorder_entry->prxb = prxb; - - if (!add_reorder_entry(ts, reorder_entry)) { - int i; - - netdev_dbg(ieee->dev, - "%s(): Duplicate packet is dropped. IndicateSeq: %d, NewSeq: %d\n", - __func__, ts->rx_indicate_seq, - seq_num); - list_add_tail(&reorder_entry->list, - &ieee->RxReorder_Unused_List); - - for (i = 0; i < prxb->nr_subframes; i++) - dev_kfree_skb(prxb->subframes[i]); - kfree(prxb); - prxb = NULL; - } else { - netdev_dbg(ieee->dev, - "Pkt insert into struct buffer. IndicateSeq: %d, NewSeq: %d\n", - ts->rx_indicate_seq, seq_num); - } - } else { - /* Packets are dropped if there are not enough reorder - * entries. This part should be modified!! We can just - * indicate all the packets in struct buffer and get - * reorder entries. - */ - netdev_err(ieee->dev, - "%s(): There is no reorder entry! Packet is dropped!\n", - __func__); - { - int i; - - for (i = 0; i < prxb->nr_subframes; i++) - dev_kfree_skb(prxb->subframes[i]); - kfree(prxb); - prxb = NULL; - } - } - } - - /* Check if there is any packet need indicate.*/ - while (!list_empty(&ts->rx_pending_pkt_list)) { - netdev_dbg(ieee->dev, "%s(): start RREORDER indicate\n", - __func__); - - reorder_entry = (struct rx_reorder_entry *) - list_entry(ts->rx_pending_pkt_list.prev, - struct rx_reorder_entry, - list); - if (SN_LESS(reorder_entry->seq_num, ts->rx_indicate_seq) || - SN_EQUAL(reorder_entry->seq_num, ts->rx_indicate_seq)) { - /* This protect struct buffer from overflow. */ - if (index >= REORDER_WIN_SIZE) { - netdev_err(ieee->dev, - "%s(): Buffer overflow!\n", - __func__); - pkt_in_buf = true; - break; - } - - list_del_init(&reorder_entry->list); - - if (SN_EQUAL(reorder_entry->seq_num, ts->rx_indicate_seq)) - ts->rx_indicate_seq = (ts->rx_indicate_seq + 1) % - 4096; - - ieee->prxb_indicate_array[index] = reorder_entry->prxb; - netdev_dbg(ieee->dev, "%s(): Indicate seq_num %d!\n", - __func__, reorder_entry->seq_num); - index++; - - list_add_tail(&reorder_entry->list, - &ieee->RxReorder_Unused_List); - } else { - pkt_in_buf = true; - break; - } - } - - /* Handling pending timer. Set this timer to prevent from long time - * Rx buffering. - */ - if (index > 0) { - spin_unlock_irqrestore(&ieee->reorder_spinlock, flags); - if (timer_pending(&ts->rx_pkt_pending_timer)) - del_timer_sync(&ts->rx_pkt_pending_timer); - spin_lock_irqsave(&ieee->reorder_spinlock, flags); - ts->rx_timeout_indicate_seq = 0xffff; - - if (index > REORDER_WIN_SIZE) { - netdev_err(ieee->dev, - "%s(): Rx Reorder struct buffer full!\n", - __func__); - spin_unlock_irqrestore(&(ieee->reorder_spinlock), - flags); - return; - } - rtllib_indicate_packets(ieee, ieee->prxb_indicate_array, index); - pkt_in_buf = false; - } - - if (pkt_in_buf && ts->rx_timeout_indicate_seq == 0xffff) { - netdev_dbg(ieee->dev, "%s(): SET rx timeout timer\n", __func__); - ts->rx_timeout_indicate_seq = ts->rx_indicate_seq; - spin_unlock_irqrestore(&ieee->reorder_spinlock, flags); - mod_timer(&ts->rx_pkt_pending_timer, jiffies + - msecs_to_jiffies(ht_info->rx_reorder_pending_time)); - spin_lock_irqsave(&ieee->reorder_spinlock, flags); - } - spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); -} - -static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, - struct rtllib_rxb *rxb, u8 *src, u8 *dst) -{ - struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - - u16 llc_offset = sizeof(struct ieee80211_hdr_3addr); - bool is_aggregate_frame = false; - u16 subframe_len; - u8 pad_len = 0; - u16 seq_num = 0; - struct sk_buff *sub_skb; - /* just for debug purpose */ - seq_num = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctrl)); - if ((RTLLIB_QOS_HAS_SEQ(fc)) && - (((union frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved)) - is_aggregate_frame = true; - - if (RTLLIB_QOS_HAS_SEQ(fc)) - llc_offset += 2; - if (rx_stats->contain_htc) - llc_offset += sHTCLng; - - if (skb->len <= llc_offset) - return 0; - - skb_pull(skb, llc_offset); - ieee->is_aggregate_frame = is_aggregate_frame; - if (!is_aggregate_frame) { - rxb->nr_subframes = 1; - - /* altered by clark 3/30/2010 - * The struct buffer size of the skb indicated to upper layer - * must be less than 5000, or the defraged IP datagram - * in the IP layer will exceed "ipfrag_high_tresh" and be - * discarded. so there must not use the function - * "skb_copy" and "skb_clone" for "skb". - */ - - /* Allocate new skb for releasing to upper layer */ - sub_skb = dev_alloc_skb(RTLLIB_SKBBUFFER_SIZE); - if (!sub_skb) - return 0; - skb_reserve(sub_skb, 12); - skb_put_data(sub_skb, skb->data, skb->len); - sub_skb->dev = ieee->dev; - - rxb->subframes[0] = sub_skb; - - memcpy(rxb->src, src, ETH_ALEN); - memcpy(rxb->dst, dst, ETH_ALEN); - rxb->subframes[0]->dev = ieee->dev; - return 1; - } - - rxb->nr_subframes = 0; - memcpy(rxb->src, src, ETH_ALEN); - memcpy(rxb->dst, dst, ETH_ALEN); - while (skb->len > ETHERNET_HEADER_SIZE) { - /* Offset 12 denote 2 mac address */ - subframe_len = *((u16 *)(skb->data + 12)); - subframe_len = (subframe_len >> 8) + - (subframe_len << 8); - - if (skb->len < (ETHERNET_HEADER_SIZE + subframe_len)) { - netdev_info(ieee->dev, - "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n", - __func__, rxb->nr_subframes); - netdev_info(ieee->dev, - "%s: A-MSDU parse error!! Subframe Length: %d\n", - __func__, subframe_len); - netdev_info(ieee->dev, - "nRemain_Length is %d and subframe_len is : %d\n", - skb->len, subframe_len); - netdev_info(ieee->dev, - "The Packet seq_num is %d\n", - seq_num); - return 0; - } - - /* move the data point to data content */ - skb_pull(skb, ETHERNET_HEADER_SIZE); - - /* altered by clark 3/30/2010 - * The struct buffer size of the skb indicated to upper layer - * must be less than 5000, or the defraged IP datagram - * in the IP layer will exceed "ipfrag_high_tresh" and be - * discarded. so there must not use the function - * "skb_copy" and "skb_clone" for "skb". - */ - - /* Allocate new skb for releasing to upper layer */ - sub_skb = dev_alloc_skb(subframe_len + 12); - if (!sub_skb) - return 0; - skb_reserve(sub_skb, 12); - skb_put_data(sub_skb, skb->data, subframe_len); - - sub_skb->dev = ieee->dev; - rxb->subframes[rxb->nr_subframes++] = sub_skb; - if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { - netdev_dbg(ieee->dev, - "ParseSubframe(): Too many Subframes! Packets dropped!\n"); - break; - } - skb_pull(skb, subframe_len); - - if (skb->len != 0) { - pad_len = 4 - ((subframe_len + - ETHERNET_HEADER_SIZE) % 4); - if (pad_len == 4) - pad_len = 0; - - if (skb->len < pad_len) - return 0; - - skb_pull(skb, pad_len); - } - } - - return rxb->nr_subframes; -} - -static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee, - struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - size_t hdrlen; - - hdrlen = rtllib_get_hdrlen(fc); - if (ht_c_check(ieee, skb->data)) { - if (net_ratelimit()) - netdev_info(ieee->dev, "%s: find HTCControl!\n", - __func__); - hdrlen += 4; - rx_stats->contain_htc = true; - } - - return hdrlen; -} - -static int rtllib_rx_check_duplicate(struct rtllib_device *ieee, - struct sk_buff *skb, u8 multicast) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc, sc; - u8 frag; - - fc = le16_to_cpu(hdr->frame_control); - sc = le16_to_cpu(hdr->seq_ctrl); - frag = WLAN_GET_SEQ_FRAG(sc); - - if (!ieee->ht_info->cur_rx_reorder_enable || - !ieee->current_network.qos_data.active || - !is_data_frame(skb->data) || - is_legacy_data_frame(skb->data)) { - if (!ieee80211_is_beacon(hdr->frame_control)) { - if (is_duplicate_packet(ieee, hdr)) - return -1; - } - } else { - struct rx_ts_record *ts = NULL; - - if (rtllib_get_ts(ieee, (struct ts_common_info **)&ts, hdr->addr2, - (u8)frame_qos_tid((u8 *)(skb->data)), RX_DIR, true)) { - if ((fc & (1 << 11)) && (frag == ts->rx_last_frag_num) && - (WLAN_GET_SEQ_SEQ(sc) == ts->rx_last_seq_num)) - return -1; - ts->rx_last_frag_num = frag; - ts->rx_last_seq_num = WLAN_GET_SEQ_SEQ(sc); - } else { - netdev_warn(ieee->dev, "%s(): No TS! Skip the check!\n", - __func__); - return -1; - } - } - - return 0; -} - -static void rtllib_rx_extract_addr(struct rtllib_device *ieee, - struct ieee80211_hdr *hdr, u8 *dst, - u8 *src, u8 *bssid) -{ - u16 fc = le16_to_cpu(hdr->frame_control); - - switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_FROMDS: - ether_addr_copy(dst, hdr->addr1); - ether_addr_copy(src, hdr->addr3); - ether_addr_copy(bssid, hdr->addr2); - break; - case IEEE80211_FCTL_TODS: - ether_addr_copy(dst, hdr->addr3); - ether_addr_copy(src, hdr->addr2); - ether_addr_copy(bssid, hdr->addr1); - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - ether_addr_copy(dst, hdr->addr3); - ether_addr_copy(src, hdr->addr4); - ether_addr_copy(bssid, ieee->current_network.bssid); - break; - default: - ether_addr_copy(dst, hdr->addr1); - ether_addr_copy(src, hdr->addr2); - ether_addr_copy(bssid, hdr->addr3); - break; - } -} - -static int rtllib_rx_data_filter(struct rtllib_device *ieee, struct ieee80211_hdr *hdr, - u8 *dst, u8 *src, u8 *bssid, u8 *addr2) -{ - u16 fc = le16_to_cpu(hdr->frame_control); - u8 type = WLAN_FC_GET_TYPE(fc); - u8 stype = WLAN_FC_GET_STYPE(fc); - - /* Filter frames from different BSS */ - if (ieee80211_has_a4(hdr->frame_control) && - !ether_addr_equal(ieee->current_network.bssid, bssid) && - !is_zero_ether_addr(ieee->current_network.bssid)) { - return -1; - } - - /* Nullfunc frames may have PS-bit set, so they must be passed to - * hostap_handle_sta_rx() before being dropped here. - */ - if (stype != IEEE80211_STYPE_DATA && - stype != IEEE80211_STYPE_DATA_CFACK && - stype != IEEE80211_STYPE_DATA_CFPOLL && - stype != IEEE80211_STYPE_DATA_CFACKPOLL && - stype != IEEE80211_STYPE_QOS_DATA) { - if (stype != IEEE80211_STYPE_NULLFUNC) - netdev_dbg(ieee->dev, - "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n", - type, stype); - return -1; - } - - /* packets from our adapter are dropped (echo) */ - if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN)) - return -1; - - /* {broad,multi}cast packets to our BSS go through */ - if (is_multicast_ether_addr(dst)) { - if (memcmp(bssid, ieee->current_network.bssid, - ETH_ALEN)) - return -1; - } - return 0; -} - -static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb, - struct lib80211_crypt_data **crypt, size_t hdrlen) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - int idx = 0; - - if (skb->len >= hdrlen + 3) - idx = skb->data[hdrlen + 3] >> 6; - - *crypt = ieee->crypt_info.crypt[idx]; - /* allow NULL decrypt to indicate an station specific override - * for default encryption - */ - if (*crypt && (!(*crypt)->ops || !(*crypt)->ops->decrypt_mpdu)) - *crypt = NULL; - - if (!*crypt && (fc & IEEE80211_FCTL_PROTECTED)) { - /* This seems to be triggered by some (multicast?) - * frames from other than current BSS, so just drop the - * frames silently instead of filling system log with - * these reports. - */ - netdev_dbg(ieee->dev, - "Decryption failed (not set) (SA= %pM)\n", - hdr->addr2); - return -1; - } - - return 0; -} - -static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, - struct lib80211_crypt_data *crypt, size_t hdrlen) -{ - struct ieee80211_hdr *hdr; - int keyidx = 0; - u16 fc, sc; - u8 frag; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = le16_to_cpu(hdr->frame_control); - sc = le16_to_cpu(hdr->seq_ctrl); - frag = WLAN_GET_SEQ_FRAG(sc); - - if ((!rx_stats->decrypted)) - ieee->need_sw_enc = 1; - else - ieee->need_sw_enc = 0; - - keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt); - if ((fc & IEEE80211_FCTL_PROTECTED) && (keyidx < 0)) { - netdev_info(ieee->dev, "%s: decrypt frame error\n", __func__); - return -1; - } - - hdr = (struct ieee80211_hdr *)skb->data; - if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { - int flen; - struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr); - - netdev_dbg(ieee->dev, "Rx Fragment received (%u)\n", frag); - - if (!frag_skb) { - netdev_dbg(ieee->dev, - "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n", - (fc & IEEE80211_FCTL_MOREFRAGS) != 0, - WLAN_GET_SEQ_SEQ(sc), frag); - return -1; - } - flen = skb->len; - if (frag != 0) - flen -= hdrlen; - - if (frag_skb->tail + flen > frag_skb->end) { - netdev_warn(ieee->dev, - "%s: host decrypted and reassembled frame did not fit skb\n", - __func__); - rtllib_frag_cache_invalidate(ieee, hdr); - return -1; - } - - if (frag == 0) { - /* copy first fragment (including full headers) into - * beginning of the fragment cache skb - */ - skb_put_data(frag_skb, skb->data, flen); - } else { - /* append frame payload to the end of the fragment - * cache skb - */ - skb_put_data(frag_skb, skb->data + hdrlen, flen); - } - dev_kfree_skb_any(skb); - skb = NULL; - - if (fc & IEEE80211_FCTL_MOREFRAGS) { - /* more fragments expected - leave the skb in fragment - * cache for now; it will be delivered to upper layers - * after all fragments have been received - */ - return -2; - } - - /* this was the last fragment and the frame will be - * delivered, so remove skb from fragment cache - */ - skb = frag_skb; - hdr = (struct ieee80211_hdr *)skb->data; - rtllib_frag_cache_invalidate(ieee, hdr); - } - - /* skb: hdr + (possible reassembled) full MSDU payload; possibly still - * encrypted/authenticated - */ - if ((fc & IEEE80211_FCTL_PROTECTED) && - rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) { - netdev_info(ieee->dev, "%s: ==>decrypt msdu error\n", __func__); - return -1; - } - - hdr = (struct ieee80211_hdr *)skb->data; - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) { - if (/*ieee->ieee802_1x &&*/ - rtllib_is_eapol_frame(ieee, skb, hdrlen)) { - /* pass unencrypted EAPOL frames even if encryption is - * configured - */ - struct eapol *eap = (struct eapol *)(skb->data + - 24); - netdev_dbg(ieee->dev, - "RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); - } else { - netdev_dbg(ieee->dev, - "encryption configured, but RX frame not encrypted (SA= %pM)\n", - hdr->addr2); - return -1; - } - } - - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && - rtllib_is_eapol_frame(ieee, skb, hdrlen)) { - struct eapol *eap = (struct eapol *)(skb->data + 24); - - netdev_dbg(ieee->dev, "RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); - } - - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep && - !rtllib_is_eapol_frame(ieee, skb, hdrlen)) { - netdev_dbg(ieee->dev, - "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n", - hdr->addr2); - return -1; - } - - return 0; -} - -static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, - u8 nr_subframes) -{ - if (unicast) { - if (ieee->link_state == MAC80211_LINKED) { - if (((ieee->link_detect_info.num_rx_unicast_ok_in_period + - ieee->link_detect_info.num_tx_ok_in_period) > 8) || - (ieee->link_detect_info.num_rx_unicast_ok_in_period > 2)) { - ieee->leisure_ps_leave(ieee->dev); - } - } - } - ieee->last_rx_ps_time = jiffies; -} - -static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee, - struct rtllib_rx_stats *rx_stats, - struct rtllib_rxb *rxb, - u8 *dst, - u8 *src) -{ - struct net_device *dev = ieee->dev; - u16 ethertype; - int i = 0; - - if (!rxb) { - netdev_info(dev, "%s: rxb is NULL!!\n", __func__); - return; - } - - for (i = 0; i < rxb->nr_subframes; i++) { - struct sk_buff *sub_skb = rxb->subframes[i]; - - if (sub_skb) { - /* convert hdr + possible LLC headers - * into Ethernet header - */ - ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; - if (sub_skb->len >= 8 && - ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation - * and replace EtherType - */ - skb_pull(sub_skb, SNAP_SIZE); - ether_addr_copy(skb_push(sub_skb, ETH_ALEN), - src); - ether_addr_copy(skb_push(sub_skb, ETH_ALEN), - dst); - } else { - u16 len; - /* Leave Ethernet header part of hdr - * and full payload - */ - len = sub_skb->len; - memcpy(skb_push(sub_skb, 2), &len, 2); - ether_addr_copy(skb_push(sub_skb, ETH_ALEN), - src); - ether_addr_copy(skb_push(sub_skb, ETH_ALEN), - dst); - } - - ieee->stats.rx_packets++; - ieee->stats.rx_bytes += sub_skb->len; - - if (is_multicast_ether_addr(dst)) - ieee->stats.multicast++; - - /* Indicate the packets to upper layer */ - memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); - sub_skb->protocol = eth_type_trans(sub_skb, dev); - sub_skb->dev = dev; - sub_skb->dev->stats.rx_packets++; - sub_skb->dev->stats.rx_bytes += sub_skb->len; - /* 802.11 crc not sufficient */ - sub_skb->ip_summed = CHECKSUM_NONE; - netif_rx(sub_skb); - } - } - kfree(rxb); -} - -static int rtllib_rx_infra_adhoc(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - struct net_device *dev = ieee->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct lib80211_crypt_data *crypt = NULL; - struct rtllib_rxb *rxb = NULL; - struct rx_ts_record *ts = NULL; - u16 fc, sc, seq_num = 0; - u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 bssid[ETH_ALEN] = {0}; - - size_t hdrlen = 0; - int ret = 0, i = 0; - - fc = le16_to_cpu(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - sc = le16_to_cpu(hdr->seq_ctrl); - - /*Filter pkt not to me*/ - multicast = is_multicast_ether_addr(hdr->addr1); - unicast = !multicast; - if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) - goto rx_dropped; - - /*Filter pkt has too small length */ - hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats); - if (skb->len < hdrlen) { - netdev_info(dev, - "%s():ERR!!! skb->len is smaller than hdrlen\n", - __func__); - goto rx_dropped; - } - - /* Filter Duplicate pkt */ - ret = rtllib_rx_check_duplicate(ieee, skb, multicast); - if (ret < 0) - goto rx_dropped; - - /* Filter CTRL Frame */ - if (type == RTLLIB_FTYPE_CTL) - goto rx_dropped; - - /* Filter MGNT Frame */ - if (type == RTLLIB_FTYPE_MGMT) { - if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) - goto rx_dropped; - else - goto rx_exit; - } - - /* Filter WAPI DATA Frame */ - - /* Update statstics for AP roaming */ - ieee->link_detect_info.num_recv_data_in_period++; - ieee->link_detect_info.num_rx_ok_in_period++; - - /* Data frame - extract src/dst addresses */ - rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid); - - /* Filter Data frames */ - ret = rtllib_rx_data_filter(ieee, hdr, dst, src, bssid, hdr->addr2); - if (ret < 0) - goto rx_dropped; - - if (skb->len == hdrlen) - goto rx_dropped; - - /* Send pspoll based on moredata */ - if ((ieee->iw_mode == IW_MODE_INFRA) && - (ieee->sta_sleep == LPS_IS_SLEEP) && - (ieee->polling)) { - if (WLAN_FC_MORE_DATA(fc)) { - /* more data bit is set, let's request a new frame - * from the AP - */ - rtllib_sta_ps_send_pspoll_frame(ieee); - } else { - ieee->polling = false; - } - } - - /* Get crypt if encrypted */ - ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen); - if (ret == -1) - goto rx_dropped; - - /* Decrypt data frame (including reassemble) */ - ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen); - if (ret == -1) - goto rx_dropped; - else if (ret == -2) - goto rx_exit; - - /* Get TS for Rx Reorder */ - hdr = (struct ieee80211_hdr *)skb->data; - if (ieee->current_network.qos_data.active && is_qos_data_frame(skb->data) - && !is_multicast_ether_addr(hdr->addr1)) { - TID = frame_qos_tid(skb->data); - seq_num = WLAN_GET_SEQ_SEQ(sc); - rtllib_get_ts(ieee, (struct ts_common_info **)&ts, hdr->addr2, TID, - RX_DIR, true); - if (TID != 0 && TID != 3) - ieee->bis_any_nonbepkts = true; - } - - /* Parse rx data frame (For AMSDU) */ - /* skb: hdr + (possible reassembled) full plaintext payload */ - rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC); - if (!rxb) - goto rx_dropped; - - /* to parse amsdu packets */ - /* qos data packets & reserved bit is 1 */ - if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) { - /* only to free rxb, and not submit the packets - * to upper layer - */ - for (i = 0; i < rxb->nr_subframes; i++) - dev_kfree_skb(rxb->subframes[i]); - kfree(rxb); - rxb = NULL; - goto rx_dropped; - } - - /* Update WAPI PN */ - - /* Check if leave LPS */ - if (ieee->is_aggregate_frame) - nr_subframes = rxb->nr_subframes; - else - nr_subframes = 1; - if (unicast) - ieee->link_detect_info.num_rx_unicast_ok_in_period += nr_subframes; - rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes); - - /* Indicate packets to upper layer or Rx Reorder */ - if (!ieee->ht_info->cur_rx_reorder_enable || !ts) - rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src); - else - rx_reorder_indicate_packet(ieee, rxb, ts, seq_num); - - dev_kfree_skb(skb); - - rx_exit: - return 1; - - rx_dropped: - ieee->stats.rx_dropped++; - - /* Returning 0 indicates to caller that we have not handled the SKB-- - * so it is still allocated and can be used again by underlying - * hardware as a DMA target - */ - return 0; -} - -static int rtllib_rx_monitor(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - size_t hdrlen = rtllib_get_hdrlen(fc); - - if (skb->len < hdrlen) { - netdev_info(ieee->dev, - "%s():ERR!!! skb->len is smaller than hdrlen\n", - __func__); - return 0; - } - - if (ht_c_check(ieee, skb->data)) { - if (net_ratelimit()) - netdev_info(ieee->dev, "%s: Find HTCControl!\n", - __func__); - hdrlen += 4; - } - - ieee->stats.rx_packets++; - ieee->stats.rx_bytes += skb->len; - rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); - - return 1; -} - -/* All received frames are sent to this function. @skb contains the frame in - * IEEE 802.11 format, i.e., in the format it was sent over air. - * This function is called only as a tasklet (software IRQ). - */ -int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - int ret = 0; - - if (!ieee || !skb || !rx_stats) { - pr_info("%s: Input parameters NULL!\n", __func__); - goto rx_dropped; - } - if (skb->len < 10) { - netdev_info(ieee->dev, "%s: SKB length < 10\n", __func__); - goto rx_dropped; - } - - switch (ieee->iw_mode) { - case IW_MODE_INFRA: - ret = rtllib_rx_infra_adhoc(ieee, skb, rx_stats); - break; - case IW_MODE_MONITOR: - ret = rtllib_rx_monitor(ieee, skb, rx_stats); - break; - default: - netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__); - break; - } - - return ret; - - rx_dropped: - if (ieee) - ieee->stats.rx_dropped++; - return 0; -} -EXPORT_SYMBOL(rtllib_rx); - -static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; - -/* Make ther structure we read from the beacon packet has the right values */ -static int rtllib_verify_qos_info(struct rtllib_qos_information_element - *info_element, int sub_type) -{ - if (info_element->element_id != QOS_ELEMENT_ID) - return -1; - if (info_element->qui_subtype != sub_type) - return -1; - if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) - return -1; - if (info_element->qui_type != QOS_OUI_TYPE) - return -1; - if (info_element->version != QOS_VERSION_1) - return -1; - - return 0; -} - -/* Parse a QoS parameter element */ -static int rtllib_read_qos_param_element( - struct rtllib_qos_parameter_info *element_param, - struct rtllib_info_element *info_element) -{ - size_t size = sizeof(*element_param); - - if (!element_param || !info_element || info_element->len != size - 2) - return -1; - - memcpy(element_param, info_element, size); - return rtllib_verify_qos_info(&element_param->info_element, - QOS_OUI_PARAM_SUB_TYPE); -} - -/* Parse a QoS information element */ -static int rtllib_read_qos_info_element( - struct rtllib_qos_information_element *element_info, - struct rtllib_info_element *info_element) -{ - size_t size = sizeof(*element_info); - - if (!element_info || !info_element || info_element->len != size - 2) - return -1; - - memcpy(element_info, info_element, size); - return rtllib_verify_qos_info(element_info, QOS_OUI_INFO_SUB_TYPE); -} - -/* Write QoS parameters from the ac parameters. */ -static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm, - struct rtllib_qos_data *qos_data) -{ - struct rtllib_qos_ac_parameter *ac_params; - struct rtllib_qos_parameters *qos_param = &(qos_data->parameters); - int i; - u8 aci; - u8 acm; - - qos_data->wmm_acm = 0; - for (i = 0; i < QOS_QUEUE_NUM; i++) { - ac_params = &(param_elm->ac_params_record[i]); - - aci = (ac_params->aci_aifsn & 0x60) >> 5; - acm = (ac_params->aci_aifsn & 0x10) >> 4; - - if (aci >= QOS_QUEUE_NUM) - continue; - switch (aci) { - case 1: - /* BIT(0) | BIT(3) */ - if (acm) - qos_data->wmm_acm |= (0x01 << 0) | (0x01 << 3); - break; - case 2: - /* BIT(4) | BIT(5) */ - if (acm) - qos_data->wmm_acm |= (0x01 << 4) | (0x01 << 5); - break; - case 3: - /* BIT(6) | BIT(7) */ - if (acm) - qos_data->wmm_acm |= (0x01 << 6) | (0x01 << 7); - break; - case 0: - default: - /* BIT(1) | BIT(2) */ - if (acm) - qos_data->wmm_acm |= (0x01 << 1) | (0x01 << 2); - break; - } - - qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; - - /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ - qos_param->aifs[aci] = max_t(u8, qos_param->aifs[aci], 2); - - qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & - 0x0F); - - qos_param->cw_max[aci] = cpu_to_le16((ac_params->ecw_min_max & - 0xF0) >> 4); - - qos_param->flag[aci] = - (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; - qos_param->tx_op_limit[aci] = ac_params->tx_op_limit; - } - return 0; -} - -/* we have a generic data element which it may contain QoS information or - * parameters element. check the information element length to decide - * which type to read - */ -static int rtllib_parse_qos_info_param_IE(struct rtllib_device *ieee, - struct rtllib_info_element - *info_element, - struct rtllib_network *network) -{ - int rc = 0; - struct rtllib_qos_information_element qos_info_element; - - rc = rtllib_read_qos_info_element(&qos_info_element, info_element); - - if (rc == 0) { - network->qos_data.param_count = qos_info_element.ac_info & 0x0F; - network->flags |= NETWORK_HAS_QOS_INFORMATION; - } else { - struct rtllib_qos_parameter_info param_element; - - rc = rtllib_read_qos_param_element(¶m_element, - info_element); - if (rc == 0) { - rtllib_qos_convert_ac_to_parameters(¶m_element, - &(network->qos_data)); - network->flags |= NETWORK_HAS_QOS_PARAMETERS; - network->qos_data.param_count = - param_element.info_element.ac_info & 0x0F; - } - } - - if (rc == 0) { - netdev_dbg(ieee->dev, "QoS is supported\n"); - network->qos_data.supported = 1; - } - return rc; -} - -static const char *get_info_element_string(u16 id) -{ - switch (id) { - case MFIE_TYPE_SSID: - return "SSID"; - case MFIE_TYPE_RATES: - return "RATES"; - case MFIE_TYPE_FH_SET: - return "FH_SET"; - case MFIE_TYPE_DS_SET: - return "DS_SET"; - case MFIE_TYPE_CF_SET: - return "CF_SET"; - case MFIE_TYPE_TIM: - return "TIM"; - case MFIE_TYPE_IBSS_SET: - return "IBSS_SET"; - case MFIE_TYPE_COUNTRY: - return "COUNTRY"; - case MFIE_TYPE_HOP_PARAMS: - return "HOP_PARAMS"; - case MFIE_TYPE_HOP_TABLE: - return "HOP_TABLE"; - case MFIE_TYPE_REQUEST: - return "REQUEST"; - case MFIE_TYPE_CHALLENGE: - return "CHALLENGE"; - case MFIE_TYPE_POWER_CONSTRAINT: - return "POWER_CONSTRAINT"; - case MFIE_TYPE_POWER_CAPABILITY: - return "POWER_CAPABILITY"; - case MFIE_TYPE_TPC_REQUEST: - return "TPC_REQUEST"; - case MFIE_TYPE_TPC_REPORT: - return "TPC_REPORT"; - case MFIE_TYPE_SUPP_CHANNELS: - return "SUPP_CHANNELS"; - case MFIE_TYPE_CSA: - return "CSA"; - case MFIE_TYPE_MEASURE_REQUEST: - return "MEASURE_REQUEST"; - case MFIE_TYPE_MEASURE_REPORT: - return "MEASURE_REPORT"; - case MFIE_TYPE_QUIET: - return "QUIET"; - case MFIE_TYPE_IBSS_DFS: - return "IBSS_DFS"; - case MFIE_TYPE_RSN: - return "RSN"; - case MFIE_TYPE_RATES_EX: - return "RATES_EX"; - case MFIE_TYPE_GENERIC: - return "GENERIC"; - case MFIE_TYPE_QOS_PARAMETER: - return "QOS_PARAMETER"; - default: - return "UNKNOWN"; - } -} - -static void rtllib_parse_mife_generic(struct rtllib_device *ieee, - struct rtllib_info_element *info_element, - struct rtllib_network *network, - u16 *tmp_htcap_len, - u16 *tmp_htinfo_len) -{ - u16 ht_realtek_agg_len = 0; - u8 ht_realtek_agg_buf[MAX_IE_LEN]; - - if (!rtllib_parse_qos_info_param_IE(ieee, info_element, network)) - return; - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x01) { - network->wpa_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->wpa_ie, info_element, network->wpa_ie_len); - return; - } - if (info_element->len == 7 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0xe0 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x01 && - info_element->data[4] == 0x02) - network->turbo_enable = 1; - - if (*tmp_htcap_len == 0) { - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x90 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x033) { - *tmp_htcap_len = min_t(u8, info_element->len, - MAX_IE_LEN); - if (*tmp_htcap_len != 0) { - network->bssht.bd_ht_spec_ver = HT_SPEC_VER_EWC; - network->bssht.bd_ht_cap_len = min_t(u16, *tmp_htcap_len, - sizeof(network->bssht.bd_ht_cap_buf)); - memcpy(network->bssht.bd_ht_cap_buf, - info_element->data, - network->bssht.bd_ht_cap_len); - } - } - if (*tmp_htcap_len != 0) { - network->bssht.bd_support_ht = true; - network->bssht.bd_ht_1r = ((((struct ht_capab_ele *)(network->bssht.bd_ht_cap_buf))->MCS[1]) == 0); - } else { - network->bssht.bd_support_ht = false; - network->bssht.bd_ht_1r = false; - } - } - - if (*tmp_htinfo_len == 0) { - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x90 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x034) { - *tmp_htinfo_len = min_t(u8, info_element->len, - MAX_IE_LEN); - if (*tmp_htinfo_len != 0) { - network->bssht.bd_ht_spec_ver = HT_SPEC_VER_EWC; - network->bssht.bd_ht_info_len = min_t(u16, *tmp_htinfo_len, - sizeof(network->bssht.bd_ht_info_buf)); - memcpy(network->bssht.bd_ht_info_buf, - info_element->data, - network->bssht.bd_ht_info_len); - } - } - } - - if (network->bssht.bd_support_ht) { - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0xe0 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x02) { - ht_realtek_agg_len = min_t(u8, info_element->len, - MAX_IE_LEN); - memcpy(ht_realtek_agg_buf, info_element->data, - info_element->len); - } - if (ht_realtek_agg_len >= 5) { - network->realtek_cap_exit = true; - network->bssht.bd_rt2rt_aggregation = true; - - if ((ht_realtek_agg_buf[4] == 1) && - (ht_realtek_agg_buf[5] & 0x02)) - network->bssht.bd_rt2rt_long_slot_time = true; - - if ((ht_realtek_agg_buf[4] == 1) && - (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE)) - network->bssht.rt2rt_ht_mode |= RT_HT_CAP_USE_92SE; - } - } - if (ht_realtek_agg_len >= 5) { - if ((ht_realtek_agg_buf[5] & RT_HT_CAP_USE_SOFTAP)) - network->bssht.rt2rt_ht_mode |= RT_HT_CAP_USE_SOFTAP; - } - - if ((info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x05 && - info_element->data[2] == 0xb5) || - (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x0a && - info_element->data[2] == 0xf7) || - (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x10 && - info_element->data[2] == 0x18)) { - network->broadcom_cap_exist = true; - } - if (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x0c && - info_element->data[2] == 0x43) - network->ralink_cap_exist = true; - if ((info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x03 && - info_element->data[2] == 0x7f) || - (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x13 && - info_element->data[2] == 0x74)) - network->atheros_cap_exist = true; - - if ((info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0x43)) - network->marvell_cap_exist = true; - if (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x40 && - info_element->data[2] == 0x96) - network->cisco_cap_exist = true; - - if (info_element->len >= 3 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x0a && - info_element->data[2] == 0xf5) - network->airgo_cap_exist = true; - - if (info_element->len > 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x40 && - info_element->data[2] == 0x96 && - info_element->data[3] == 0x01) { - if (info_element->len == 6) { - memcpy(network->ccx_rm_state, &info_element->data[4], 2); - if (network->ccx_rm_state[0] != 0) - network->ccx_rm_enable = true; - else - network->ccx_rm_enable = false; - network->mb_ssid_mask = network->ccx_rm_state[1] & 0x07; - if (network->mb_ssid_mask != 0) { - network->mb_ssid_valid = true; - network->mb_ssid_mask = 0xff << - (network->mb_ssid_mask); - ether_addr_copy(network->mb_ssid, - network->bssid); - network->mb_ssid[5] &= network->mb_ssid_mask; - } else { - network->mb_ssid_valid = false; - } - } else { - network->ccx_rm_enable = false; - } - } - if (info_element->len > 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x40 && - info_element->data[2] == 0x96 && - info_element->data[3] == 0x03) { - if (info_element->len == 5) { - network->with_ccx_ver_num = true; - network->bss_ccx_ver_number = info_element->data[4]; - } else { - network->with_ccx_ver_num = false; - network->bss_ccx_ver_number = 0; - } - } - if (info_element->len > 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x04) { - netdev_dbg(ieee->dev, "MFIE_TYPE_WZC: %d bytes\n", - info_element->len); - network->wzc_ie_len = min(info_element->len + 2, MAX_WZC_IE_LEN); - memcpy(network->wzc_ie, info_element, network->wzc_ie_len); - } -} - -static void rtllib_parse_mfie_ht_cap(struct rtllib_info_element *info_element, - struct rtllib_network *network, - u16 *tmp_htcap_len) -{ - struct bss_ht *ht = &network->bssht; - - *tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN); - if (*tmp_htcap_len != 0) { - ht->bd_ht_spec_ver = HT_SPEC_VER_EWC; - ht->bd_ht_cap_len = min_t(u16, *tmp_htcap_len, - sizeof(ht->bd_ht_cap_buf)); - memcpy(ht->bd_ht_cap_buf, info_element->data, ht->bd_ht_cap_len); - - ht->bd_support_ht = true; - ht->bd_ht_1r = ((((struct ht_capab_ele *) - ht->bd_ht_cap_buf))->MCS[1]) == 0; - - ht->bd_bandwidth = (enum ht_channel_width) - (((struct ht_capab_ele *) - (ht->bd_ht_cap_buf))->chl_width); - } else { - ht->bd_support_ht = false; - ht->bd_ht_1r = false; - ht->bd_bandwidth = HT_CHANNEL_WIDTH_20; - } -} - -int rtllib_parse_info_param(struct rtllib_device *ieee, - struct rtllib_info_element *info_element, - u16 length, - struct rtllib_network *network, - struct rtllib_rx_stats *stats) -{ - u8 i; - short offset; - u16 tmp_htcap_len = 0; - u16 tmp_htinfo_len = 0; - char rates_str[64]; - char *p; - - while (length >= sizeof(*info_element)) { - if (sizeof(*info_element) + info_element->len > length) { - netdev_dbg(ieee->dev, - "Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n", - info_element->len + sizeof(*info_element), - length, info_element->id); - /* We stop processing but don't return an error here - * because some misbehaviour APs break this rule. ie. - * Orinoco AP1000. - */ - break; - } - - switch (info_element->id) { - case MFIE_TYPE_SSID: - if (rtllib_is_empty_essid(info_element->data, - info_element->len)) { - network->flags |= NETWORK_EMPTY_ESSID; - break; - } - - network->ssid_len = min(info_element->len, - (u8)IW_ESSID_MAX_SIZE); - memcpy(network->ssid, info_element->data, - network->ssid_len); - if (network->ssid_len < IW_ESSID_MAX_SIZE) - memset(network->ssid + network->ssid_len, 0, - IW_ESSID_MAX_SIZE - network->ssid_len); - - netdev_dbg(ieee->dev, "MFIE_TYPE_SSID: '%s' len=%d.\n", - network->ssid, network->ssid_len); - break; - - case MFIE_TYPE_RATES: - p = rates_str; - network->rates_len = min(info_element->len, - MAX_RATES_LENGTH); - for (i = 0; i < network->rates_len; i++) { - network->rates[i] = info_element->data[i]; - p += scnprintf(p, sizeof(rates_str) - - (p - rates_str), "%02X ", - network->rates[i]); - if (rtllib_is_ofdm_rate - (info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - RTLLIB_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - - if (rtllib_is_cck_rate - (info_element->data[i])) { - network->flags |= NETWORK_HAS_CCK; - } - } - - netdev_dbg(ieee->dev, "MFIE_TYPE_RATES: '%s' (%d)\n", - rates_str, network->rates_len); - break; - - case MFIE_TYPE_RATES_EX: - p = rates_str; - network->rates_ex_len = min(info_element->len, - MAX_RATES_EX_LENGTH); - for (i = 0; i < network->rates_ex_len; i++) { - network->rates_ex[i] = info_element->data[i]; - p += scnprintf(p, sizeof(rates_str) - - (p - rates_str), "%02X ", - network->rates_ex[i]); - if (rtllib_is_ofdm_rate - (info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - RTLLIB_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - netdev_dbg(ieee->dev, "MFIE_TYPE_RATES_EX: '%s' (%d)\n", - rates_str, network->rates_ex_len); - break; - - case MFIE_TYPE_DS_SET: - netdev_dbg(ieee->dev, "MFIE_TYPE_DS_SET: %d\n", - info_element->data[0]); - network->channel = info_element->data[0]; - break; - - case MFIE_TYPE_FH_SET: - netdev_dbg(ieee->dev, "MFIE_TYPE_FH_SET: ignored\n"); - break; - - case MFIE_TYPE_CF_SET: - netdev_dbg(ieee->dev, "MFIE_TYPE_CF_SET: ignored\n"); - break; - - case MFIE_TYPE_TIM: - if (info_element->len < 4) - break; - - network->tim.tim_count = info_element->data[0]; - network->tim.tim_period = info_element->data[1]; - - network->dtim_period = info_element->data[1]; - if (ieee->link_state != MAC80211_LINKED) - break; - network->last_dtim_sta_time = jiffies; - - network->dtim_data = RTLLIB_DTIM_VALID; - - if (info_element->data[2] & 1) - network->dtim_data |= RTLLIB_DTIM_MBCAST; - - offset = (info_element->data[2] >> 1) * 2; - - if (ieee->assoc_id < 8 * offset || - ieee->assoc_id > 8 * (offset + info_element->len - 3)) - break; - - offset = (ieee->assoc_id / 8) - offset; - if (info_element->data[3 + offset] & - (1 << (ieee->assoc_id % 8))) - network->dtim_data |= RTLLIB_DTIM_UCAST; - - network->listen_interval = network->dtim_period; - break; - - case MFIE_TYPE_ERP: - network->erp_value = info_element->data[0]; - network->flags |= NETWORK_HAS_ERP_VALUE; - netdev_dbg(ieee->dev, "MFIE_TYPE_ERP_SET: %d\n", - network->erp_value); - break; - case MFIE_TYPE_IBSS_SET: - network->atim_window = info_element->data[0]; - netdev_dbg(ieee->dev, "MFIE_TYPE_IBSS_SET: %d\n", - network->atim_window); - break; - - case MFIE_TYPE_CHALLENGE: - netdev_dbg(ieee->dev, "MFIE_TYPE_CHALLENGE: ignored\n"); - break; - - case MFIE_TYPE_GENERIC: - netdev_dbg(ieee->dev, "MFIE_TYPE_GENERIC: %d bytes\n", - info_element->len); - - rtllib_parse_mife_generic(ieee, info_element, network, - &tmp_htcap_len, - &tmp_htinfo_len); - break; - - case MFIE_TYPE_RSN: - netdev_dbg(ieee->dev, "MFIE_TYPE_RSN: %d bytes\n", - info_element->len); - network->rsn_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->rsn_ie, info_element, - network->rsn_ie_len); - break; - - case MFIE_TYPE_HT_CAP: - netdev_dbg(ieee->dev, "MFIE_TYPE_HT_CAP: %d bytes\n", - info_element->len); - - rtllib_parse_mfie_ht_cap(info_element, network, - &tmp_htcap_len); - break; - - case MFIE_TYPE_HT_INFO: - netdev_dbg(ieee->dev, "MFIE_TYPE_HT_INFO: %d bytes\n", - info_element->len); - tmp_htinfo_len = min_t(u8, info_element->len, - MAX_IE_LEN); - if (tmp_htinfo_len) { - network->bssht.bd_ht_spec_ver = HT_SPEC_VER_IEEE; - network->bssht.bd_ht_info_len = tmp_htinfo_len > - sizeof(network->bssht.bd_ht_info_buf) ? - sizeof(network->bssht.bd_ht_info_buf) : - tmp_htinfo_len; - memcpy(network->bssht.bd_ht_info_buf, - info_element->data, - network->bssht.bd_ht_info_len); - } - break; - - case MFIE_TYPE_AIRONET: - netdev_dbg(ieee->dev, "MFIE_TYPE_AIRONET: %d bytes\n", - info_element->len); - if (info_element->len > IE_CISCO_FLAG_POSITION) { - network->with_aironet_ie = true; - - if ((info_element->data[IE_CISCO_FLAG_POSITION] - & SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION] - & SUPPORT_CKIP_PK)) - network->ckip_supported = true; - else - network->ckip_supported = false; - } else { - network->with_aironet_ie = false; - network->ckip_supported = false; - } - break; - case MFIE_TYPE_QOS_PARAMETER: - netdev_err(ieee->dev, - "QoS Error need to parse QOS_PARAMETER IE\n"); - break; - - case MFIE_TYPE_COUNTRY: - netdev_dbg(ieee->dev, "MFIE_TYPE_COUNTRY: %d bytes\n", - info_element->len); - break; -/* TODO */ - default: - netdev_dbg(ieee->dev, - "Unsupported info element: %s (%d)\n", - get_info_element_string(info_element->id), - info_element->id); - break; - } - - length -= sizeof(*info_element) + info_element->len; - info_element = - (struct rtllib_info_element *)&info_element->data[info_element->len]; - } - - if (!network->atheros_cap_exist && !network->broadcom_cap_exist && - !network->cisco_cap_exist && !network->ralink_cap_exist && - !network->bssht.bd_rt2rt_aggregation) - network->unknown_cap_exist = true; - else - network->unknown_cap_exist = false; - return 0; -} - -static long rtllib_translate_todbm(u8 signal_strength_index) -{ - long signal_power; - - signal_power = (long)((signal_strength_index + 1) >> 1); - signal_power -= 95; - - return signal_power; -} - -static inline int rtllib_network_init( - struct rtllib_device *ieee, - struct rtllib_probe_response *beacon, - struct rtllib_network *network, - struct rtllib_rx_stats *stats) -{ - memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data)); - - /* Pull out fixed field data */ - ether_addr_copy(network->bssid, beacon->header.addr3); - network->capability = le16_to_cpu(beacon->capability); - network->last_scanned = jiffies; - network->time_stamp[0] = beacon->time_stamp[0]; - network->time_stamp[1] = beacon->time_stamp[1]; - network->beacon_interval = le16_to_cpu(beacon->beacon_interval); - /* Where to pull this? beacon->listen_interval;*/ - network->listen_interval = 0x0A; - network->rates_len = network->rates_ex_len = 0; - network->ssid_len = 0; - network->hidden_ssid_len = 0; - memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid)); - network->flags = 0; - network->atim_window = 0; - network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? - 0x3 : 0x0; - network->berp_info_valid = false; - network->broadcom_cap_exist = false; - network->ralink_cap_exist = false; - network->atheros_cap_exist = false; - network->cisco_cap_exist = false; - network->unknown_cap_exist = false; - network->realtek_cap_exit = false; - network->marvell_cap_exist = false; - network->airgo_cap_exist = false; - network->turbo_enable = 0; - network->signal_strength = stats->signal_strength; - network->RSSI = stats->signal_strength; - network->country_ie_len = 0; - memset(network->country_ie_buf, 0, MAX_IE_LEN); - ht_initialize_bss_desc(&network->bssht); - network->flags |= NETWORK_HAS_CCK; - - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; - network->wzc_ie_len = 0; - - if (rtllib_parse_info_param(ieee, - beacon->info_element, - (stats->len - sizeof(*beacon)), - network, - stats)) - return 1; - - network->mode = 0; - - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= WIRELESS_MODE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= WIRELESS_MODE_B; - - if (network->mode == 0) { - netdev_dbg(ieee->dev, "Filtered out '%s (%pM)' network.\n", - escape_essid(network->ssid, network->ssid_len), - network->bssid); - return 1; - } - - if (network->bssht.bd_support_ht) { - if (network->mode & (WIRELESS_MODE_G | WIRELESS_MODE_B)) - network->mode = WIRELESS_MODE_N_24G; - } - if (rtllib_is_empty_essid(network->ssid, network->ssid_len)) - network->flags |= NETWORK_EMPTY_ESSID; - stats->signal = 30 + (stats->signal_strength * 70) / 100; - stats->noise = rtllib_translate_todbm((u8)(100 - stats->signal)) - 25; - - memcpy(&network->stats, stats, sizeof(network->stats)); - - return 0; -} - -static inline int is_same_network(struct rtllib_network *src, - struct rtllib_network *dst, u8 ssidbroad) -{ - /* A network is only a duplicate if the channel, BSSID, ESSID - * and the capability field (in particular IBSS and BSS) all match. - * We treat all <hidden> with the same BSSID and channel - * as one network - */ - return (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) && - (src->channel == dst->channel) && - !memcmp(src->bssid, dst->bssid, ETH_ALEN) && - (!memcmp(src->ssid, dst->ssid, src->ssid_len) || - (!ssidbroad)) && - ((src->capability & WLAN_CAPABILITY_IBSS) == - (dst->capability & WLAN_CAPABILITY_IBSS)) && - ((src->capability & WLAN_CAPABILITY_ESS) == - (dst->capability & WLAN_CAPABILITY_ESS))); -} - -static inline void update_network(struct rtllib_device *ieee, - struct rtllib_network *dst, - struct rtllib_network *src) -{ - int qos_active; - u8 old_param; - - memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats)); - dst->capability = src->capability; - memcpy(dst->rates, src->rates, src->rates_len); - dst->rates_len = src->rates_len; - memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); - dst->rates_ex_len = src->rates_ex_len; - if (src->ssid_len > 0) { - if (dst->ssid_len == 0) { - memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid)); - dst->hidden_ssid_len = src->ssid_len; - memcpy(dst->hidden_ssid, src->ssid, src->ssid_len); - } else { - memset(dst->ssid, 0, dst->ssid_len); - dst->ssid_len = src->ssid_len; - memcpy(dst->ssid, src->ssid, src->ssid_len); - } - } - dst->mode = src->mode; - dst->flags = src->flags; - dst->time_stamp[0] = src->time_stamp[0]; - dst->time_stamp[1] = src->time_stamp[1]; - if (src->flags & NETWORK_HAS_ERP_VALUE) { - dst->erp_value = src->erp_value; - dst->berp_info_valid = src->berp_info_valid = true; - } - dst->beacon_interval = src->beacon_interval; - dst->listen_interval = src->listen_interval; - dst->atim_window = src->atim_window; - dst->dtim_period = src->dtim_period; - dst->dtim_data = src->dtim_data; - dst->last_dtim_sta_time = src->last_dtim_sta_time; - memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters)); - - dst->bssht.bd_support_ht = src->bssht.bd_support_ht; - dst->bssht.bd_rt2rt_aggregation = src->bssht.bd_rt2rt_aggregation; - dst->bssht.bd_ht_cap_len = src->bssht.bd_ht_cap_len; - memcpy(dst->bssht.bd_ht_cap_buf, src->bssht.bd_ht_cap_buf, - src->bssht.bd_ht_cap_len); - dst->bssht.bd_ht_info_len = src->bssht.bd_ht_info_len; - memcpy(dst->bssht.bd_ht_info_buf, src->bssht.bd_ht_info_buf, - src->bssht.bd_ht_info_len); - dst->bssht.bd_ht_spec_ver = src->bssht.bd_ht_spec_ver; - dst->bssht.bd_rt2rt_long_slot_time = src->bssht.bd_rt2rt_long_slot_time; - dst->broadcom_cap_exist = src->broadcom_cap_exist; - dst->ralink_cap_exist = src->ralink_cap_exist; - dst->atheros_cap_exist = src->atheros_cap_exist; - dst->realtek_cap_exit = src->realtek_cap_exit; - dst->marvell_cap_exist = src->marvell_cap_exist; - dst->cisco_cap_exist = src->cisco_cap_exist; - dst->airgo_cap_exist = src->airgo_cap_exist; - dst->unknown_cap_exist = src->unknown_cap_exist; - memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); - dst->wpa_ie_len = src->wpa_ie_len; - memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); - dst->rsn_ie_len = src->rsn_ie_len; - memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len); - dst->wzc_ie_len = src->wzc_ie_len; - - dst->last_scanned = jiffies; - /* qos related parameters */ - qos_active = dst->qos_data.active; - old_param = dst->qos_data.param_count; - dst->qos_data.supported = src->qos_data.supported; - if (dst->flags & NETWORK_HAS_QOS_PARAMETERS) - memcpy(&dst->qos_data, &src->qos_data, - sizeof(struct rtllib_qos_data)); - if (dst->qos_data.supported == 1) { - if (dst->ssid_len) - netdev_dbg(ieee->dev, - "QoS the network %s is QoS supported\n", - dst->ssid); - else - netdev_dbg(ieee->dev, - "QoS the network is QoS supported\n"); - } - dst->qos_data.active = qos_active; - dst->qos_data.old_param_count = old_param; - - dst->wmm_info = src->wmm_info; - if (src->wmm_param[0].ac_aci_acm_aifsn || - src->wmm_param[1].ac_aci_acm_aifsn || - src->wmm_param[2].ac_aci_acm_aifsn || - src->wmm_param[3].ac_aci_acm_aifsn) - memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); - - dst->signal_strength = src->signal_strength; - dst->RSSI = src->RSSI; - dst->turbo_enable = src->turbo_enable; - - dst->country_ie_len = src->country_ie_len; - memcpy(dst->country_ie_buf, src->country_ie_buf, src->country_ie_len); - - dst->with_aironet_ie = src->with_aironet_ie; - dst->ckip_supported = src->ckip_supported; - memcpy(dst->ccx_rm_state, src->ccx_rm_state, 2); - dst->ccx_rm_enable = src->ccx_rm_enable; - dst->mb_ssid_mask = src->mb_ssid_mask; - dst->mb_ssid_valid = src->mb_ssid_valid; - memcpy(dst->mb_ssid, src->mb_ssid, 6); - dst->with_ccx_ver_num = src->with_ccx_ver_num; - dst->bss_ccx_ver_number = src->bss_ccx_ver_number; -} - -static int is_passive_channel(struct rtllib_device *rtllib, u8 channel) -{ - if (channel > MAX_CHANNEL_NUMBER) { - netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__); - return 0; - } - - if (rtllib->active_channel_map[channel] == 2) - return 1; - - return 0; -} - -int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel) -{ - if (channel > MAX_CHANNEL_NUMBER) { - netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__); - return 0; - } - if (rtllib->active_channel_map[channel] > 0) - return 1; - - return 0; -} -EXPORT_SYMBOL(rtllib_legal_channel); - -static inline void rtllib_process_probe_response( - struct rtllib_device *ieee, - struct rtllib_probe_response *beacon, - struct rtllib_rx_stats *stats) -{ - struct rtllib_network *target; - struct rtllib_network *oldest = NULL; - struct rtllib_info_element *info_element = &beacon->info_element[0]; - unsigned long flags; - short renew; - struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network), - GFP_ATOMIC); - __le16 frame_ctl = beacon->header.frame_control; - - if (!network) - return; - - netdev_dbg(ieee->dev, - "'%s' ( %pM ): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", - escape_essid(info_element->data, info_element->len), - beacon->header.addr3, - (le16_to_cpu(beacon->capability) & (1 << 0xf)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0xe)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0xd)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0xc)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0xb)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0xa)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x9)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x8)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x7)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x6)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x5)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x4)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x3)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x2)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x1)) ? '1' : '0', - (le16_to_cpu(beacon->capability) & (1 << 0x0)) ? '1' : '0'); - - if (rtllib_network_init(ieee, beacon, network, stats)) { - netdev_dbg(ieee->dev, "Dropped '%s' ( %pM) via %s.\n", - escape_essid(info_element->data, info_element->len), - beacon->header.addr3, - ieee80211_is_beacon(frame_ctl) ? "BEACON" : "PROBE RESPONSE"); - goto free_network; - } - - if (!rtllib_legal_channel(ieee, network->channel)) - goto free_network; - - if (ieee80211_is_probe_resp(frame_ctl)) { - if (is_passive_channel(ieee, network->channel)) { - netdev_info(ieee->dev, - "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", - network->channel); - goto free_network; - } - } - - /* The network parsed correctly -- so now we scan our known networks - * to see if we can find it in our list. - * - * NOTE: This search is definitely not optimized. Once its doing - * the "right thing" we'll optimize it for efficiency if - * necessary - */ - - /* Search for this entry in the list and update it if it is - * already there. - */ - - spin_lock_irqsave(&ieee->lock, flags); - if (is_same_network(&ieee->current_network, network, - (network->ssid_len ? 1 : 0))) { - update_network(ieee, &ieee->current_network, network); - if ((ieee->current_network.mode == WIRELESS_MODE_N_24G || - ieee->current_network.mode == WIRELESS_MODE_G) && - ieee->current_network.berp_info_valid) { - if (ieee->current_network.erp_value & ERP_UseProtection) - ieee->current_network.buseprotection = true; - else - ieee->current_network.buseprotection = false; - } - if (ieee80211_is_beacon(frame_ctl)) { - if (ieee->link_state >= MAC80211_LINKED) - ieee->link_detect_info.num_recv_bcn_in_period++; - } - } - list_for_each_entry(target, &ieee->network_list, list) { - if (is_same_network(target, network, - (target->ssid_len ? 1 : 0))) - break; - if (!oldest || (target->last_scanned < oldest->last_scanned)) - oldest = target; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information - */ - if (&target->list == &ieee->network_list) { - if (list_empty(&ieee->network_free_list)) { - /* If there are no more slots, expire the oldest */ - list_del(&oldest->list); - target = oldest; - netdev_dbg(ieee->dev, - "Expired '%s' ( %pM) from network list.\n", - escape_essid(target->ssid, target->ssid_len), - target->bssid); - } else { - /* Otherwise just pull from the free list */ - target = list_entry(ieee->network_free_list.next, - struct rtllib_network, list); - list_del(ieee->network_free_list.next); - } - - netdev_dbg(ieee->dev, "Adding '%s' ( %pM) via %s.\n", - escape_essid(network->ssid, network->ssid_len), - network->bssid, - ieee80211_is_beacon(frame_ctl) ? "BEACON" : "PROBE RESPONSE"); - - memcpy(target, network, sizeof(*target)); - list_add_tail(&target->list, &ieee->network_list); - if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) - rtllib_softmac_new_net(ieee, network); - } else { - netdev_dbg(ieee->dev, "Updating '%s' ( %pM) via %s.\n", - escape_essid(target->ssid, target->ssid_len), - target->bssid, - ieee80211_is_beacon(frame_ctl) ? "BEACON" : "PROBE RESPONSE"); - - /* we have an entry and we are going to update it. But this - * entry may be already expired. In this case we do the same - * as we found a new net and call the new_net handler - */ - renew = !time_after(target->last_scanned + ieee->scan_age, - jiffies); - if ((!target->ssid_len) && - (((network->ssid_len > 0) && (target->hidden_ssid_len == 0)) - || ((ieee->current_network.ssid_len == network->ssid_len) && - (strncmp(ieee->current_network.ssid, network->ssid, - network->ssid_len) == 0) && - (ieee->link_state == MAC80211_NOLINK)))) - renew = 1; - update_network(ieee, target, network); - if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) - rtllib_softmac_new_net(ieee, network); - } - - spin_unlock_irqrestore(&ieee->lock, flags); - if (ieee80211_is_beacon(frame_ctl) && - is_same_network(&ieee->current_network, network, - (network->ssid_len ? 1 : 0)) && - (ieee->link_state == MAC80211_LINKED)) { - ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network); - } -free_network: - kfree(network); -} - -static void rtllib_rx_mgt(struct rtllib_device *ieee, - struct sk_buff *skb, - struct rtllib_rx_stats *stats) -{ - struct ieee80211_hdr *header = (struct ieee80211_hdr *)skb->data; - - if (!ieee80211_is_probe_resp(header->frame_control) && - (!ieee80211_is_beacon(header->frame_control))) - ieee->last_rx_ps_time = jiffies; - - if (ieee80211_is_beacon(header->frame_control)) { - netdev_dbg(ieee->dev, "received BEACON\n"); - rtllib_process_probe_response( - ieee, (struct rtllib_probe_response *)header, - stats); - - if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED && - ieee->iw_mode == IW_MODE_INFRA && - ieee->link_state == MAC80211_LINKED)) - schedule_work(&ieee->ps_task); - } else if (ieee80211_is_probe_resp(header->frame_control)) { - netdev_dbg(ieee->dev, "received PROBE RESPONSE\n"); - rtllib_process_probe_response(ieee, (struct rtllib_probe_response *)header, - stats); - } -} diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c deleted file mode 100644 index 0fc97c868f81..000000000000 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ /dev/null @@ -1,2309 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Few lines might be stolen from other part of the rtllib - * stack. Copyright who own it's copyright - * - * WPA code stolen from the ipw2200 driver. - * Copyright who own it's copyright. - */ -#include "rtllib.h" - -#include <linux/random.h> -#include <linux/delay.h> -#include <linux/uaccess.h> -#include <linux/etherdevice.h> -#include <linux/ieee80211.h> - -static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl); - -static short rtllib_is_54g(struct rtllib_network *net) -{ - return (net->rates_ex_len > 0) || (net->rates_len > 4); -} - -/* returns the total length needed for placing the RATE MFIE - * tag and the EXTENDED RATE MFIE tag if needed. - * It encludes two bytes per tag for the tag itself and its len - */ -static unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee) -{ - unsigned int rate_len = 0; - - rate_len = RTLLIB_CCK_RATE_LEN + 2; - rate_len += RTLLIB_OFDM_RATE_LEN + 2; - - return rate_len; -} - -/* place the MFIE rate, tag to the memory (double) pointed. - * Then it updates the pointer so that - * it points after the new MFIE tag added. - */ -static void rtllib_mfie_brate(struct rtllib_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_RATES; - *tag++ = 4; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB; - - /* We may add an option for custom rates that specific HW - * might support - */ - *tag_p = tag; -} - -static void rtllib_mfie_grate(struct rtllib_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_RATES_EX; - *tag++ = 8; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB; - *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB; - - /* We may add an option for custom rates that specific HW might - * support - */ - *tag_p = tag; -} - -static void rtllib_wmm_info(struct rtllib_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0x50; - *tag++ = 0xf2; - *tag++ = 0x02; - *tag++ = 0x00; - *tag++ = 0x01; - *tag++ = MAX_SP_Len; - *tag_p = tag; -} - -static void rtllib_turbo_info(struct rtllib_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0xe0; - *tag++ = 0x4c; - *tag++ = 0x01; - *tag++ = 0x02; - *tag++ = 0x11; - *tag++ = 0x00; - - *tag_p = tag; - netdev_alert(ieee->dev, "This is enable turbo mode IE process\n"); -} - -static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb) -{ - int nh; - - nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM; - -/* if the queue is full but we have newer frames then - * just overwrites the oldest. - * - * if (nh == ieee->mgmt_queue_tail) - * return -1; - */ - ieee->mgmt_queue_head = nh; - ieee->mgmt_queue_ring[nh] = skb; -} - -static void init_mgmt_queue(struct rtllib_device *ieee) -{ - ieee->mgmt_queue_tail = 0; - ieee->mgmt_queue_head = 0; -} - -u8 mgnt_query_tx_rate_exclude_cck_rates(struct rtllib_device *ieee) -{ - u16 i; - u8 query_rate = 0; - u8 basic_rate; - - for (i = 0; i < ieee->current_network.rates_len; i++) { - basic_rate = ieee->current_network.rates[i] & 0x7F; - if (!rtllib_is_cck_rate(basic_rate)) { - if (query_rate == 0) { - query_rate = basic_rate; - } else { - if (basic_rate < query_rate) - query_rate = basic_rate; - } - } - } - - if (query_rate == 0) { - query_rate = 12; - netdev_info(ieee->dev, "No basic_rate found!!\n"); - } - return query_rate; -} - -static u8 mgnt_query_mgnt_frame_tx_rate(struct rtllib_device *ieee) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - u8 rate; - - if (ht_info->iot_action & HT_IOT_ACT_MGNT_USE_CCK_6M) - rate = 0x0c; - else - rate = ieee->basic_rate & 0x7f; - - if (rate == 0) - rate = 0x02; - - return rate; -} - -inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) -{ - unsigned long flags; - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *)skb->data; - - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8); - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd param 0, no mgmt lock required */ - rtllib_sta_wakeup(ieee, 0); - - if (ieee80211_is_beacon(header->frame_control)) - tcb_desc->queue_index = BEACON_QUEUE; - else - tcb_desc->queue_index = MGNT_QUEUE; - - if (ieee->disable_mgnt_queue) - tcb_desc->queue_index = HIGH_QUEUE; - - tcb_desc->data_rate = mgnt_query_mgnt_frame_tx_rate(ieee); - tcb_desc->ratr_index = 7; - tcb_desc->tx_dis_rate_fallback = 1; - tcb_desc->tx_use_drv_assinged_rate = 1; - if (single) { - if (ieee->queue_stop) { - enqueue_mgmt(ieee, skb); - } else { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, - ieee->basic_rate); - } - - spin_unlock_irqrestore(&ieee->lock, flags); - } else { - spin_unlock_irqrestore(&ieee->lock, flags); - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); - - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* check whether the managed packet queued greater than 5 */ - if (!ieee->check_nic_enough_desc(ieee->dev, - tcb_desc->queue_index) || - skb_queue_len(&ieee->skb_waitq[tcb_desc->queue_index]) || - ieee->queue_stop) { - /* insert the skb packet to the management queue - * - * as for the completion function, it does not need - * to check it any more. - */ - netdev_info(ieee->dev, - "%s():insert to waitqueue, queue_index:%d!\n", - __func__, tcb_desc->queue_index); - skb_queue_tail(&ieee->skb_waitq[tcb_desc->queue_index], - skb); - } else { - ieee->softmac_hard_start_xmit(skb, ieee->dev); - } - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); - } -} - -static inline void -softmac_ps_mgmt_xmit(struct sk_buff *skb, - struct rtllib_device *ieee) -{ - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *)skb->data; - u16 fc, type, stype; - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8); - - fc = le16_to_cpu(header->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - if (stype != IEEE80211_STYPE_PSPOLL) - tcb_desc->queue_index = MGNT_QUEUE; - else - tcb_desc->queue_index = HIGH_QUEUE; - - if (ieee->disable_mgnt_queue) - tcb_desc->queue_index = HIGH_QUEUE; - - tcb_desc->data_rate = mgnt_query_mgnt_frame_tx_rate(ieee); - tcb_desc->ratr_index = 7; - tcb_desc->tx_dis_rate_fallback = 1; - tcb_desc->tx_use_drv_assinged_rate = 1; - if (single) { - if (type != RTLLIB_FTYPE_CTL) { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - } - /* avoid watchdog triggers */ - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, - ieee->basic_rate); - - } else { - if (type != RTLLIB_FTYPE_CTL) { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - } - ieee->softmac_hard_start_xmit(skb, ieee->dev); - } -} - -static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) -{ - unsigned int len, rate_len; - u8 *tag; - struct sk_buff *skb; - struct rtllib_probe_request *req; - - len = ieee->current_network.ssid_len; - - rate_len = rtllib_MFIE_rate_len(ieee); - - skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + - 2 + len + rate_len + ieee->tx_headroom); - - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - req = skb_put(skb, sizeof(struct rtllib_probe_request)); - req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - req->header.duration_id = 0; - - eth_broadcast_addr(req->header.addr1); - ether_addr_copy(req->header.addr2, ieee->dev->dev_addr); - eth_broadcast_addr(req->header.addr3); - - tag = skb_put(skb, len + 2 + rate_len); - - *tag++ = MFIE_TYPE_SSID; - *tag++ = len; - memcpy(tag, ieee->current_network.ssid, len); - tag += len; - - rtllib_mfie_brate(ieee, &tag); - rtllib_mfie_grate(ieee, &tag); - - return skb; -} - -/* Enables network monitor mode, all rx packets will be received. */ -void rtllib_enable_net_monitor_mode(struct net_device *dev, - bool init_state) -{ - struct rtllib_device *ieee = netdev_priv_rsl(dev); - - netdev_info(dev, "========>Enter Monitor Mode\n"); - - ieee->allow_all_dest_addr_handler(dev, true, !init_state); -} - -/* Disables network monitor mode. Only packets destinated to - * us will be received. - */ -void rtllib_disable_net_monitor_mode(struct net_device *dev, bool init_state) -{ - struct rtllib_device *ieee = netdev_priv_rsl(dev); - - netdev_info(dev, "========>Exit Monitor Mode\n"); - - ieee->allow_all_dest_addr_handler(dev, false, !init_state); -} - -static void rtllib_send_probe(struct rtllib_device *ieee) -{ - struct sk_buff *skb; - - skb = rtllib_probe_req(ieee); - if (skb) { - softmac_mgmt_xmit(skb, ieee); - ieee->softmac_stats.tx_probe_rq++; - } -} - -static void rtllib_send_probe_requests(struct rtllib_device *ieee) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ) { - rtllib_send_probe(ieee); - rtllib_send_probe(ieee); - } -} - -/* this performs syncro scan blocking the caller until all channels - * in the allowed channel map has been checked. - */ -static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee) -{ - union iwreq_data wrqu; - short ch = 0; - - ieee->be_scan_inprogress = true; - - mutex_lock(&ieee->scan_mutex); - - while (1) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - goto out; /* scan completed */ - } while (!ieee->active_channel_map[ch]); - - /* this function can be called in two situations - * 1- We have switched to ad-hoc mode and we are - * performing a complete syncro scan before conclude - * there are no interesting cell and to create a - * new one. In this case the link state is - * MAC80211_NOLINK until we found an interesting cell. - * If so the ieee8021_new_net, called by the RX path - * will set the state to MAC80211_LINKED, so we stop - * scanning - * 2- We are linked and the root uses run iwlist scan. - * So we switch to MAC80211_LINKED_SCANNING to remember - * that we are still logically linked (not interested in - * new network events, despite for updating the net list, - * but we are temporarily 'unlinked' as the driver shall - * not filter RX frames and the channel is changing. - * So the only situation in which are interested is to check - * if the state become LINKED because of the #1 situation - */ - - if (ieee->link_state == MAC80211_LINKED) - goto out; - if (ieee->sync_scan_hurryup) { - netdev_info(ieee->dev, - "============>sync_scan_hurryup out\n"); - goto out; - } - - ieee->set_chan(ieee->dev, ch); - if (ieee->active_channel_map[ch] == 1) - rtllib_send_probe_requests(ieee); - - /* this prevent excessive time wait when we - * need to wait for a syncro scan to end.. - */ - msleep_interruptible_rsl(RTLLIB_SOFTMAC_SCAN_TIME); - } -out: - ieee->actscanning = false; - ieee->sync_scan_hurryup = 0; - - mutex_unlock(&ieee->scan_mutex); - - ieee->be_scan_inprogress = false; - - memset(&wrqu, 0, sizeof(wrqu)); - wireless_send_event(ieee->dev, SIOCGIWSCAN, &wrqu, NULL); -} - -static void rtllib_softmac_scan_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, softmac_scan_wq); - u8 last_channel = ieee->current_network.channel; - - if (!ieee->ieee_up) - return; - if (rtllib_act_scanning(ieee, true)) - return; - - mutex_lock(&ieee->scan_mutex); - - if (ieee->rf_power_state == rf_off) { - netdev_info(ieee->dev, - "======>%s():rf state is rf_off, return\n", - __func__); - goto out1; - } - - do { - ieee->current_network.channel = - (ieee->current_network.channel + 1) % - MAX_CHANNEL_NUMBER; - if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER) { - if (!ieee->active_channel_map[ieee->current_network.channel]) - ieee->current_network.channel = 6; - goto out; /* no good chans */ - } - } while (!ieee->active_channel_map[ieee->current_network.channel]); - - if (ieee->scanning_continue == 0) - goto out; - - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - if (ieee->active_channel_map[ieee->current_network.channel] == 1) - rtllib_send_probe_requests(ieee); - - schedule_delayed_work(&ieee->softmac_scan_wq, - msecs_to_jiffies(RTLLIB_SOFTMAC_SCAN_TIME)); - - mutex_unlock(&ieee->scan_mutex); - return; - -out: - ieee->current_network.channel = last_channel; - -out1: - ieee->actscanning = false; - ieee->scan_watch_dog = 0; - ieee->scanning_continue = 0; - mutex_unlock(&ieee->scan_mutex); -} - -static void rtllib_softmac_stop_scan(struct rtllib_device *ieee) -{ - mutex_lock(&ieee->scan_mutex); - ieee->scan_watch_dog = 0; - if (ieee->scanning_continue == 1) { - ieee->scanning_continue = 0; - ieee->actscanning = false; - mutex_unlock(&ieee->scan_mutex); - cancel_delayed_work_sync(&ieee->softmac_scan_wq); - } else { - mutex_unlock(&ieee->scan_mutex); - } -} - -void rtllib_stop_scan(struct rtllib_device *ieee) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - rtllib_softmac_stop_scan(ieee); -} -EXPORT_SYMBOL(rtllib_stop_scan); - -void rtllib_stop_scan_syncro(struct rtllib_device *ieee) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - ieee->sync_scan_hurryup = 1; -} -EXPORT_SYMBOL(rtllib_stop_scan_syncro); - -bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { - if (sync_scan) - return ieee->be_scan_inprogress; - else - return ieee->actscanning || ieee->be_scan_inprogress; - } else { - return test_bit(STATUS_SCANNING, &ieee->status); - } -} -EXPORT_SYMBOL(rtllib_act_scanning); - -/* called with ieee->lock held */ -static void rtllib_start_scan(struct rtllib_device *ieee) -{ - ieee->rtllib_ips_leave_wq(ieee->dev); - - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { - if (ieee->scanning_continue == 0) { - ieee->actscanning = true; - ieee->scanning_continue = 1; - schedule_delayed_work(&ieee->softmac_scan_wq, 0); - } - } -} - -/* called with wx_mutex held */ -void rtllib_start_scan_syncro(struct rtllib_device *ieee) -{ - ieee->sync_scan_hurryup = 0; - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - rtllib_softmac_scan_syncro(ieee); -} -EXPORT_SYMBOL(rtllib_start_scan_syncro); - -static inline struct sk_buff * -rtllib_authentication_req(struct rtllib_network *beacon, - struct rtllib_device *ieee, - int challengelen, u8 *daddr) -{ - struct sk_buff *skb; - struct rtllib_authentication *auth; - int len; - - len = sizeof(struct rtllib_authentication) + challengelen + - ieee->tx_headroom + 4; - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - auth = skb_put(skb, sizeof(struct rtllib_authentication)); - - auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH); - if (challengelen) - auth->header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - auth->header.duration_id = cpu_to_le16(0x013a); - ether_addr_copy(auth->header.addr1, beacon->bssid); - ether_addr_copy(auth->header.addr2, ieee->dev->dev_addr); - ether_addr_copy(auth->header.addr3, beacon->bssid); - if (ieee->auth_mode == 0) - auth->algorithm = WLAN_AUTH_OPEN; - else if (ieee->auth_mode == 1) - auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY); - else if (ieee->auth_mode == 2) - auth->algorithm = WLAN_AUTH_OPEN; - auth->transaction = cpu_to_le16(ieee->associate_seq); - ieee->associate_seq++; - - auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); - - return skb; -} - -static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr) -{ - struct sk_buff *skb; - struct ieee80211_hdr_3addr *hdr; - - skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr) + ieee->tx_headroom); - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - hdr = skb_put(skb, sizeof(struct ieee80211_hdr_3addr)); - - ether_addr_copy(hdr->addr1, ieee->current_network.bssid); - ether_addr_copy(hdr->addr2, ieee->dev->dev_addr); - ether_addr_copy(hdr->addr3, ieee->current_network.bssid); - - hdr->frame_control = cpu_to_le16(RTLLIB_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | - (pwr ? IEEE80211_FCTL_PM : 0)); - - return skb; -} - -static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee) -{ - struct sk_buff *skb; - struct ieee80211_pspoll *hdr; - - skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll) + ieee->tx_headroom); - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - hdr = skb_put(skb, sizeof(struct ieee80211_pspoll)); - - ether_addr_copy(hdr->bssid, ieee->current_network.bssid); - ether_addr_copy(hdr->ta, ieee->dev->dev_addr); - - hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000); - hdr->frame_control = cpu_to_le16(RTLLIB_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | - IEEE80211_FCTL_PM); - - return skb; -} - -static inline int sec_is_in_pmkid_list(struct rtllib_device *ieee, u8 *bssid) -{ - int i = 0; - - do { - if ((ieee->pmkid_list[i].used) && - (memcmp(ieee->pmkid_list[i].bssid, bssid, ETH_ALEN) == 0)) - break; - i++; - } while (i < NUM_PMKID_CACHE); - - if (i == NUM_PMKID_CACHE) - i = -1; - return i; -} - -static inline struct sk_buff * -rtllib_association_req(struct rtllib_network *beacon, - struct rtllib_device *ieee) -{ - struct sk_buff *skb; - struct rtllib_assoc_request_frame *hdr; - u8 *tag, *ies; - int i; - u8 *ht_cap_buf = NULL; - u8 ht_cap_len = 0; - u8 *realtek_ie_buf = NULL; - u8 realtek_ie_len = 0; - int wpa_ie_len = ieee->wpa_ie_len; - int wps_ie_len = ieee->wps_ie_len; - unsigned int ckip_ie_len = 0; - unsigned int ccxrm_ie_len = 0; - unsigned int cxvernum_ie_len = 0; - struct lib80211_crypt_data *crypt; - int encrypt; - int pmk_cache_idx; - - unsigned int rate_len = (beacon->rates_len ? - (beacon->rates_len + 2) : 0) + - (beacon->rates_ex_len ? (beacon->rates_ex_len) + - 2 : 0); - - unsigned int wmm_info_len = beacon->qos_data.supported ? 9 : 0; - unsigned int turbo_info_len = beacon->turbo_enable ? 9 : 0; - - int len = 0; - - crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - if (crypt) - encrypt = crypt && crypt->ops && - ((strcmp(crypt->ops->name, "R-WEP") == 0 || - wpa_ie_len)); - else - encrypt = 0; - - if ((ieee->rtllib_ap_sec_type && - (ieee->rtllib_ap_sec_type(ieee) & SEC_ALG_TKIP)) || - ieee->forced_bg_mode) { - ieee->ht_info->enable_ht = 0; - ieee->mode = WIRELESS_MODE_G; - } - - if (ieee->ht_info->current_ht_support && ieee->ht_info->enable_ht) { - ht_cap_buf = (u8 *)&ieee->ht_info->self_ht_cap; - ht_cap_len = sizeof(ieee->ht_info->self_ht_cap); - ht_construct_capability_element(ieee, ht_cap_buf, &ht_cap_len, - encrypt, true); - if (ieee->ht_info->current_rt2rt_aggregation) { - realtek_ie_buf = ieee->ht_info->sz_rt2rt_agg_buf; - realtek_ie_len = - sizeof(ieee->ht_info->sz_rt2rt_agg_buf); - ht_construct_rt2rt_agg_element(ieee, realtek_ie_buf, - &realtek_ie_len); - } - } - - if (beacon->ckip_supported) - ckip_ie_len = 30 + 2; - if (beacon->ccx_rm_enable) - ccxrm_ie_len = 6 + 2; - if (beacon->bss_ccx_ver_number >= 2) - cxvernum_ie_len = 5 + 2; - - pmk_cache_idx = sec_is_in_pmkid_list(ieee, ieee->current_network.bssid); - if (pmk_cache_idx >= 0) { - wpa_ie_len += 18; - netdev_info(ieee->dev, "[PMK cache]: WPA2 IE length: %x\n", - wpa_ie_len); - } - len = sizeof(struct rtllib_assoc_request_frame) + 2 - + beacon->ssid_len - + rate_len - + wpa_ie_len - + wps_ie_len - + wmm_info_len - + turbo_info_len - + ht_cap_len - + realtek_ie_len - + ckip_ie_len - + ccxrm_ie_len - + cxvernum_ie_len - + ieee->tx_headroom; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - hdr = skb_put(skb, sizeof(struct rtllib_assoc_request_frame) + 2); - - hdr->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ); - hdr->header.duration_id = cpu_to_le16(37); - ether_addr_copy(hdr->header.addr1, beacon->bssid); - ether_addr_copy(hdr->header.addr2, ieee->dev->dev_addr); - ether_addr_copy(hdr->header.addr3, beacon->bssid); - - ether_addr_copy(ieee->ap_mac_addr, beacon->bssid); - - hdr->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); - if (beacon->capability & WLAN_CAPABILITY_PRIVACY) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - - if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - - if (beacon->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); - - hdr->listen_interval = cpu_to_le16(beacon->listen_interval); - - hdr->info_element[0].id = MFIE_TYPE_SSID; - - hdr->info_element[0].len = beacon->ssid_len; - skb_put_data(skb, beacon->ssid, beacon->ssid_len); - - tag = skb_put(skb, rate_len); - - if (beacon->rates_len) { - *tag++ = MFIE_TYPE_RATES; - *tag++ = beacon->rates_len; - for (i = 0; i < beacon->rates_len; i++) - *tag++ = beacon->rates[i]; - } - - if (beacon->rates_ex_len) { - *tag++ = MFIE_TYPE_RATES_EX; - *tag++ = beacon->rates_ex_len; - for (i = 0; i < beacon->rates_ex_len; i++) - *tag++ = beacon->rates_ex[i]; - } - - if (beacon->ckip_supported) { - static const u8 aironet_ie_oui[] = {0x00, 0x01, 0x66}; - u8 ccx_aironet_buf[30]; - struct octet_string os_ccx_aironet_ie; - - memset(ccx_aironet_buf, 0, 30); - os_ccx_aironet_ie.octet = ccx_aironet_buf; - os_ccx_aironet_ie.Length = sizeof(ccx_aironet_buf); - memcpy(os_ccx_aironet_ie.octet, aironet_ie_oui, - sizeof(aironet_ie_oui)); - - os_ccx_aironet_ie.octet[IE_CISCO_FLAG_POSITION] |= - (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC); - tag = skb_put(skb, ckip_ie_len); - *tag++ = MFIE_TYPE_AIRONET; - *tag++ = os_ccx_aironet_ie.Length; - memcpy(tag, os_ccx_aironet_ie.octet, os_ccx_aironet_ie.Length); - tag += os_ccx_aironet_ie.Length; - } - - if (beacon->ccx_rm_enable) { - static const u8 ccx_rm_cap_buf[] = {0x00, 0x40, 0x96, 0x01, 0x01, - 0x00}; - struct octet_string os_ccx_rm_cap; - - os_ccx_rm_cap.octet = (u8 *)ccx_rm_cap_buf; - os_ccx_rm_cap.Length = sizeof(ccx_rm_cap_buf); - tag = skb_put(skb, ccxrm_ie_len); - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = os_ccx_rm_cap.Length; - memcpy(tag, os_ccx_rm_cap.octet, os_ccx_rm_cap.Length); - tag += os_ccx_rm_cap.Length; - } - - if (beacon->bss_ccx_ver_number >= 2) { - u8 ccx_ver_num_buf[] = {0x00, 0x40, 0x96, 0x03, 0x00}; - struct octet_string os_ccx_ver_num; - - ccx_ver_num_buf[4] = beacon->bss_ccx_ver_number; - os_ccx_ver_num.octet = ccx_ver_num_buf; - os_ccx_ver_num.Length = sizeof(ccx_ver_num_buf); - tag = skb_put(skb, cxvernum_ie_len); - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = os_ccx_ver_num.Length; - memcpy(tag, os_ccx_ver_num.octet, os_ccx_ver_num.Length); - tag += os_ccx_ver_num.Length; - } - if (ieee->ht_info->current_ht_support && ieee->ht_info->enable_ht) { - if (ieee->ht_info->peer_ht_spec_ver != HT_SPEC_VER_EWC) { - tag = skb_put(skb, ht_cap_len); - *tag++ = MFIE_TYPE_HT_CAP; - *tag++ = ht_cap_len - 2; - memcpy(tag, ht_cap_buf, ht_cap_len - 2); - tag += ht_cap_len - 2; - } - } - - if (wpa_ie_len) { - skb_put_data(skb, ieee->wpa_ie, ieee->wpa_ie_len); - - if (pmk_cache_idx >= 0) { - tag = skb_put(skb, 18); - *tag = 1; - *(tag + 1) = 0; - memcpy((tag + 2), &ieee->pmkid_list[pmk_cache_idx].PMKID, - 16); - } - } - if (wmm_info_len) { - tag = skb_put(skb, wmm_info_len); - rtllib_wmm_info(ieee, &tag); - } - - if (wps_ie_len && ieee->wps_ie) - skb_put_data(skb, ieee->wps_ie, wps_ie_len); - - if (turbo_info_len) { - tag = skb_put(skb, turbo_info_len); - rtllib_turbo_info(ieee, &tag); - } - - if (ieee->ht_info->current_ht_support && ieee->ht_info->enable_ht) { - if (ieee->ht_info->peer_ht_spec_ver == HT_SPEC_VER_EWC) { - tag = skb_put(skb, ht_cap_len); - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = ht_cap_len - 2; - memcpy(tag, ht_cap_buf, ht_cap_len - 2); - tag += ht_cap_len - 2; - } - - if (ieee->ht_info->current_rt2rt_aggregation) { - tag = skb_put(skb, realtek_ie_len); - *tag++ = MFIE_TYPE_GENERIC; - *tag++ = realtek_ie_len - 2; - memcpy(tag, realtek_ie_buf, realtek_ie_len - 2); - } - } - - kfree(ieee->assocreq_ies); - ieee->assocreq_ies = NULL; - ies = &hdr->info_element[0].id; - ieee->assocreq_ies_len = (skb->data + skb->len) - ies; - ieee->assocreq_ies = kmemdup(ies, ieee->assocreq_ies_len, GFP_ATOMIC); - if (!ieee->assocreq_ies) - ieee->assocreq_ies_len = 0; - - return skb; -} - -static void rtllib_associate_abort(struct rtllib_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - - ieee->associate_seq++; - - /* don't scan, and avoid to have the RX path possibly - * try again to associate. Even do not react to AUTH or - * ASSOC response. Just wait for the retry wq to be scheduled. - * Here we will check if there are good nets to associate - * with, so we retry or just get back to NO_LINK and scanning - */ - if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING) { - netdev_dbg(ieee->dev, "Authentication failed\n"); - ieee->softmac_stats.no_auth_rs++; - } else { - netdev_dbg(ieee->dev, "Association failed\n"); - ieee->softmac_stats.no_ass_rs++; - } - - ieee->link_state = RTLLIB_ASSOCIATING_RETRY; - - schedule_delayed_work(&ieee->associate_retry_wq, - RTLLIB_SOFTMAC_ASSOC_RETRY_TIME); - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static void rtllib_associate_abort_cb(struct timer_list *t) -{ - struct rtllib_device *dev = from_timer(dev, t, associate_timer); - - rtllib_associate_abort(dev); -} - -static void rtllib_associate_step1(struct rtllib_device *ieee, u8 *daddr) -{ - struct rtllib_network *beacon = &ieee->current_network; - struct sk_buff *skb; - - netdev_dbg(ieee->dev, "Stopping scan\n"); - - ieee->softmac_stats.tx_auth_rq++; - - skb = rtllib_authentication_req(beacon, ieee, 0, daddr); - - if (!skb) { - rtllib_associate_abort(ieee); - } else { - ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATING; - netdev_dbg(ieee->dev, "Sending authentication request\n"); - softmac_mgmt_xmit(skb, ieee); - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - } -} - -static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, - int chlen) -{ - u8 *c; - struct sk_buff *skb; - struct rtllib_network *beacon = &ieee->current_network; - - ieee->associate_seq++; - ieee->softmac_stats.tx_auth_rq++; - - skb = rtllib_authentication_req(beacon, ieee, chlen + 2, beacon->bssid); - - if (!skb) { - rtllib_associate_abort(ieee); - } else { - c = skb_put(skb, chlen + 2); - *(c++) = MFIE_TYPE_CHALLENGE; - *(c++) = chlen; - memcpy(c, challenge, chlen); - - netdev_dbg(ieee->dev, - "Sending authentication challenge response\n"); - - rtllib_encrypt_fragment(ieee, skb, - sizeof(struct ieee80211_hdr_3addr)); - - softmac_mgmt_xmit(skb, ieee); - mod_timer(&ieee->associate_timer, jiffies + (HZ / 2)); - } - kfree(challenge); -} - -static void rtllib_associate_step2(struct rtllib_device *ieee) -{ - struct sk_buff *skb; - struct rtllib_network *beacon = &ieee->current_network; - - del_timer_sync(&ieee->associate_timer); - - netdev_dbg(ieee->dev, "Sending association request\n"); - - ieee->softmac_stats.tx_ass_rq++; - skb = rtllib_association_req(beacon, ieee); - if (!skb) { - rtllib_associate_abort(ieee); - } else { - softmac_mgmt_xmit(skb, ieee); - mod_timer(&ieee->associate_timer, jiffies + (HZ / 2)); - } -} - -static void rtllib_associate_complete_wq(void *data) -{ - struct rtllib_device *ieee = (struct rtllib_device *) - container_of(data, - struct rtllib_device, - associate_complete_wq); - struct rt_pwr_save_ctrl *psc = &ieee->pwr_save_ctrl; - - netdev_info(ieee->dev, "Associated successfully with %pM\n", - ieee->current_network.bssid); - netdev_info(ieee->dev, "normal associate\n"); - notify_wx_assoc_event(ieee); - - netif_carrier_on(ieee->dev); - ieee->is_roaming = false; - if (rtllib_is_54g(&ieee->current_network)) { - ieee->rate = 108; - netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate); - } else { - ieee->rate = 22; - ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B); - netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate); - } - if (ieee->ht_info->current_ht_support && ieee->ht_info->enable_ht) { - netdev_info(ieee->dev, "Successfully associated, ht enabled\n"); - ht_on_assoc_rsp(ieee); - } else { - netdev_info(ieee->dev, - "Successfully associated, ht not enabled(%d, %d)\n", - ieee->ht_info->current_ht_support, - ieee->ht_info->enable_ht); - memset(ieee->dot11ht_oper_rate_set, 0, 16); - } - ieee->link_detect_info.slot_num = 2 * (1 + - ieee->current_network.beacon_interval / - 500); - if (ieee->link_detect_info.num_recv_bcn_in_period == 0 || - ieee->link_detect_info.num_recv_data_in_period == 0) { - ieee->link_detect_info.num_recv_bcn_in_period = 1; - ieee->link_detect_info.num_recv_data_in_period = 1; - } - psc->lps_idle_count = 0; - ieee->link_change(ieee->dev); -} - -static void rtllib_sta_send_associnfo(struct rtllib_device *ieee) -{ -} - -static void rtllib_associate_complete(struct rtllib_device *ieee) -{ - del_timer_sync(&ieee->associate_timer); - - ieee->link_state = MAC80211_LINKED; - rtllib_sta_send_associnfo(ieee); - - schedule_work(&ieee->associate_complete_wq); -} - -static void rtllib_associate_procedure_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, - associate_procedure_wq); - rtllib_stop_scan_syncro(ieee); - ieee->rtllib_ips_leave(ieee->dev); - mutex_lock(&ieee->wx_mutex); - - rtllib_stop_scan(ieee); - ht_set_connect_bw_mode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); - if (ieee->rf_power_state == rf_off) { - ieee->rtllib_ips_leave_wq(ieee->dev); - mutex_unlock(&ieee->wx_mutex); - return; - } - ieee->associate_seq = 1; - - rtllib_associate_step1(ieee, ieee->current_network.bssid); - - mutex_unlock(&ieee->wx_mutex); -} - -inline void rtllib_softmac_new_net(struct rtllib_device *ieee, - struct rtllib_network *net) -{ - u8 tmp_ssid[IW_ESSID_MAX_SIZE + 1]; - int tmp_ssid_len = 0; - - short apset, ssidset, ssidbroad, apmatch, ssidmatch; - - /* we are interested in new only if we are not associated - * and we are not associating / authenticating - */ - if (ieee->link_state != MAC80211_NOLINK) - return; - - if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & - WLAN_CAPABILITY_ESS)) - return; - - if (ieee->iw_mode == IW_MODE_INFRA) { - /* if the user specified the AP MAC, we need also the essid - * This could be obtained by beacons or, if the network does not - * broadcast it, it can be put manually. - */ - apset = ieee->wap_set; - ssidset = ieee->ssid_set; - ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0'); - apmatch = (memcmp(ieee->current_network.bssid, net->bssid, - ETH_ALEN) == 0); - if (!ssidbroad) { - ssidmatch = (ieee->current_network.ssid_len == - net->hidden_ssid_len) && - (!strncmp(ieee->current_network.ssid, - net->hidden_ssid, net->hidden_ssid_len)); - if (net->hidden_ssid_len > 0) { - strncpy(net->ssid, net->hidden_ssid, - net->hidden_ssid_len); - net->ssid_len = net->hidden_ssid_len; - ssidbroad = 1; - } - } else { - ssidmatch = - (ieee->current_network.ssid_len == net->ssid_len) && - (!strncmp(ieee->current_network.ssid, net->ssid, - net->ssid_len)); - } - - /* if the user set the AP check if match. - * if the network does not broadcast essid we check the - * user supplied ANY essid - * if the network does broadcast and the user does not set - * essid it is OK - * if the network does broadcast and the user did set essid - * check if essid match - * if the ap is not set, check that the user set the bssid - * and the network does broadcast and that those two bssid match - */ - if ((apset && apmatch && - ((ssidset && ssidbroad && ssidmatch) || - (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || - (!apset && ssidset && ssidbroad && ssidmatch) || - (ieee->is_roaming && ssidset && ssidbroad && ssidmatch)) { - /* Save the essid so that if it is hidden, it is - * replaced with the essid provided by the user. - */ - if (!ssidbroad) { - memcpy(tmp_ssid, ieee->current_network.ssid, - ieee->current_network.ssid_len); - tmp_ssid_len = ieee->current_network.ssid_len; - } - memcpy(&ieee->current_network, net, - sizeof(ieee->current_network)); - if (!ssidbroad) { - memcpy(ieee->current_network.ssid, tmp_ssid, - tmp_ssid_len); - ieee->current_network.ssid_len = tmp_ssid_len; - } - netdev_info(ieee->dev, - "Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x cur_net.flags:0x%x\n", - ieee->current_network.ssid, - ieee->current_network.channel, - ieee->current_network.qos_data.supported, - ieee->ht_info->enable_ht, - ieee->current_network.bssht.bd_support_ht, - ieee->current_network.mode, - ieee->current_network.flags); - - if ((rtllib_act_scanning(ieee, false)) && - !(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) - rtllib_stop_scan_syncro(ieee); - - ht_reset_iot_setting(ieee->ht_info); - ieee->wmm_acm = 0; - if (ieee->iw_mode == IW_MODE_INFRA) { - /* Join the network for the first time */ - ieee->asoc_retry_count = 0; - if ((ieee->current_network.qos_data.supported == 1) && - ieee->current_network.bssht.bd_support_ht) - ht_reset_self_and_save_peer_setting(ieee, - &ieee->current_network); - else - ieee->ht_info->current_ht_support = false; - - ieee->link_state = RTLLIB_ASSOCIATING; - schedule_delayed_work(&ieee->associate_procedure_wq, 0); - } else { - if (rtllib_is_54g(&ieee->current_network)) { - ieee->rate = 108; - ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G); - netdev_info(ieee->dev, - "Using G rates\n"); - } else { - ieee->rate = 22; - ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_B); - netdev_info(ieee->dev, - "Using B rates\n"); - } - memset(ieee->dot11ht_oper_rate_set, 0, 16); - ieee->link_state = MAC80211_LINKED; - } - } - } -} - -static void rtllib_softmac_check_all_nets(struct rtllib_device *ieee) -{ - unsigned long flags; - struct rtllib_network *target; - - spin_lock_irqsave(&ieee->lock, flags); - - list_for_each_entry(target, &ieee->network_list, list) { - /* if the state become different that NOLINK means - * we had found what we are searching for - */ - - if (ieee->link_state != MAC80211_NOLINK) - break; - - if (ieee->scan_age == 0 || time_after(target->last_scanned + - ieee->scan_age, jiffies)) - rtllib_softmac_new_net(ieee, target); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static inline int auth_parse(struct net_device *dev, struct sk_buff *skb, - u8 **challenge, int *chlen) -{ - struct rtllib_authentication *a; - u8 *t; - - if (skb->len < (sizeof(struct rtllib_authentication) - - sizeof(struct rtllib_info_element))) { - netdev_dbg(dev, "invalid len in auth resp: %d\n", skb->len); - return -EINVAL; - } - *challenge = NULL; - a = (struct rtllib_authentication *)skb->data; - if (skb->len > (sizeof(struct rtllib_authentication) + 3)) { - t = skb->data + sizeof(struct rtllib_authentication); - - if (*(t++) == MFIE_TYPE_CHALLENGE) { - *chlen = *(t++); - *challenge = kmemdup(t, *chlen, GFP_ATOMIC); - if (!*challenge) - return -ENOMEM; - } - } - - if (a->status) { - netdev_dbg(dev, "auth_parse() failed\n"); - return -EINVAL; - } - - return 0; -} - -static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb, - int *aid) -{ - struct rtllib_assoc_response_frame *response_head; - u16 status_code; - - if (skb->len < sizeof(struct rtllib_assoc_response_frame)) { - netdev_dbg(ieee->dev, "Invalid len in auth resp: %d\n", - skb->len); - return 0xcafe; - } - - response_head = (struct rtllib_assoc_response_frame *)skb->data; - *aid = le16_to_cpu(response_head->aid) & 0x3fff; - - status_code = le16_to_cpu(response_head->status); - if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES || - status_code == WLAN_STATUS_CAPS_UNSUPPORTED) && - ((ieee->mode == WIRELESS_MODE_G) && - (ieee->current_network.mode == WIRELESS_MODE_N_24G) && - (ieee->asoc_retry_count++ < (RT_ASOC_RETRY_LIMIT - 1)))) { - ieee->ht_info->iot_action |= HT_IOT_ACT_PURE_N_MODE; - } else { - ieee->asoc_retry_count = 0; - } - - return le16_to_cpu(response_head->status); -} - -void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr) -{ - struct sk_buff *buf = rtllib_null_func(ieee, pwr); - - if (buf) - softmac_ps_mgmt_xmit(buf, ieee); -} -EXPORT_SYMBOL(rtllib_sta_ps_send_null_frame); - -void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee) -{ - struct sk_buff *buf = rtllib_pspoll_func(ieee); - - if (buf) - softmac_ps_mgmt_xmit(buf, ieee); -} - -static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time) -{ - int timeout; - u8 dtim; - struct rt_pwr_save_ctrl *psc = &ieee->pwr_save_ctrl; - - if (ieee->lps_delay_cnt) { - ieee->lps_delay_cnt--; - return 0; - } - - dtim = ieee->current_network.dtim_data; - if (!(dtim & RTLLIB_DTIM_VALID)) - return 0; - timeout = ieee->current_network.beacon_interval; - ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID; - /* there's no need to notify AP that I find you buffered - * with broadcast packet - */ - if (dtim & (RTLLIB_DTIM_UCAST & ieee->ps)) - return 2; - - if (!time_after(jiffies, - dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout))) - return 0; - if (!time_after(jiffies, - ieee->last_rx_ps_time + msecs_to_jiffies(timeout))) - return 0; - if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) && - (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) - return 0; - - if (time) { - if (ieee->awake_pkt_sent) { - psc->lps_awake_intvl = 1; - } else { - u8 max_period = 5; - - if (psc->lps_awake_intvl == 0) - psc->lps_awake_intvl = 1; - psc->lps_awake_intvl = (psc->lps_awake_intvl >= - max_period) ? max_period : - (psc->lps_awake_intvl + 1); - } - { - u8 lps_awake_intvl_tmp = 0; - u8 period = ieee->current_network.dtim_period; - u8 count = ieee->current_network.tim.tim_count; - - if (count == 0) { - if (psc->lps_awake_intvl > period) - lps_awake_intvl_tmp = period + - (psc->lps_awake_intvl - - period) - - ((psc->lps_awake_intvl - period) % - period); - else - lps_awake_intvl_tmp = psc->lps_awake_intvl; - - } else { - if (psc->lps_awake_intvl > - ieee->current_network.tim.tim_count) - lps_awake_intvl_tmp = count + - (psc->lps_awake_intvl - count) - - ((psc->lps_awake_intvl - count) % period); - else - lps_awake_intvl_tmp = psc->lps_awake_intvl; - } - - *time = ieee->current_network.last_dtim_sta_time - + msecs_to_jiffies(ieee->current_network.beacon_interval * - lps_awake_intvl_tmp); - } - } - - return 1; -} - -static inline void rtllib_sta_ps(struct work_struct *work) -{ - struct rtllib_device *ieee; - u64 time; - short sleep; - unsigned long flags, flags2; - - ieee = container_of(work, struct rtllib_device, ps_task); - - spin_lock_irqsave(&ieee->lock, flags); - - if ((ieee->ps == RTLLIB_PS_DISABLED || - ieee->iw_mode != IW_MODE_INFRA || - ieee->link_state != MAC80211_LINKED)) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - rtllib_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - sleep = rtllib_sta_ps_sleep(ieee, &time); - /* 2 wake, 1 sleep, 0 do nothing */ - if (sleep == 0) - goto out; - if (sleep == 1) { - if (ieee->sta_sleep == LPS_IS_SLEEP) { - ieee->enter_sleep_state(ieee->dev, time); - } else if (ieee->sta_sleep == LPS_IS_WAKE) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - if (ieee->ps_is_queue_empty(ieee->dev)) { - ieee->sta_sleep = LPS_WAIT_NULL_DATA_SEND; - ieee->ack_tx_to_ieee = 1; - rtllib_sta_ps_send_null_frame(ieee, 1); - ieee->ps_time = time; - } - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - - ieee->awake_pkt_sent = false; - - } else if (sleep == 2) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - rtllib_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - -out: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl) -{ - if (ieee->sta_sleep == LPS_IS_WAKE) { - if (nl) { - if (ieee->ht_info->iot_action & - HT_IOT_ACT_NULL_DATA_POWER_SAVING) { - ieee->ack_tx_to_ieee = 1; - rtllib_sta_ps_send_null_frame(ieee, 0); - } else { - ieee->ack_tx_to_ieee = 1; - rtllib_sta_ps_send_pspoll_frame(ieee); - } - } - return; - } - - if (ieee->sta_sleep == LPS_IS_SLEEP) - ieee->sta_wake_up(ieee->dev); - if (nl) { - if (ieee->ht_info->iot_action & - HT_IOT_ACT_NULL_DATA_POWER_SAVING) { - ieee->ack_tx_to_ieee = 1; - rtllib_sta_ps_send_null_frame(ieee, 0); - } else { - ieee->ack_tx_to_ieee = 1; - ieee->polling = true; - rtllib_sta_ps_send_pspoll_frame(ieee); - } - - } else { - ieee->sta_sleep = LPS_IS_WAKE; - ieee->polling = false; - } -} - -void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success) -{ - unsigned long flags, flags2; - - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->sta_sleep == LPS_WAIT_NULL_DATA_SEND) { - /* Null frame with PS bit set */ - if (success) { - ieee->sta_sleep = LPS_IS_SLEEP; - ieee->enter_sleep_state(ieee->dev, ieee->ps_time); - } - /* if the card report not success we can't be sure the AP - * has not RXed so we can't assume the AP believe us awake - */ - } else {/* 21112005 - tx again null without PS bit if lost */ - - if ((ieee->sta_sleep == LPS_IS_WAKE) && !success) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - if (ieee->ht_info->iot_action & - HT_IOT_ACT_NULL_DATA_POWER_SAVING) - rtllib_sta_ps_send_null_frame(ieee, 0); - else - rtllib_sta_ps_send_pspoll_frame(ieee); - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); -} -EXPORT_SYMBOL(rtllib_ps_tx_ack); - -static void rtllib_process_action(struct rtllib_device *ieee, - struct sk_buff *skb) -{ - u8 *act = skb->data + RTLLIB_3ADDR_LEN; - u8 category = 0; - - category = *act; - act++; - switch (category) { - case ACT_CAT_BA: - switch (*act) { - case ACT_ADDBAREQ: - rtllib_rx_add_ba_req(ieee, skb); - break; - case ACT_ADDBARSP: - rtllib_rx_add_ba_rsp(ieee, skb); - break; - case ACT_DELBA: - rtllib_rx_DELBA(ieee, skb); - break; - } - break; - default: - break; - } -} - -static inline int -rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - u16 errcode; - int aid; - u8 *ies; - struct rtllib_assoc_response_frame *assoc_resp; - struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *)skb->data; - u16 frame_ctl = le16_to_cpu(header->frame_control); - - netdev_dbg(ieee->dev, "received [RE]ASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(frame_ctl)); - - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATED && - (ieee->iw_mode == IW_MODE_INFRA)) { - errcode = assoc_parse(ieee, skb, &aid); - if (!errcode) { - struct rtllib_network *network = - kzalloc(sizeof(struct rtllib_network), - GFP_ATOMIC); - - if (!network) - return 1; - ieee->link_state = MAC80211_LINKED; - ieee->assoc_id = aid; - ieee->softmac_stats.rx_ass_ok++; - /* station support qos */ - /* Let the register setting default with Legacy station */ - assoc_resp = (struct rtllib_assoc_response_frame *)skb->data; - if (ieee->current_network.qos_data.supported == 1) { - if (rtllib_parse_info_param(ieee, assoc_resp->info_element, - rx_stats->len - sizeof(*assoc_resp), - network, rx_stats)) { - kfree(network); - return 1; - } - memcpy(ieee->ht_info->peer_ht_cap_buf, - network->bssht.bd_ht_cap_buf, - network->bssht.bd_ht_cap_len); - memcpy(ieee->ht_info->peer_ht_info_buf, - network->bssht.bd_ht_info_buf, - network->bssht.bd_ht_info_len); - ieee->handle_assoc_response(ieee->dev, - (struct rtllib_assoc_response_frame *)header, network); - } - kfree(network); - - kfree(ieee->assocresp_ies); - ieee->assocresp_ies = NULL; - ies = &assoc_resp->info_element[0].id; - ieee->assocresp_ies_len = (skb->data + skb->len) - ies; - ieee->assocresp_ies = kmemdup(ies, - ieee->assocresp_ies_len, - GFP_ATOMIC); - if (!ieee->assocresp_ies) - ieee->assocresp_ies_len = 0; - - rtllib_associate_complete(ieee); - } else { - /* aid could not been allocated */ - ieee->softmac_stats.rx_ass_err++; - netdev_info(ieee->dev, - "Association response status code 0x%x\n", - errcode); - if (ieee->asoc_retry_count < RT_ASOC_RETRY_LIMIT) - schedule_delayed_work(&ieee->associate_procedure_wq, 0); - else - rtllib_associate_abort(ieee); - } - } - return 0; -} - -static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb) -{ - int errcode; - u8 *challenge; - int chlen = 0; - bool support_nmode = true, half_support_nmode = false; - - errcode = auth_parse(ieee->dev, skb, &challenge, &chlen); - - if (errcode) { - ieee->softmac_stats.rx_auth_rs_err++; - netdev_info(ieee->dev, - "Authentication response status code %d", errcode); - rtllib_associate_abort(ieee); - return; - } - - if (ieee->open_wep || !challenge) { - ieee->link_state = RTLLIB_ASSOCIATING_AUTHENTICATED; - ieee->softmac_stats.rx_auth_rs_ok++; - if (!(ieee->ht_info->iot_action & HT_IOT_ACT_PURE_N_MODE)) { - if (!ieee->get_nmode_support_by_sec_cfg(ieee->dev)) { - if (is_ht_half_nmode_aps(ieee)) { - support_nmode = true; - half_support_nmode = true; - } else { - support_nmode = false; - half_support_nmode = false; - } - } - } - /* Dummy wirless mode setting to avoid encryption issue */ - if (support_nmode) { - ieee->set_wireless_mode(ieee->dev, - ieee->current_network.mode); - } else { - /*TODO*/ - ieee->set_wireless_mode(ieee->dev, WIRELESS_MODE_G); - } - - if ((ieee->current_network.mode == WIRELESS_MODE_N_24G) && - half_support_nmode) { - netdev_info(ieee->dev, "======>enter half N mode\n"); - ieee->half_wireless_n24g_mode = true; - } else { - ieee->half_wireless_n24g_mode = false; - } - rtllib_associate_step2(ieee); - } else { - rtllib_auth_challenge(ieee, challenge, chlen); - } -} - -static inline int -rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { - if (ieee->link_state == RTLLIB_ASSOCIATING_AUTHENTICATING && - (ieee->iw_mode == IW_MODE_INFRA)) { - netdev_dbg(ieee->dev, - "Received authentication response"); - rtllib_rx_auth_resp(ieee, skb); - } - } - return 0; -} - -static inline int -rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) -{ - struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *)skb->data; - u16 frame_ctl; - - if (memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0) - return 0; - - /* FIXME for now repeat all the association procedure - * both for disassociation and deauthentication - */ - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->link_state == MAC80211_LINKED && - (ieee->iw_mode == IW_MODE_INFRA)) { - frame_ctl = le16_to_cpu(header->frame_control); - netdev_info(ieee->dev, - "==========>received disassoc/deauth(%x) frame, reason code:%x\n", - WLAN_FC_GET_STYPE(frame_ctl), - ((struct rtllib_disassoc *)skb->data)->reason); - ieee->link_state = RTLLIB_ASSOCIATING; - ieee->softmac_stats.reassoc++; - ieee->is_roaming = true; - ieee->link_detect_info.busy_traffic = false; - rtllib_disassociate(ieee); - remove_peer_ts(ieee, header->addr2); - if (!(ieee->rtllib_ap_sec_type(ieee) & (SEC_ALG_CCMP | SEC_ALG_TKIP))) - schedule_delayed_work(&ieee->associate_procedure_wq, 5); - } - return 0; -} - -inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee, - struct sk_buff *skb, - struct rtllib_rx_stats *rx_stats, u16 type, - u16 stype) -{ - struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *)skb->data; - u16 frame_ctl; - - if (!ieee->proto_started) - return 0; - - frame_ctl = le16_to_cpu(header->frame_control); - switch (WLAN_FC_GET_STYPE(frame_ctl)) { - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - if (rtllib_rx_assoc_resp(ieee, skb, rx_stats) == 1) - return 1; - break; - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - break; - case IEEE80211_STYPE_AUTH: - rtllib_rx_auth(ieee, skb, rx_stats); - break; - case IEEE80211_STYPE_DISASSOC: - case IEEE80211_STYPE_DEAUTH: - rtllib_rx_deauth(ieee, skb); - break; - case IEEE80211_STYPE_ACTION: - rtllib_process_action(ieee, skb); - break; - default: - return -1; - } - return 0; -} - -/* following are for a simpler TX queue management. - * Instead of using netif_[stop/wake]_queue the driver - * will use these two functions (plus a reset one), that - * will internally use the kernel netif_* and takes - * care of the ieee802.11 fragmentation. - * So the driver receives a fragment per time and might - * call the stop function when it wants to not - * have enough room to TX an entire packet. - * This might be useful if each fragment needs it's own - * descriptor, thus just keep a total free memory > than - * the max fragmentation threshold is not enough.. If the - * ieee802.11 stack passed a TXB struct then you need - * to keep N free descriptors where - * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD - * In this way you need just one and the 802.11 stack - * will take care of buffering fragments and pass them to - * the driver later, when it wakes the queue. - */ -void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee) -{ - unsigned int queue_index = txb->queue_index; - unsigned long flags; - int i; - struct cb_desc *tcb_desc = NULL; - unsigned long queue_len = 0; - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd param 0, no tx mgmt lock required */ - rtllib_sta_wakeup(ieee, 0); - - /* update the tx status */ - tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + - MAX_DEV_ADDR_SIZE); - if (tcb_desc->multicast) - ieee->stats.multicast++; - - /* if xmit available, just xmit it immediately, else just insert it to - * the wait queue - */ - for (i = 0; i < txb->nr_frags; i++) { - queue_len = skb_queue_len(&ieee->skb_waitq[queue_index]); - if ((queue_len != 0) || - (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) || - (ieee->queue_stop)) { - /* insert the skb packet to the wait queue - * as for the completion function, it does not need - * to check it any more. - */ - if (queue_len < 200) - skb_queue_tail(&ieee->skb_waitq[queue_index], - txb->fragments[i]); - else - kfree_skb(txb->fragments[i]); - } else { - ieee->softmac_data_hard_start_xmit(txb->fragments[i], - ieee->dev, ieee->rate); - } - } - - rtllib_txb_free(txb); - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void rtllib_reset_queue(struct rtllib_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - init_mgmt_queue(ieee); - if (ieee->tx_pending.txb) { - rtllib_txb_free(ieee->tx_pending.txb); - ieee->tx_pending.txb = NULL; - } - ieee->queue_stop = 0; - spin_unlock_irqrestore(&ieee->lock, flags); -} -EXPORT_SYMBOL(rtllib_reset_queue); - -void rtllib_stop_all_queues(struct rtllib_device *ieee) -{ - unsigned int i; - - for (i = 0; i < ieee->dev->num_tx_queues; i++) - txq_trans_cond_update(netdev_get_tx_queue(ieee->dev, i)); - - netif_tx_stop_all_queues(ieee->dev); -} - -void rtllib_wake_all_queues(struct rtllib_device *ieee) -{ - netif_tx_wake_all_queues(ieee->dev); -} - -/* this is called only in user context, with wx_mutex held */ -static void rtllib_start_bss(struct rtllib_device *ieee) -{ - unsigned long flags; - - /* check if we have already found the net we - * are interested in (if any). - * if not (we are disassociated and we are not - * in associating / authenticating phase) start the background scanning. - */ - rtllib_softmac_check_all_nets(ieee); - - /* ensure no-one start an associating process (thus setting - * the ieee->link_state to rtllib_ASSOCIATING) while we - * have just checked it and we are going to enable scan. - * The rtllib_new_net function is always called with - * lock held (from both rtllib_softmac_check_all_nets and - * the rx path), so we cannot be in the middle of such function - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->link_state == MAC80211_NOLINK) - rtllib_start_scan(ieee); - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static void rtllib_link_change_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, link_change_wq); - ieee->link_change(ieee->dev); -} - -/* called only in userspace context */ -void rtllib_disassociate(struct rtllib_device *ieee) -{ - netif_carrier_off(ieee->dev); - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) - rtllib_reset_queue(ieee); - - ieee->link_state = MAC80211_NOLINK; - ieee->is_set_key = false; - ieee->wap_set = 0; - - schedule_delayed_work(&ieee->link_change_wq, 0); - - notify_wx_assoc_event(ieee); -} - -static void rtllib_associate_retry_wq(void *data) -{ - struct rtllib_device *ieee = container_of_dwork_rsl(data, - struct rtllib_device, associate_retry_wq); - unsigned long flags; - - mutex_lock(&ieee->wx_mutex); - if (!ieee->proto_started) - goto exit; - - if (ieee->link_state != RTLLIB_ASSOCIATING_RETRY) - goto exit; - - /* until we do not set the state to MAC80211_NOLINK - * there are no possibility to have someone else trying - * to start an association procedure (we get here with - * ieee->link_state = RTLLIB_ASSOCIATING). - * When we set the state to MAC80211_NOLINK it is possible - * that the RX path run an attempt to associate, but - * both rtllib_softmac_check_all_nets and the - * RX path works with ieee->lock held so there are no - * problems. If we are still disassociated then start a scan. - * the lock here is necessary to ensure no one try to start - * an association procedure when we have just checked the - * state and we are going to start the scan. - */ - ieee->beinretry = true; - ieee->link_state = MAC80211_NOLINK; - - rtllib_softmac_check_all_nets(ieee); - - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->link_state == MAC80211_NOLINK) - rtllib_start_scan(ieee); - spin_unlock_irqrestore(&ieee->lock, flags); - - ieee->beinretry = false; -exit: - mutex_unlock(&ieee->wx_mutex); -} - -void rtllib_softmac_stop_protocol(struct rtllib_device *ieee) -{ - rtllib_stop_scan_syncro(ieee); - mutex_lock(&ieee->wx_mutex); - rtllib_stop_protocol(ieee); - mutex_unlock(&ieee->wx_mutex); -} -EXPORT_SYMBOL(rtllib_softmac_stop_protocol); - -void rtllib_stop_protocol(struct rtllib_device *ieee) -{ - if (!ieee->proto_started) - return; - - ieee->proto_started = 0; - ieee->proto_stoppping = 1; - ieee->rtllib_ips_leave(ieee->dev); - - del_timer_sync(&ieee->associate_timer); - mutex_unlock(&ieee->wx_mutex); - cancel_delayed_work_sync(&ieee->associate_retry_wq); - mutex_lock(&ieee->wx_mutex); - cancel_delayed_work_sync(&ieee->link_change_wq); - rtllib_stop_scan(ieee); - - if (ieee->link_state <= RTLLIB_ASSOCIATING_AUTHENTICATED) - ieee->link_state = MAC80211_NOLINK; - - if (ieee->link_state == MAC80211_LINKED) { - if (ieee->iw_mode == IW_MODE_INFRA) - send_disassociation(ieee, 1, WLAN_REASON_DEAUTH_LEAVING); - rtllib_disassociate(ieee); - } - - remove_all_ts(ieee); - ieee->proto_stoppping = 0; - - kfree(ieee->assocreq_ies); - ieee->assocreq_ies = NULL; - ieee->assocreq_ies_len = 0; - kfree(ieee->assocresp_ies); - ieee->assocresp_ies = NULL; - ieee->assocresp_ies_len = 0; -} - -void rtllib_softmac_start_protocol(struct rtllib_device *ieee) -{ - mutex_lock(&ieee->wx_mutex); - rtllib_start_protocol(ieee); - mutex_unlock(&ieee->wx_mutex); -} -EXPORT_SYMBOL(rtllib_softmac_start_protocol); - -void rtllib_start_protocol(struct rtllib_device *ieee) -{ - short ch = 0; - int i = 0; - - if (ieee->proto_started) - return; - - ieee->proto_started = 1; - - if (ieee->current_network.channel == 0) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - return; /* no channel found */ - } while (!ieee->active_channel_map[ch]); - ieee->current_network.channel = ch; - } - - if (ieee->current_network.beacon_interval == 0) - ieee->current_network.beacon_interval = 100; - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } - - ieee->wmm_acm = 0; - /* if the user set the MAC of the ad-hoc cell and then - * switch to managed mode, shall we make sure that association - * attempts does not fail just because the user provide the essid - * and the nic is still checking for the AP MAC ?? - */ - switch (ieee->iw_mode) { - case IW_MODE_INFRA: - rtllib_start_bss(ieee); - break; - } -} - -int rtllib_softmac_init(struct rtllib_device *ieee) -{ - int i; - - memset(&ieee->current_network, 0, sizeof(struct rtllib_network)); - - ieee->link_state = MAC80211_NOLINK; - for (i = 0; i < 5; i++) - ieee->seq_ctrl[i] = 0; - - ieee->link_detect_info.slot_index = 0; - ieee->link_detect_info.slot_num = 2; - ieee->link_detect_info.num_recv_bcn_in_period = 0; - ieee->link_detect_info.num_recv_data_in_period = 0; - ieee->link_detect_info.num_tx_ok_in_period = 0; - ieee->link_detect_info.num_rx_ok_in_period = 0; - ieee->link_detect_info.num_rx_unicast_ok_in_period = 0; - ieee->is_aggregate_frame = false; - ieee->assoc_id = 0; - ieee->queue_stop = 0; - ieee->scanning_continue = 0; - ieee->softmac_features = 0; - ieee->wap_set = 0; - ieee->ssid_set = 0; - ieee->proto_started = 0; - ieee->proto_stoppping = 0; - ieee->basic_rate = RTLLIB_DEFAULT_BASIC_RATE; - ieee->rate = 22; - ieee->ps = RTLLIB_PS_DISABLED; - ieee->sta_sleep = LPS_IS_WAKE; - - ieee->reg_dot11ht_oper_rate_set[0] = 0xff; - ieee->reg_dot11ht_oper_rate_set[1] = 0xff; - ieee->reg_dot11ht_oper_rate_set[4] = 0x01; - - ieee->reg_dot11tx_ht_oper_rate_set[0] = 0xff; - ieee->reg_dot11tx_ht_oper_rate_set[1] = 0xff; - ieee->reg_dot11tx_ht_oper_rate_set[4] = 0x01; - - ieee->first_ie_in_scan = false; - ieee->actscanning = false; - ieee->beinretry = false; - ieee->is_set_key = false; - init_mgmt_queue(ieee); - - ieee->tx_pending.txb = NULL; - - timer_setup(&ieee->associate_timer, rtllib_associate_abort_cb, 0); - - INIT_DELAYED_WORK(&ieee->link_change_wq, (void *)rtllib_link_change_wq); - INIT_WORK(&ieee->associate_complete_wq, (void *)rtllib_associate_complete_wq); - INIT_DELAYED_WORK(&ieee->associate_procedure_wq, (void *)rtllib_associate_procedure_wq); - INIT_DELAYED_WORK(&ieee->softmac_scan_wq, (void *)rtllib_softmac_scan_wq); - INIT_DELAYED_WORK(&ieee->associate_retry_wq, (void *)rtllib_associate_retry_wq); - INIT_WORK(&ieee->wx_sync_scan_wq, (void *)rtllib_wx_sync_scan_wq); - - mutex_init(&ieee->wx_mutex); - mutex_init(&ieee->scan_mutex); - mutex_init(&ieee->ips_mutex); - - spin_lock_init(&ieee->mgmt_tx_lock); - spin_lock_init(&ieee->beacon_lock); - - INIT_WORK(&ieee->ps_task, rtllib_sta_ps); - - return 0; -} - -void rtllib_softmac_free(struct rtllib_device *ieee) -{ - del_timer_sync(&ieee->associate_timer); - - cancel_delayed_work_sync(&ieee->associate_retry_wq); - cancel_delayed_work_sync(&ieee->associate_procedure_wq); - cancel_delayed_work_sync(&ieee->softmac_scan_wq); - cancel_delayed_work_sync(&ieee->hw_wakeup_wq); - cancel_delayed_work_sync(&ieee->hw_sleep_wq); - cancel_delayed_work_sync(&ieee->link_change_wq); - cancel_work_sync(&ieee->associate_complete_wq); - cancel_work_sync(&ieee->ips_leave_wq); - cancel_work_sync(&ieee->wx_sync_scan_wq); - cancel_work_sync(&ieee->ps_task); -} - -static inline struct sk_buff * -rtllib_disauth_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 rsn) -{ - struct sk_buff *skb; - struct rtllib_disauth *disauth; - int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom; - - skb = dev_alloc_skb(len); - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - disauth = skb_put(skb, sizeof(struct rtllib_disauth)); - disauth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DEAUTH); - disauth->header.duration_id = 0; - - ether_addr_copy(disauth->header.addr1, beacon->bssid); - ether_addr_copy(disauth->header.addr2, ieee->dev->dev_addr); - ether_addr_copy(disauth->header.addr3, beacon->bssid); - - disauth->reason = cpu_to_le16(rsn); - return skb; -} - -static inline struct sk_buff * -rtllib_disassociate_skb(struct rtllib_network *beacon, - struct rtllib_device *ieee, u16 rsn) -{ - struct sk_buff *skb; - struct rtllib_disassoc *disass; - int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - skb_reserve(skb, ieee->tx_headroom); - - disass = skb_put(skb, sizeof(struct rtllib_disassoc)); - disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); - disass->header.duration_id = 0; - - ether_addr_copy(disass->header.addr1, beacon->bssid); - ether_addr_copy(disass->header.addr2, ieee->dev->dev_addr); - ether_addr_copy(disass->header.addr3, beacon->bssid); - - disass->reason = cpu_to_le16(rsn); - return skb; -} - -void send_disassociation(struct rtllib_device *ieee, bool deauth, u16 rsn) -{ - struct rtllib_network *beacon = &ieee->current_network; - struct sk_buff *skb; - - if (deauth) - skb = rtllib_disauth_skb(beacon, ieee, rsn); - else - skb = rtllib_disassociate_skb(beacon, ieee, rsn); - - if (skb) - softmac_mgmt_xmit(skb, ieee); -} - -u8 rtllib_ap_sec_type(struct rtllib_device *ieee) -{ - static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04}; - static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04}; - int wpa_ie_len = ieee->wpa_ie_len; - struct lib80211_crypt_data *crypt; - int encrypt; - - crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) - || (crypt && crypt->ops && (strcmp(crypt->ops->name, "R-WEP") == 0)); - - /* simply judge */ - if (encrypt && (wpa_ie_len == 0)) { - return SEC_ALG_WEP; - } else if ((wpa_ie_len != 0)) { - if (((ieee->wpa_ie[0] == 0xdd) && - (!memcmp(&ieee->wpa_ie[14], ccmp_ie, 4))) || - ((ieee->wpa_ie[0] == 0x30) && - (!memcmp(&ieee->wpa_ie[10], ccmp_rsn_ie, 4)))) - return SEC_ALG_CCMP; - else - return SEC_ALG_TKIP; - } else { - return SEC_ALG_NONE; - } -} - -static void rtllib_mlme_disassociate_request(struct rtllib_device *rtllib, - u8 *addr, u8 rsn) -{ - u8 i; - u8 op_mode; - - remove_peer_ts(rtllib, addr); - - if (memcmp(rtllib->current_network.bssid, addr, 6) == 0) { - rtllib->link_state = MAC80211_NOLINK; - - for (i = 0; i < 6; i++) - rtllib->current_network.bssid[i] = 0x22; - op_mode = RT_OP_MODE_NO_LINK; - rtllib->op_mode = RT_OP_MODE_NO_LINK; - rtllib->set_hw_reg_handler(rtllib->dev, HW_VAR_MEDIA_STATUS, - (u8 *)(&op_mode)); - rtllib_disassociate(rtllib); - - rtllib->set_hw_reg_handler(rtllib->dev, HW_VAR_BSSID, - rtllib->current_network.bssid); - } -} - -static void rtllib_mgnt_disconnect_ap(struct rtllib_device *rtllib, u8 rsn) -{ - bool filter_out_nonassociated_bssid = false; - - filter_out_nonassociated_bssid = false; - rtllib->set_hw_reg_handler(rtllib->dev, HW_VAR_CECHK_BSSID, - (u8 *)(&filter_out_nonassociated_bssid)); - rtllib_mlme_disassociate_request(rtllib, rtllib->current_network.bssid, - rsn); - - rtllib->link_state = MAC80211_NOLINK; -} - -bool rtllib_mgnt_disconnect(struct rtllib_device *rtllib, u8 rsn) -{ - if (rtllib->ps != RTLLIB_PS_DISABLED) - rtllib->sta_wake_up(rtllib->dev); - - if (rtllib->link_state == MAC80211_LINKED) { - if (rtllib->iw_mode == IW_MODE_INFRA) - rtllib_mgnt_disconnect_ap(rtllib, rsn); - } - - return true; -} -EXPORT_SYMBOL(rtllib_mgnt_disconnect); - -void notify_wx_assoc_event(struct rtllib_device *ieee) -{ - union iwreq_data wrqu; - - if (ieee->cannot_notify) - return; - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (ieee->link_state == MAC80211_LINKED) { - memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, - ETH_ALEN); - } else { - netdev_info(ieee->dev, "%s(): Tell user space disconnected\n", - __func__); - eth_zero_addr(wrqu.ap_addr.sa_data); - } - wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); -} -EXPORT_SYMBOL(notify_wx_assoc_event); diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c deleted file mode 100644 index c59686d68a33..000000000000 --- a/drivers/staging/rtl8192e/rtllib_softmac_wx.c +++ /dev/null @@ -1,534 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com> - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Some pieces of code might be stolen from ipw2100 driver - * copyright of who own it's copyright ;-) - * - * PS wx handler mostly stolen from hostap, copyright who - * own it's copyright ;-) - */ -#include <linux/etherdevice.h> - -#include "rtllib.h" - -int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct iw_freq *fwrq = &wrqu->freq; - - mutex_lock(&ieee->wx_mutex); - - if (ieee->iw_mode == IW_MODE_INFRA) { - ret = 0; - goto out; - } - - /* if setting by freq convert to channel */ - if (fwrq->e == 1) { - if ((fwrq->m >= (int)2.412e8 && - fwrq->m <= (int)2.487e8)) { - fwrq->m = ieee80211_freq_khz_to_channel(fwrq->m / 100); - fwrq->e = 0; - } - } - - if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) { - ret = -EOPNOTSUPP; - goto out; - - } else { /* Set the channel */ - - if (ieee->active_channel_map[fwrq->m] != 1) { - ret = -EINVAL; - goto out; - } - ieee->current_network.channel = fwrq->m; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - } - - ret = 0; -out: - mutex_unlock(&ieee->wx_mutex); - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_freq); - -int rtllib_wx_get_freq(struct rtllib_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct iw_freq *fwrq = &wrqu->freq; - - if (ieee->current_network.channel == 0) - return -1; - fwrq->m = ieee80211_channel_to_freq_khz(ieee->current_network.channel, - NL80211_BAND_2GHZ) * 100; - fwrq->e = 1; - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_freq); - -int rtllib_wx_get_wap(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - unsigned long flags; - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->link_state != MAC80211_LINKED && - ieee->link_state != MAC80211_LINKED_SCANNING && - ieee->wap_set == 0) - - eth_zero_addr(wrqu->ap_addr.sa_data); - else - memcpy(wrqu->ap_addr.sa_data, - ieee->current_network.bssid, ETH_ALEN); - - spin_unlock_irqrestore(&ieee->lock, flags); - - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_wap); - -int rtllib_wx_set_wap(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra) -{ - int ret = 0; - unsigned long flags; - - short ifup = ieee->proto_started; - struct sockaddr *temp = (struct sockaddr *)awrq; - - rtllib_stop_scan_syncro(ieee); - - mutex_lock(&ieee->wx_mutex); - /* use ifconfig hw ether */ - - if (temp->sa_family != ARPHRD_ETHER) { - ret = -EINVAL; - goto out; - } - - if (is_zero_ether_addr(temp->sa_data)) { - spin_lock_irqsave(&ieee->lock, flags); - ether_addr_copy(ieee->current_network.bssid, temp->sa_data); - ieee->wap_set = 0; - spin_unlock_irqrestore(&ieee->lock, flags); - ret = -1; - goto out; - } - - if (ifup) - rtllib_stop_protocol(ieee); - - /* just to avoid to give inconsistent infos in the - * get wx method. not really needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - ieee->cannot_notify = false; - ether_addr_copy(ieee->current_network.bssid, temp->sa_data); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); - - spin_unlock_irqrestore(&ieee->lock, flags); - - if (ifup) - rtllib_start_protocol(ieee); -out: - mutex_unlock(&ieee->wx_mutex); - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_wap); - -int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int len, ret = 0; - unsigned long flags; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->current_network.ssid[0] == '\0' || - ieee->current_network.ssid_len == 0) { - ret = -1; - goto out; - } - - if (ieee->link_state != MAC80211_LINKED && - ieee->link_state != MAC80211_LINKED_SCANNING && - ieee->ssid_set == 0) { - ret = -1; - goto out; - } - len = ieee->current_network.ssid_len; - wrqu->essid.length = len; - strncpy(b, ieee->current_network.ssid, len); - wrqu->essid.flags = 1; - -out: - spin_unlock_irqrestore(&ieee->lock, flags); - - return ret; -} -EXPORT_SYMBOL(rtllib_wx_get_essid); - -int rtllib_wx_set_rate(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u32 target_rate = wrqu->bitrate.value; - - ieee->rate = target_rate / 100000; - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_rate); - -int rtllib_wx_get_rate(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u32 tmp_rate; - - tmp_rate = tx_count_to_data_rate(ieee, - ieee->softmac_stats.CurrentShowTxate); - wrqu->bitrate.value = tmp_rate * 500000; - - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_rate); - -int rtllib_wx_set_rts(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - if (wrqu->rts.disabled || !wrqu->rts.fixed) { - ieee->rts = DEFAULT_RTS_THRESHOLD; - } else { - if (wrqu->rts.value < MIN_RTS_THRESHOLD || - wrqu->rts.value > MAX_RTS_THRESHOLD) - return -EINVAL; - ieee->rts = wrqu->rts.value; - } - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_rts); - -int rtllib_wx_get_rts(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->rts.value = ieee->rts; - wrqu->rts.fixed = 0; /* no auto select */ - wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_rts); - -int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int set_mode_status = 0; - - rtllib_stop_scan_syncro(ieee); - mutex_lock(&ieee->wx_mutex); - switch (wrqu->mode) { - case IW_MODE_MONITOR: - case IW_MODE_INFRA: - break; - case IW_MODE_AUTO: - wrqu->mode = IW_MODE_INFRA; - break; - default: - set_mode_status = -EINVAL; - goto out; - } - - if (wrqu->mode == ieee->iw_mode) - goto out; - - if (wrqu->mode == IW_MODE_MONITOR) { - ieee->dev->type = ARPHRD_IEEE80211; - rtllib_enable_net_monitor_mode(ieee->dev, false); - } else { - ieee->dev->type = ARPHRD_ETHER; - if (ieee->iw_mode == IW_MODE_MONITOR) - rtllib_disable_net_monitor_mode(ieee->dev, false); - } - - if (!ieee->proto_started) { - ieee->iw_mode = wrqu->mode; - } else { - rtllib_stop_protocol(ieee); - ieee->iw_mode = wrqu->mode; - rtllib_start_protocol(ieee); - } - -out: - mutex_unlock(&ieee->wx_mutex); - return set_mode_status; -} -EXPORT_SYMBOL(rtllib_wx_set_mode); - -void rtllib_wx_sync_scan_wq(void *data) -{ - struct rtllib_device *ieee = container_of(data, struct rtllib_device, wx_sync_scan_wq); - short chan; - enum ht_extchnl_offset chan_offset = 0; - enum ht_channel_width bandwidth = 0; - int b40M = 0; - - mutex_lock(&ieee->wx_mutex); - if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { - rtllib_start_scan_syncro(ieee); - goto out; - } - - chan = ieee->current_network.channel; - - ieee->leisure_ps_leave(ieee->dev); - /* notify AP to be in PS mode */ - rtllib_sta_ps_send_null_frame(ieee, 1); - rtllib_sta_ps_send_null_frame(ieee, 1); - - rtllib_stop_all_queues(ieee); - ieee->link_state = MAC80211_LINKED_SCANNING; - ieee->link_change(ieee->dev); - /* wait for ps packet to be kicked out successfully */ - msleep(50); - - ieee->scan_operation_backup_handler(ieee->dev, SCAN_OPT_BACKUP); - - if (ieee->ht_info->current_ht_support && ieee->ht_info->enable_ht && - ieee->ht_info->cur_bw_40mhz) { - b40M = 1; - chan_offset = ieee->ht_info->cur_sta_ext_chnl_offset; - bandwidth = (enum ht_channel_width)ieee->ht_info->cur_bw_40mhz; - ieee->set_bw_mode_handler(ieee->dev, HT_CHANNEL_WIDTH_20, - HT_EXTCHNL_OFFSET_NO_EXT); - } - - rtllib_start_scan_syncro(ieee); - - if (b40M) { - if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) - ieee->set_chan(ieee->dev, chan + 2); - else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) - ieee->set_chan(ieee->dev, chan - 2); - else - ieee->set_chan(ieee->dev, chan); - ieee->set_bw_mode_handler(ieee->dev, bandwidth, chan_offset); - } else { - ieee->set_chan(ieee->dev, chan); - } - - ieee->scan_operation_backup_handler(ieee->dev, SCAN_OPT_RESTORE); - - ieee->link_state = MAC80211_LINKED; - ieee->link_change(ieee->dev); - - /* Notify AP that I wake up again */ - rtllib_sta_ps_send_null_frame(ieee, 0); - - if (ieee->link_detect_info.num_recv_bcn_in_period == 0 || - ieee->link_detect_info.num_recv_data_in_period == 0) { - ieee->link_detect_info.num_recv_bcn_in_period = 1; - ieee->link_detect_info.num_recv_data_in_period = 1; - } - rtllib_wake_all_queues(ieee); - -out: - mutex_unlock(&ieee->wx_mutex); -} - -int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret = 0; - - if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { - ret = -1; - goto out; - } - - if (ieee->link_state == MAC80211_LINKED) { - schedule_work(&ieee->wx_sync_scan_wq); - /* intentionally forget to up sem */ - return 0; - } - -out: - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_scan); - -int rtllib_wx_set_essid(struct rtllib_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0, len; - short proto_started; - unsigned long flags; - - rtllib_stop_scan_syncro(ieee); - mutex_lock(&ieee->wx_mutex); - - proto_started = ieee->proto_started; - - len = min_t(__u16, wrqu->essid.length, IW_ESSID_MAX_SIZE); - - if (ieee->iw_mode == IW_MODE_MONITOR) { - ret = -1; - goto out; - } - - if (proto_started) - rtllib_stop_protocol(ieee); - - /* this is just to be sure that the GET wx callback - * has consistent infos. not needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (wrqu->essid.flags && wrqu->essid.length) { - strncpy(ieee->current_network.ssid, extra, len); - ieee->current_network.ssid_len = len; - ieee->cannot_notify = false; - ieee->ssid_set = 1; - } else { - ieee->ssid_set = 0; - ieee->current_network.ssid[0] = '\0'; - ieee->current_network.ssid_len = 0; - } - spin_unlock_irqrestore(&ieee->lock, flags); - - if (proto_started) - rtllib_start_protocol(ieee); -out: - mutex_unlock(&ieee->wx_mutex); - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_essid); - -int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - wrqu->mode = ieee->iw_mode; - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_mode); - -int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - const char *n = ieee->mode & (WIRELESS_MODE_N_24G) ? "n" : ""; - - scnprintf(wrqu->name, sizeof(wrqu->name), "802.11bg%s", n); - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_name); - -/* this is mostly stolen from hostap */ -int rtllib_wx_set_power(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - - if ((!ieee->sta_wake_up) || - (!ieee->enter_sleep_state) || - (!ieee->ps_is_queue_empty)) { - netdev_warn(ieee->dev, - "%s(): PS mode is tried to be use but driver missed a callback\n", - __func__); - return -1; - } - - mutex_lock(&ieee->wx_mutex); - - if (wrqu->power.disabled) { - ieee->ps = RTLLIB_PS_DISABLED; - goto exit; - } - if (wrqu->power.flags & IW_POWER_TIMEOUT) - ieee->ps_timeout = wrqu->power.value / 1000; - - if (wrqu->power.flags & IW_POWER_PERIOD) - ieee->ps_period = wrqu->power.value / 1000; - - switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - ieee->ps = RTLLIB_PS_UNICAST; - break; - case IW_POWER_MULTICAST_R: - ieee->ps = RTLLIB_PS_MBCAST; - break; - case IW_POWER_ALL_R: - ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST; - break; - - case IW_POWER_ON: - break; - - default: - ret = -EINVAL; - goto exit; - } -exit: - mutex_unlock(&ieee->wx_mutex); - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_power); - -/* this is stolen from hostap */ -int rtllib_wx_get_power(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - mutex_lock(&ieee->wx_mutex); - - if (ieee->ps == RTLLIB_PS_DISABLED) { - wrqu->power.disabled = 1; - goto exit; - } - - wrqu->power.disabled = 0; - - if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - wrqu->power.flags = IW_POWER_TIMEOUT; - wrqu->power.value = ieee->ps_timeout * 1000; - } else { - wrqu->power.flags = IW_POWER_PERIOD; - wrqu->power.value = ieee->ps_period * 1000; - } - - if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == - (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) - wrqu->power.flags |= IW_POWER_ALL_R; - else if (ieee->ps & RTLLIB_PS_MBCAST) - wrqu->power.flags |= IW_POWER_MULTICAST_R; - else - wrqu->power.flags |= IW_POWER_UNICAST_R; - -exit: - mutex_unlock(&ieee->wx_mutex); - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_power); diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c deleted file mode 100644 index 8e2abd16eb86..000000000000 --- a/drivers/staging/rtl8192e/rtllib_tx.c +++ /dev/null @@ -1,901 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. - * - * Contact Information: - * James P. Ketrenos <ipw2100-admin@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * Few modifications for Realtek's Wi-Fi drivers by - * Andrea Merello <andrea.merello@gmail.com> - * - * A special thanks goes to Realtek for their support ! - */ -#include <linux/compiler.h> -#include <linux/errno.h> -#include <linux/if_arp.h> -#include <linux/in6.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/pci.h> -#include <linux/proc_fs.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/wireless.h> -#include <linux/etherdevice.h> -#include <linux/uaccess.h> -#include <linux/if_vlan.h> - -#include "rtllib.h" - -/* 802.11 Data Frame - * - * - * 802.11 frame_control for data frames - 2 bytes - * ,--------------------------------------------------------------------. - * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | - * |---|---|---|---|---|---|---|---|---|----|----|-----|-----|-----|----| - * val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | - * |---|---|---|---|---|---|---|---|---|----|----|-----|-----|-----|----| - * desc | ver | type | ^-subtype-^ |to |from|more|retry| pwr |more |wep | - * | | | x=0 data |DS | DS |frag| | mgm |data | | - * | | | x=1 data+ack | | | | | | | | - * '--------------------------------------------------------------------' - * /\ - * | - * 802.11 Data Frame | - * ,--------- 'ctrl' expands to >---' - * | - * ,--'---,-------------------------------------------------------------. - * Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - * |------|------|---------|---------|---------|------|---------|------| - * Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | - * | | tion | (BSSID) | | | ence | data | | - * `--------------------------------------------------| |------' - * Total: 28 non-data bytes `----.----' - * | - * .- 'Frame data' expands to <---------------------------' - * | - * V - * ,---------------------------------------------------. - * Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | - * |------|------|---------|----------|------|---------| - * Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | - * | DSAP | SSAP | | | | Packet | - * | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | - * `-----------------------------------------| | - * Total: 8 non-data bytes `----.----' - * | - * .- 'IP Packet' expands, if WEP enabled, to <--' - * | - * V - * ,-----------------------. - * Bytes | 4 | 0-2296 | 4 | - * |-----|-----------|-----| - * Desc. | IV | Encrypted | ICV | - * | | IP Packet | | - * `-----------------------' - * Total: 8 non-data bytes - * - * - * 802.3 Ethernet Data Frame - * - * ,-----------------------------------------. - * Bytes | 6 | 6 | 2 | Variable | 4 | - * |-------|-------|------|-----------|------| - * Desc. | Dest. | Source| Type | IP Packet | fcs | - * | MAC | MAC | | | | - * `-----------------------------------------' - * Total: 18 non-data bytes - * - * In the event that fragmentation is required, the incoming payload is split - * into N parts of size ieee->fts. The first fragment contains the SNAP header - * and the remaining packets are just data. - * - * If encryption is enabled, each fragment payload size is reduced by enough - * space to add the prefix and postfix (IV and ICV totalling 8 bytes in - * the case of WEP) So if you have 1500 bytes of payload with ieee->fts set to - * 500 without encryption it will take 3 frames. With WEP it will take 4 frames - * as the payload of each frame is reduced to 492 bytes. - * - * SKB visualization - * - * ,- skb->data - * | - * | ETHERNET HEADER ,-<-- PAYLOAD - * | | 14 bytes from skb->data - * | 2 bytes for Type --> ,T. | (sizeof ethhdr) - * | | | | - * |,-Dest.--. ,--Src.---. | | | - * | 6 bytes| | 6 bytes | | | | - * v | | | | | | - * 0 | v 1 | v | v 2 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * ^ | ^ | ^ | - * | | | | | | - * | | | | `T' <---- 2 bytes for Type - * | | | | - * | | '---SNAP--' <-------- 6 bytes for SNAP - * | | - * `-IV--' <-------------------- 4 bytes for IV (WEP) - * - * SNAP HEADER - * - */ - -static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; -static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; - -static int rtllib_put_snap(u8 *data, u16 h_proto) -{ - struct rtllib_snap_hdr *snap; - u8 *oui; - - snap = (struct rtllib_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - - if (h_proto == 0x8137 || h_proto == 0x80f3) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - - *(__be16 *)(data + SNAP_SIZE) = htons(h_proto); - - return SNAP_SIZE + sizeof(u16); -} - -int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag, - int hdr_len) -{ - struct lib80211_crypt_data *crypt = NULL; - int res; - - crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - - if (!(crypt && crypt->ops)) { - netdev_info(ieee->dev, "=========>%s(), crypt is null\n", - __func__); - return -1; - } - /* To encrypt, frame format is: - * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) - */ - - /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so - * call both MSDU and MPDU encryption functions from here. - */ - atomic_inc(&crypt->refcnt); - res = 0; - if (crypt->ops->encrypt_msdu) - res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); - if (res == 0 && crypt->ops->encrypt_mpdu) - res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); - - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n", - ieee->dev->name, frag->len); - return -1; - } - - return 0; -} - -void rtllib_txb_free(struct rtllib_txb *txb) -{ - if (unlikely(!txb)) - return; - kfree(txb); -} - -static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, - gfp_t gfp_mask) -{ - struct rtllib_txb *txb; - int i; - - txb = kzalloc(struct_size(txb, fragments, nr_frags), gfp_mask); - if (!txb) - return NULL; - - txb->nr_frags = nr_frags; - txb->frag_size = cpu_to_le16(txb_size); - - for (i = 0; i < nr_frags; i++) { - txb->fragments[i] = dev_alloc_skb(txb_size); - if (unlikely(!txb->fragments[i])) - goto err_free; - memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb)); - } - - return txb; - -err_free: - while (--i >= 0) - dev_kfree_skb_any(txb->fragments[i]); - kfree(txb); - - return NULL; -} - -static int rtllib_classify(struct sk_buff *skb) -{ - struct ethhdr *eth; - struct iphdr *ip; - - eth = (struct ethhdr *)skb->data; - if (eth->h_proto != htons(ETH_P_IP)) - return 0; - -#ifdef VERBOSE_DEBUG - print_hex_dump_bytes("%s: ", __func__, DUMP_PREFIX_NONE, skb->data, - skb->len); -#endif - ip = ip_hdr(skb); - switch (ip->tos & 0xfc) { - case 0x20: - return 2; - case 0x40: - return 1; - case 0x60: - return 3; - case 0x80: - return 4; - case 0xa0: - return 5; - case 0xc0: - return 6; - case 0xe0: - return 7; - default: - return 0; - } -} - -static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, - struct sk_buff *skb, - struct cb_desc *tcb_desc) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - struct tx_ts_record *ts = NULL; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - if (rtllib_act_scanning(ieee, false)) - return; - - if (!ht_info->current_ht_support || !ht_info->enable_ht) - return; - if (!is_qos_data_frame(skb->data)) - return; - if (is_multicast_ether_addr(hdr->addr1)) - return; - - if (tcb_desc->bdhcp || ieee->cnt_after_link < 2) - return; - - if (ht_info->iot_action & HT_IOT_ACT_TX_NO_AGGREGATION) - return; - - if (!ieee->get_nmode_support_by_sec_cfg(ieee->dev)) - return; - if (ht_info->current_ampdu_enable) { - if (!rtllib_get_ts(ieee, (struct ts_common_info **)(&ts), hdr->addr1, - skb->priority, TX_DIR, true)) { - netdev_info(ieee->dev, "%s: can't get TS\n", __func__); - return; - } - if (!ts->tx_admitted_ba_record.b_valid) { - if (ieee->wpa_ie_len && (ieee->pairwise_key_type == - KEY_TYPE_NA)) { - ; - } else if (tcb_desc->bdhcp == 1) { - ; - } else if (!ts->disable_add_ba) { - rtllib_ts_start_add_ba_process(ieee, ts); - } - return; - } else if (!ts->using_ba) { - if (SN_LESS(ts->tx_admitted_ba_record.ba_start_seq_ctrl.field.seq_num, - (ts->tx_cur_seq + 1) % 4096)) - ts->using_ba = true; - else - return; - } - if (ieee->iw_mode == IW_MODE_INFRA) { - tcb_desc->ampdu_enable = true; - tcb_desc->ampdu_factor = ht_info->current_ampdu_factor; - tcb_desc->ampdu_density = ht_info->current_mpdu_density; - } - } -} - -static void rtllib_query_short_preamble_mode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) -{ - tcb_desc->use_short_preamble = false; - if (tcb_desc->data_rate == 2) - return; - else if (ieee->current_network.capability & - WLAN_CAPABILITY_SHORT_PREAMBLE) - tcb_desc->use_short_preamble = true; -} - -static void rtllib_query_ht_cap_short_gi(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - tcb_desc->use_short_gi = false; - - if (!ht_info->current_ht_support || !ht_info->enable_ht) - return; - - if (ht_info->cur_bw_40mhz && ht_info->cur_short_gi_40mhz) - tcb_desc->use_short_gi = true; - else if (!ht_info->cur_bw_40mhz && ht_info->cur_short_gi_20mhz) - tcb_desc->use_short_gi = true; -} - -static void rtllib_query_bandwidth_mode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) -{ - struct rt_hi_throughput *ht_info = ieee->ht_info; - - tcb_desc->packet_bw = false; - - if (!ht_info->current_ht_support || !ht_info->enable_ht) - return; - - if (tcb_desc->multicast || tcb_desc->broadcast) - return; - - if ((tcb_desc->data_rate & 0x80) == 0) - return; - if (ht_info->cur_bw_40mhz && ht_info->cur_tx_bw40mhz && - !ieee->bandwidth_auto_switch.forced_tx_20MHz) - tcb_desc->packet_bw = true; -} - -static void rtllib_query_protectionmode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc, - struct sk_buff *skb) -{ - struct rt_hi_throughput *ht_info; - - tcb_desc->rtsstbc = false; - tcb_desc->rts_use_short_gi = false; - tcb_desc->cts_enable = false; - tcb_desc->RTSSC = 0; - tcb_desc->rts_bw = false; - - if (tcb_desc->broadcast || tcb_desc->multicast) - return; - - if (is_broadcast_ether_addr(skb->data + 16)) - return; - - if (ieee->mode < WIRELESS_MODE_N_24G) { - if (skb->len > ieee->rts) { - tcb_desc->rts_enable = true; - tcb_desc->rts_rate = MGN_24M; - } else if (ieee->current_network.buseprotection) { - tcb_desc->rts_enable = true; - tcb_desc->cts_enable = true; - tcb_desc->rts_rate = MGN_24M; - } - return; - } - - ht_info = ieee->ht_info; - - while (true) { - if (ht_info->iot_action & HT_IOT_ACT_FORCED_CTS2SELF) { - tcb_desc->cts_enable = true; - tcb_desc->rts_rate = MGN_24M; - tcb_desc->rts_enable = true; - break; - } else if (ht_info->iot_action & (HT_IOT_ACT_FORCED_RTS | - HT_IOT_ACT_PURE_N_MODE)) { - tcb_desc->rts_enable = true; - tcb_desc->rts_rate = MGN_24M; - break; - } - if (ieee->current_network.buseprotection) { - tcb_desc->rts_enable = true; - tcb_desc->cts_enable = true; - tcb_desc->rts_rate = MGN_24M; - break; - } - if (ht_info->current_ht_support && ht_info->enable_ht) { - u8 ht_op_mode = ht_info->current_op_mode; - - if ((ht_info->cur_bw_40mhz && (ht_op_mode == 2 || - ht_op_mode == 3)) || - (!ht_info->cur_bw_40mhz && ht_op_mode == 3)) { - tcb_desc->rts_rate = MGN_24M; - tcb_desc->rts_enable = true; - break; - } - } - if (skb->len > ieee->rts) { - tcb_desc->rts_rate = MGN_24M; - tcb_desc->rts_enable = true; - break; - } - if (tcb_desc->ampdu_enable) { - tcb_desc->rts_rate = MGN_24M; - tcb_desc->rts_enable = false; - break; - } - goto NO_PROTECTION; - } - if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - tcb_desc->use_short_preamble = true; - return; -NO_PROTECTION: - tcb_desc->rts_enable = false; - tcb_desc->cts_enable = false; - tcb_desc->rts_rate = 0; - tcb_desc->RTSSC = 0; - tcb_desc->rts_bw = false; -} - -static void rtllib_txrate_selectmode(struct rtllib_device *ieee, - struct cb_desc *tcb_desc) -{ - if (ieee->tx_dis_rate_fallback) - tcb_desc->tx_dis_rate_fallback = true; - - if (ieee->tx_use_drv_assinged_rate) - tcb_desc->tx_use_drv_assinged_rate = true; - if (!tcb_desc->tx_dis_rate_fallback || - !tcb_desc->tx_use_drv_assinged_rate) { - if (ieee->iw_mode == IW_MODE_INFRA) - tcb_desc->ratr_index = 0; - } -} - -static u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb, - u8 *dst) -{ - u16 seqnum = 0; - - if (is_multicast_ether_addr(dst)) - return 0; - if (is_qos_data_frame(skb->data)) { - struct tx_ts_record *ts = NULL; - - if (!rtllib_get_ts(ieee, (struct ts_common_info **)(&ts), dst, - skb->priority, TX_DIR, true)) - return 0; - seqnum = ts->tx_cur_seq; - ts->tx_cur_seq = (ts->tx_cur_seq + 1) % 4096; - return seqnum; - } - return 0; -} - -static int wme_downgrade_ac(struct sk_buff *skb) -{ - switch (skb->priority) { - case 6: - case 7: - skb->priority = 5; /* VO -> VI */ - return 0; - case 4: - case 5: - skb->priority = 3; /* VI -> BE */ - return 0; - case 0: - case 3: - skb->priority = 1; /* BE -> BK */ - return 0; - default: - return -1; - } -} - -static u8 rtllib_current_rate(struct rtllib_device *ieee) -{ - if (ieee->mode & IEEE_MODE_MASK) - return ieee->rate; - - if (ieee->ht_curr_op_rate) - return ieee->ht_curr_op_rate; - else - return ieee->rate & 0x7F; -} - -static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) -{ - struct rtllib_device *ieee = (struct rtllib_device *) - netdev_priv_rsl(dev); - struct rtllib_txb *txb = NULL; - struct ieee80211_qos_hdr *frag_hdr; - int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; - unsigned long flags; - struct net_device_stats *stats = &ieee->stats; - int ether_type = 0, encrypt; - int bytes, fc, qos_ctl = 0, hdr_len; - struct sk_buff *skb_frag; - struct ieee80211_qos_hdr header = { /* Ensure zero initialized */ - .duration_id = 0, - .seq_ctrl = 0, - .qos_ctrl = 0 - }; - int qos_activated = ieee->current_network.qos_data.active; - u8 dest[ETH_ALEN]; - u8 src[ETH_ALEN]; - struct lib80211_crypt_data *crypt = NULL; - struct cb_desc *tcb_desc; - u8 is_multicast = false; - bool bdhcp = false; - - spin_lock_irqsave(&ieee->lock, flags); - - /* If there is no driver handler to take the TXB, don't bother - * creating it... - */ - if (!(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) || - ((!ieee->softmac_data_hard_start_xmit && - (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { - netdev_warn(ieee->dev, "No xmit handler.\n"); - goto success; - } - - if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { - netdev_warn(ieee->dev, "skb too small (%d).\n", - skb->len); - goto success; - } - /* Save source and destination addresses */ - ether_addr_copy(dest, skb->data); - ether_addr_copy(src, skb->data + ETH_ALEN); - - memset(skb->cb, 0, sizeof(skb->cb)); - ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); - - if (ieee->iw_mode == IW_MODE_MONITOR) { - txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); - if (unlikely(!txb)) { - netdev_warn(ieee->dev, - "Could not allocate TXB\n"); - goto failed; - } - - txb->encrypted = 0; - txb->payload_size = cpu_to_le16(skb->len); - skb_put_data(txb->fragments[0], skb->data, skb->len); - - goto success; - } - - if (skb->len > 282) { - if (ether_type == ETH_P_IP) { - const struct iphdr *ip = (struct iphdr *) - ((u8 *)skb->data + 14); - if (ip->protocol == IPPROTO_UDP) { - struct udphdr *udp; - - udp = (struct udphdr *)((u8 *)ip + - (ip->ihl << 2)); - if (((((u8 *)udp)[1] == 68) && - (((u8 *)udp)[3] == 67)) || - ((((u8 *)udp)[1] == 67) && - (((u8 *)udp)[3] == 68))) { - bdhcp = true; - ieee->lps_delay_cnt = 200; - } - } - } else if (ether_type == ETH_P_ARP) { - netdev_info(ieee->dev, - "=================>DHCP Protocol start tx ARP pkt!!\n"); - bdhcp = true; - ieee->lps_delay_cnt = - ieee->current_network.tim.tim_count; - } - } - - skb->priority = rtllib_classify(skb); - crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && crypt && crypt->ops; - if (!encrypt && ieee->ieee802_1x && - ieee->drop_unencrypted && ether_type != ETH_P_PAE) { - stats->tx_dropped++; - goto success; - } - if (crypt && !encrypt && ether_type == ETH_P_PAE) { - struct eapol *eap = (struct eapol *)(skb->data + - sizeof(struct ethhdr) - SNAP_SIZE - - sizeof(u16)); - netdev_dbg(ieee->dev, - "TX: IEEE 802.11 EAPOL frame: %s\n", - eap_get_type(eap->type)); - } - - /* Advance the SKB to the start of the payload */ - skb_pull(skb, sizeof(struct ethhdr)); - - /* Determine total amount of storage required for TXB packets */ - bytes = skb->len + SNAP_SIZE + sizeof(u16); - - if (encrypt) - fc = RTLLIB_FTYPE_DATA | IEEE80211_FCTL_PROTECTED; - else - fc = RTLLIB_FTYPE_DATA; - - if (qos_activated) - fc |= IEEE80211_STYPE_QOS_DATA; - else - fc |= IEEE80211_STYPE_DATA; - - if (ieee->iw_mode == IW_MODE_INFRA) { - fc |= IEEE80211_FCTL_TODS; - /* To DS: Addr1 = BSSID, Addr2 = SA, - * Addr3 = DA - */ - ether_addr_copy(header.addr1, - ieee->current_network.bssid); - ether_addr_copy(header.addr2, src); - ether_addr_copy(header.addr3, dest); - } - - is_multicast = is_multicast_ether_addr(header.addr1); - - header.frame_control = cpu_to_le16(fc); - - /* Determine fragmentation size based on destination (multicast - * and broadcast are not fragmented) - */ - if (is_multicast) { - frag_size = MAX_FRAG_THRESHOLD; - qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; - } else { - frag_size = ieee->fts; - qos_ctl = 0; - } - - if (qos_activated) { - hdr_len = RTLLIB_3ADDR_LEN + 2; - - /* in case we are a client verify acm is not set for this ac */ - while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { - netdev_info(ieee->dev, "skb->priority = %x\n", - skb->priority); - if (wme_downgrade_ac(skb)) - break; - netdev_info(ieee->dev, "converted skb->priority = %x\n", - skb->priority); - } - - qos_ctl |= skb->priority; - header.qos_ctrl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); - - } else { - hdr_len = RTLLIB_3ADDR_LEN; - } - /* Determine amount of payload per fragment. Regardless of if - * this stack is providing the full 802.11 header, one will - * eventually be affixed to this fragment -- so we must account - * for it when determining the amount of payload space. - */ - bytes_per_frag = frag_size - hdr_len; - if (ieee->config & - (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) - bytes_per_frag -= RTLLIB_FCS_LEN; - - /* Each fragment may need to have room for encrypting - * pre/postfix - */ - if (encrypt) { - bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + - crypt->ops->extra_mpdu_postfix_len + - crypt->ops->extra_msdu_prefix_len + - crypt->ops->extra_msdu_postfix_len; - } - /* Number of fragments is the total bytes_per_frag / - * payload_per_fragment - */ - nr_frags = bytes / bytes_per_frag; - bytes_last_frag = bytes % bytes_per_frag; - if (bytes_last_frag) - nr_frags++; - else - bytes_last_frag = bytes_per_frag; - - /* When we allocate the TXB we allocate enough space for the - * reserve and full fragment bytes (bytes_per_frag doesn't - * include prefix, postfix, header, FCS, etc.) - */ - txb = rtllib_alloc_txb(nr_frags, frag_size + - ieee->tx_headroom, GFP_ATOMIC); - if (unlikely(!txb)) { - netdev_warn(ieee->dev, "Could not allocate TXB\n"); - goto failed; - } - txb->encrypted = encrypt; - txb->payload_size = cpu_to_le16(bytes); - - if (qos_activated) - txb->queue_index = UP2AC(skb->priority); - else - txb->queue_index = WME_AC_BE; - - for (i = 0; i < nr_frags; i++) { - skb_frag = txb->fragments[i]; - tcb_desc = (struct cb_desc *)(skb_frag->cb + - MAX_DEV_ADDR_SIZE); - if (qos_activated) { - skb_frag->priority = skb->priority; - tcb_desc->queue_index = UP2AC(skb->priority); - } else { - skb_frag->priority = WME_AC_BE; - tcb_desc->queue_index = WME_AC_BE; - } - skb_reserve(skb_frag, ieee->tx_headroom); - - if (encrypt) { - if (ieee->hwsec_active) - tcb_desc->hw_sec = 1; - else - tcb_desc->hw_sec = 0; - skb_reserve(skb_frag, - crypt->ops->extra_mpdu_prefix_len + - crypt->ops->extra_msdu_prefix_len); - } else { - tcb_desc->hw_sec = 0; - } - frag_hdr = skb_put_data(skb_frag, &header, hdr_len); - - /* If this is not the last fragment, then add the - * MOREFRAGS bit to the frame control - */ - if (i != nr_frags - 1) { - frag_hdr->frame_control = cpu_to_le16(fc | - IEEE80211_FCTL_MOREFRAGS); - bytes = bytes_per_frag; - - } else { - /* The last fragment has the remaining length */ - bytes = bytes_last_frag; - } - if ((qos_activated) && (!is_multicast)) { - frag_hdr->seq_ctrl = - cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag, - header.addr1)); - frag_hdr->seq_ctrl = - cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctrl) << 4 | i); - } else { - frag_hdr->seq_ctrl = - cpu_to_le16(ieee->seq_ctrl[0] << 4 | i); - } - /* Put a SNAP header on the first fragment */ - if (i == 0) { - rtllib_put_snap(skb_put(skb_frag, - SNAP_SIZE + - sizeof(u16)), ether_type); - bytes -= SNAP_SIZE + sizeof(u16); - } - - skb_put_data(skb_frag, skb->data, bytes); - - /* Advance the SKB... */ - skb_pull(skb, bytes); - - /* Encryption routine will move the header forward in - * order to insert the IV between the header and the - * payload - */ - if (encrypt) - rtllib_encrypt_fragment(ieee, skb_frag, - hdr_len); - if (ieee->config & - (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) - skb_put(skb_frag, 4); - } - - if ((qos_activated) && (!is_multicast)) { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; - } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - } - - success: - if (txb) { - tcb_desc = (struct cb_desc *) - (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); - tcb_desc->tx_enable_fw_calc_dur = 1; - tcb_desc->priority = skb->priority; - - if (ether_type == ETH_P_PAE) { - if (ieee->ht_info->iot_action & - HT_IOT_ACT_WA_IOT_Broadcom) { - tcb_desc->data_rate = - mgnt_query_tx_rate_exclude_cck_rates(ieee); - tcb_desc->tx_dis_rate_fallback = false; - } else { - tcb_desc->data_rate = ieee->basic_rate; - tcb_desc->tx_dis_rate_fallback = 1; - } - - tcb_desc->ratr_index = 7; - tcb_desc->tx_use_drv_assinged_rate = 1; - } else { - if (is_multicast_ether_addr(header.addr1)) - tcb_desc->multicast = 1; - if (is_broadcast_ether_addr(header.addr1)) - tcb_desc->broadcast = 1; - rtllib_txrate_selectmode(ieee, tcb_desc); - if (tcb_desc->multicast || tcb_desc->broadcast) - tcb_desc->data_rate = ieee->basic_rate; - else - tcb_desc->data_rate = rtllib_current_rate(ieee); - - if (bdhcp) { - if (ieee->ht_info->iot_action & - HT_IOT_ACT_WA_IOT_Broadcom) { - tcb_desc->data_rate = - mgnt_query_tx_rate_exclude_cck_rates(ieee); - tcb_desc->tx_dis_rate_fallback = false; - } else { - tcb_desc->data_rate = MGN_1M; - tcb_desc->tx_dis_rate_fallback = 1; - } - - tcb_desc->ratr_index = 7; - tcb_desc->tx_use_drv_assinged_rate = 1; - tcb_desc->bdhcp = 1; - } - - rtllib_query_short_preamble_mode(ieee, tcb_desc); - rtllib_tx_query_agg_cap(ieee, txb->fragments[0], - tcb_desc); - rtllib_query_ht_cap_short_gi(ieee, tcb_desc); - rtllib_query_bandwidth_mode(ieee, tcb_desc); - rtllib_query_protectionmode(ieee, tcb_desc, - txb->fragments[0]); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); - dev_kfree_skb_any(skb); - if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += le16_to_cpu(txb->payload_size); - rtllib_softmac_xmit(txb, ieee); - } else { - rtllib_txb_free(txb); - } - } - - return 0; - - failed: - spin_unlock_irqrestore(&ieee->lock, flags); - netif_stop_queue(dev); - stats->tx_errors++; - return 1; -} - -netdev_tx_t rtllib_xmit(struct sk_buff *skb, struct net_device *dev) -{ - memset(skb->cb, 0, sizeof(skb->cb)); - return rtllib_xmit_inter(skb, dev) ? NETDEV_TX_BUSY : NETDEV_TX_OK; -} -EXPORT_SYMBOL(rtllib_xmit); diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c deleted file mode 100644 index c730d921463d..000000000000 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ /dev/null @@ -1,752 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright(c) 2004 Intel Corporation. All rights reserved. - * - * Portions of this file are based on the WEP enablement code provided by the - * Host AP project hostap-drivers v0.1.3 - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <jkmaline@cc.hut.fi> - * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> - * - * Contact Information: - * James P. Ketrenos <ipw2100-admin@linux.intel.com> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ -#include <linux/wireless.h> -#include <linux/kmod.h> -#include <linux/module.h> -#include <linux/etherdevice.h> -#include "rtllib.h" - -static const char * const rtllib_modes[] = { - "a", "b", "g", "?", "N-24G" -}; - -#define MAX_CUSTOM_LEN 64 -static inline char *rtl819x_translate_scan(struct rtllib_device *ieee, - char *start, char *stop, - struct rtllib_network *network, - struct iw_request_info *info) -{ - char custom[MAX_CUSTOM_LEN]; - char proto_name[6]; - char *pname = proto_name; - char *p; - struct iw_event iwe; - int i, j; - u16 max_rate, rate; - static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - /* Remaining entries will be displayed in the order we provide them */ - - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - if (network->ssid_len > 0) { - iwe.u.data.length = min_t(u8, network->ssid_len, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - } else if (network->hidden_ssid_len == 0) { - iwe.u.data.length = sizeof("<hidden>"); - start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>"); - } else { - iwe.u.data.length = min_t(u8, network->hidden_ssid_len, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, network->hidden_ssid); - } - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - for (i = 0; i < ARRAY_SIZE(rtllib_modes); i++) { - if (network->mode & BIT(i)) { - strcpy(pname, rtllib_modes[i]); - pname += strlen(rtllib_modes[i]); - } - } - *pname = '\0'; - snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - if (network->capability & - (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { - if (network->capability & WLAN_CAPABILITY_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - } - - /* Add frequency/channel */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = network->channel; - iwe.u.freq.e = 0; - iwe.u.freq.i = 0; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (network->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - /* Add basic and extended rates */ - max_rate = 0; - p = custom; - p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); - for (i = 0, j = 0; i < network->rates_len;) { - if (j < network->rates_ex_len && - ((network->rates_ex[j] & 0x7F) < - (network->rates[i] & 0x7F))) - rate = network->rates_ex[j++] & 0x7F; - else - rate = network->rates[i++] & 0x7F; - if (rate > max_rate) - max_rate = rate; - p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - } - for (; j < network->rates_ex_len; j++) { - rate = network->rates_ex[j] & 0x7F; - p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - if (rate > max_rate) - max_rate = rate; - } - - if (network->mode >= WIRELESS_MODE_N_24G) { - struct ht_capab_ele *ht_cap = NULL; - bool is40M = false, isShortGI = false; - u8 max_mcs = 0; - - if (!memcmp(network->bssht.bd_ht_cap_buf, EWC11NHTCap, 4)) - ht_cap = (struct ht_capab_ele *) - &network->bssht.bd_ht_cap_buf[4]; - else - ht_cap = (struct ht_capab_ele *) - &network->bssht.bd_ht_cap_buf[0]; - is40M = (ht_cap->chl_width) ? 1 : 0; - isShortGI = (ht_cap->chl_width) ? - ((ht_cap->short_gi_40mhz) ? 1 : 0) : - ((ht_cap->short_gi_20mhz) ? 1 : 0); - - max_mcs = ht_get_highest_mcs_rate(ieee, ht_cap->MCS, - MCS_FILTER_ALL); - rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f]; - if (rate > max_rate) - max_rate = rate; - } - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.value = max_rate * 500000; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - /* Add quality statistics */ - /* TODO: Fix these values... */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = network->stats.signal; - iwe.u.qual.level = network->stats.rssi; - iwe.u.qual.noise = network->stats.noise; - iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK; - if (!(network->stats.mask & RTLLIB_STATMASK_RSSI)) - iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; - if (!(network->stats.mask & RTLLIB_STATMASK_NOISE)) - iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; - if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL)) - iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; - iwe.u.qual.updated = 7; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - - iwe.cmd = IWEVCUSTOM; - p = custom; - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - memset(&iwe, 0, sizeof(iwe)); - if (network->wpa_ie_len) { - char buf[MAX_WPA_IE_LEN]; - - memcpy(buf, network->wpa_ie, network->wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - memset(&iwe, 0, sizeof(iwe)); - if (network->rsn_ie_len) { - char buf[MAX_WPA_IE_LEN]; - - memcpy(buf, network->rsn_ie, network->rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - /* add info for WZC */ - memset(&iwe, 0, sizeof(iwe)); - if (network->wzc_ie_len) { - char buf[MAX_WZC_IE_LEN]; - - memcpy(buf, network->wzc_ie, network->wzc_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->wzc_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - /* Add EXTRA: Age to display seconds since last beacon/probe response - * for given network. - */ - iwe.cmd = IWEVCUSTOM; - p = custom; - p += scnprintf(p, MAX_CUSTOM_LEN - (p - custom), - " Last beacon: %lums ago", - (100 * (jiffies - network->last_scanned)) / HZ); - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - return start; -} - -int rtllib_wx_get_scan(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct rtllib_network *network; - unsigned long flags; - - char *ev = extra; - char *stop = ev + wrqu->data.length; - int i = 0; - int err = 0; - - netdev_dbg(ieee->dev, "Getting scan\n"); - mutex_lock(&ieee->wx_mutex); - spin_lock_irqsave(&ieee->lock, flags); - - list_for_each_entry(network, &ieee->network_list, list) { - i++; - if ((stop - ev) < 200) { - err = -E2BIG; - break; - } - if (ieee->scan_age == 0 || - time_after(network->last_scanned + ieee->scan_age, jiffies)) - ev = rtl819x_translate_scan(ieee, ev, stop, network, - info); - else - netdev_dbg(ieee->dev, - "Network '%s ( %pM)' hidden due to age (%lums).\n", - escape_essid(network->ssid, - network->ssid_len), - network->bssid, - (100 * (jiffies - network->last_scanned)) / - HZ); - } - - spin_unlock_irqrestore(&ieee->lock, flags); - mutex_unlock(&ieee->wx_mutex); - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - - netdev_dbg(ieee->dev, "%s(): %d networks returned.\n", __func__, i); - - return err; -} -EXPORT_SYMBOL(rtllib_wx_get_scan); - -int rtllib_wx_set_encode(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &wrqu->encoding; - struct net_device *dev = ieee->dev; - struct rtllib_security sec = { - .flags = 0 - }; - int i, key, key_provided, len; - struct lib80211_crypt_data **crypt; - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > NUM_WEP_KEYS) - return -EINVAL; - key--; - key_provided = 1; - } else { - key_provided = 0; - key = ieee->crypt_info.tx_keyidx; - } - - netdev_dbg(ieee->dev, "Key: %d [%s]\n", key, key_provided ? - "provided" : "default"); - crypt = &ieee->crypt_info.crypt[key]; - if (erq->flags & IW_ENCODE_DISABLED) { - if (key_provided && *crypt) { - netdev_dbg(ieee->dev, - "Disabling encryption on key %d.\n", key); - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - } else { - netdev_dbg(ieee->dev, "Disabling encryption.\n"); - } - - /* Check all the keys to see if any are still configured, - * and if no key index was provided, de-init them all - */ - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ieee->crypt_info.crypt[i]) { - if (key_provided) - break; - lib80211_crypt_delayed_deinit(&ieee->crypt_info, - &ieee->crypt_info.crypt[i]); - } - } - - if (i == NUM_WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; - } - - goto done; - } - - sec.enabled = 1; - sec.flags |= SEC_ENABLED; - - if (*crypt && (*crypt)->ops && - strcmp((*crypt)->ops->name, "R-WEP") != 0) { - /* changing to use WEP; deinit previously used algorithm - * on this key - */ - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - } - - if (!*crypt) { - struct lib80211_crypt_data *new_crypt; - - /* take WEP into use */ - new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); - if (!new_crypt) - return -ENOMEM; - new_crypt->ops = lib80211_get_crypto_ops("R-WEP"); - if (!new_crypt->ops) { - request_module("rtllib_crypt_wep"); - new_crypt->ops = lib80211_get_crypto_ops("R-WEP"); - } - - if (new_crypt->ops) - new_crypt->priv = new_crypt->ops->init(key); - - if (!new_crypt->ops || !new_crypt->priv) { - kfree(new_crypt); - new_crypt = NULL; - - netdev_warn(dev, - "%s: could not initialize WEP: load module rtllib_crypt_wep\n", - dev->name); - return -EOPNOTSUPP; - } - *crypt = new_crypt; - } - - /* If a new key was provided, set it up */ - if (erq->length > 0) { - len = erq->length <= 5 ? 5 : 13; - memcpy(sec.keys[key], keybuf, erq->length); - if (len > erq->length) - memset(sec.keys[key] + erq->length, 0, - len - erq->length); - netdev_dbg(ieee->dev, "Setting key %d to '%s' (%d:%d bytes)\n", - key, escape_essid(sec.keys[key], len), erq->length, - len); - sec.key_sizes[key] = len; - (*crypt)->ops->set_key(sec.keys[key], len, NULL, - (*crypt)->priv); - sec.flags |= (1 << key); - /* This ensures a key will be activated if no key is - * explicitly set - */ - if (key == sec.active_key) - sec.flags |= SEC_ACTIVE_KEY; - ieee->crypt_info.tx_keyidx = key; - - } else { - len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, - NULL, (*crypt)->priv); - if (len == 0) { - /* Set a default key of all 0 */ - netdev_info(ieee->dev, "Setting key %d to all zero.\n", key); - - memset(sec.keys[key], 0, 13); - (*crypt)->ops->set_key(sec.keys[key], 13, NULL, - (*crypt)->priv); - sec.key_sizes[key] = 13; - sec.flags |= (1 << key); - } - - /* No key data - just set the default TX key index */ - if (key_provided) { - netdev_dbg(ieee->dev, - "Setting key %d as default Tx key.\n", key); - ieee->crypt_info.tx_keyidx = key; - sec.active_key = key; - sec.flags |= SEC_ACTIVE_KEY; - } - } - done: - ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); - ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : - WLAN_AUTH_SHARED_KEY; - sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; - sec.flags |= SEC_AUTH_MODE; - netdev_dbg(ieee->dev, "Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? - "OPEN" : "SHARED KEY"); - - /* For now we just support WEP, so only set that security level... - * TODO: When WPA is added this is one place that needs to change - */ - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_encode); - -int rtllib_wx_get_encode(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &wrqu->encoding; - int len, key; - struct lib80211_crypt_data *crypt; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > NUM_WEP_KEYS) - return -EINVAL; - key--; - } else { - key = ieee->crypt_info.tx_keyidx; - } - crypt = ieee->crypt_info.crypt[key]; - - erq->flags = key + 1; - - if (!crypt || !crypt->ops) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv); - - erq->length = max(len, 0); - - erq->flags |= IW_ENCODE_ENABLED; - - if (ieee->open_wep) - erq->flags |= IW_ENCODE_OPEN; - else - erq->flags |= IW_ENCODE_RESTRICTED; - - return 0; -} -EXPORT_SYMBOL(rtllib_wx_get_encode); - -int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct net_device *dev = ieee->dev; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int i, idx; - int group_key = 0; - const char *alg, *module; - const struct lib80211_crypto_ops *ops; - struct lib80211_crypt_data **crypt; - - struct rtllib_security sec = { - .flags = 0, - }; - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > NUM_WEP_KEYS) - return -EINVAL; - idx--; - } else { - idx = ieee->crypt_info.tx_keyidx; - } - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - crypt = &ieee->crypt_info.crypt[idx]; - group_key = 1; - } else { - /* some Cisco APs use idx>0 for unicast in dynamic WEP */ - if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) - return -EINVAL; - if (ieee->iw_mode == IW_MODE_INFRA) - crypt = &ieee->crypt_info.crypt[idx]; - else - return -EINVAL; - } - - sec.flags |= SEC_ENABLED; - if ((encoding->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - if (*crypt) - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ieee->crypt_info.crypt[i]) - break; - } - if (i == NUM_WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_LEVEL; - } - goto done; - } - - sec.enabled = 1; - switch (ext->alg) { - case IW_ENCODE_ALG_WEP: - alg = "R-WEP"; - module = "rtllib_crypt_wep"; - break; - case IW_ENCODE_ALG_TKIP: - alg = "R-TKIP"; - module = "rtllib_crypt_tkip"; - break; - case IW_ENCODE_ALG_CCMP: - alg = "R-CCMP"; - module = "rtllib_crypt_ccmp"; - break; - default: - netdev_dbg(ieee->dev, "Unknown crypto alg %d\n", ext->alg); - ret = -EINVAL; - goto done; - } - netdev_dbg(dev, "alg name:%s\n", alg); - - ops = lib80211_get_crypto_ops(alg); - if (!ops) { - char tempbuf[100]; - - memset(tempbuf, 0x00, 100); - sprintf(tempbuf, "%s", module); - request_module("%s", tempbuf); - ops = lib80211_get_crypto_ops(alg); - } - if (!ops) { - netdev_info(dev, "========>unknown crypto alg %d\n", ext->alg); - ret = -EINVAL; - goto done; - } - - if (!*crypt || (*crypt)->ops != ops) { - struct lib80211_crypt_data *new_crypt; - - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - - new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); - if (!new_crypt) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(idx); - - if (!new_crypt->priv) { - kfree(new_crypt); - ret = -EINVAL; - goto done; - } - *crypt = new_crypt; - } - - if (ext->key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, - (*crypt)->priv) < 0) { - netdev_info(dev, "key setting failed\n"); - ret = -EINVAL; - goto done; - } - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ieee->crypt_info.tx_keyidx = idx; - sec.active_key = idx; - sec.flags |= SEC_ACTIVE_KEY; - } - if (ext->alg != IW_ENCODE_ALG_NONE) { - sec.key_sizes[idx] = ext->key_len; - sec.flags |= (1 << idx); - if (ext->alg == IW_ENCODE_ALG_WEP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (ext->alg == IW_ENCODE_ALG_TKIP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (ext->alg == IW_ENCODE_ALG_CCMP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - /* Don't set sec level for group keys. */ - if (group_key) - sec.flags &= ~SEC_LEVEL; - } -done: - return ret; -} -EXPORT_SYMBOL(rtllib_wx_set_encode_ext); - -int rtllib_wx_set_mlme(struct rtllib_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u8 i = 0; - bool deauth = false; - struct iw_mlme *mlme = (struct iw_mlme *)extra; - - if (ieee->link_state != MAC80211_LINKED) - return -ENOLINK; - - mutex_lock(&ieee->wx_mutex); - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - deauth = true; - fallthrough; - case IW_MLME_DISASSOC: - if (deauth) - netdev_info(ieee->dev, "disauth packet !\n"); - else - netdev_info(ieee->dev, "dis associate packet!\n"); - - ieee->cannot_notify = true; - - send_disassociation(ieee, deauth, mlme->reason_code); - rtllib_disassociate(ieee); - - ieee->wap_set = 0; - for (i = 0; i < 6; i++) - ieee->current_network.bssid[i] = 0x55; - - ieee->ssid_set = 0; - ieee->current_network.ssid[0] = '\0'; - ieee->current_network.ssid_len = 0; - break; - default: - mutex_unlock(&ieee->wx_mutex); - return -EOPNOTSUPP; - } - - mutex_unlock(&ieee->wx_mutex); - - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_mlme); - -int rtllib_wx_set_auth(struct rtllib_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - break; - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* Host AP driver does not use these parameters and allows - * wpa_supplicant to control them internally. - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - ieee->tkip_countermeasures = data->value; - break; - case IW_AUTH_DROP_UNENCRYPTED: - ieee->drop_unencrypted = data->value; - break; - - case IW_AUTH_80211_AUTH_ALG: - if (data->value & IW_AUTH_ALG_SHARED_KEY) { - ieee->open_wep = 0; - ieee->auth_mode = 1; - } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) { - ieee->open_wep = 1; - ieee->auth_mode = 0; - } else if (data->value & IW_AUTH_ALG_LEAP) { - ieee->open_wep = 1; - ieee->auth_mode = 2; - } else { - return -EINVAL; - } - break; - - case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value) ? 1 : 0; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ieee->ieee802_1x = data->value; - break; - case IW_AUTH_PRIVACY_INVOKED: - ieee->privacy_invoked = data->value; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_auth); - -int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len) -{ - u8 *buf; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - if (len > MAX_WPA_IE_LEN || (len && !ie)) - return -EINVAL; - - if (len) { - eid = ie[0]; - if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2], wps_oui, 4))) { - ieee->wps_ie_len = min_t(size_t, len, MAX_WZC_IE_LEN); - buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - ieee->wps_ie = buf; - return 0; - } - } - ieee->wps_ie_len = 0; - kfree(ieee->wps_ie); - ieee->wps_ie = NULL; - if (len) { - if (len != ie[1] + 2) - return -EINVAL; - buf = kmemdup(ie, len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - return 0; -} -EXPORT_SYMBOL(rtllib_wx_set_gen_ie); diff --git a/drivers/staging/rtl8712/TODO b/drivers/staging/rtl8712/TODO index 847c8c41f4f7..5aed36efa7cb 100644 --- a/drivers/staging/rtl8712/TODO +++ b/drivers/staging/rtl8712/TODO @@ -1,6 +1,5 @@ TODO: - merge Realtek's bugfixes and new features into the driver -- switch to use LIB80211 - switch to use MAC80211 - checkpatch.pl fixes - only a few remain diff --git a/drivers/staging/rtl8723bs/TODO b/drivers/staging/rtl8723bs/TODO index 3d8f5a634a10..4c413f9d3df0 100644 --- a/drivers/staging/rtl8723bs/TODO +++ b/drivers/staging/rtl8723bs/TODO @@ -5,7 +5,6 @@ TODO: - checkpatch.pl fixes - most of the remaining ones are lines too long. Many of them will require refactoring - merge Realtek's bugfixes and new features into the driver -- switch to use LIB80211 - switch to use MAC80211 Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, diff --git a/drivers/staging/vt6655/TODO b/drivers/staging/vt6655/TODO index 529bc22cd608..27654bd0ff5d 100644 --- a/drivers/staging/vt6655/TODO +++ b/drivers/staging/vt6655/TODO @@ -8,7 +8,6 @@ TODO: - abstract VT3253 chipset specific code - add common vt665x infrastructure - kill ttype.h -- switch to use LIB80211 - switch to use MAC80211 - verify unsigned long usage for x86-64 arch - reduce .data footprint diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO index 876cdccb6948..cca78d2d3cfe 100644 --- a/drivers/staging/vt6656/TODO +++ b/drivers/staging/vt6656/TODO @@ -8,7 +8,6 @@ TODO: - abstract VT3184 chipset specific code - add common vt665x infrastructure - kill ttype.h -- done -- switch to use LIB80211 - switch to use MAC80211 - use kernel coding style - sparse fixes diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 67299e8b734e..47dc96dfe386 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -100,8 +100,16 @@ int debugfs_file_get(struct dentry *dentry) if (!fsd) return -ENOMEM; - fsd->real_fops = (void *)((unsigned long)d_fsd & - ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); + if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) { + fsd->real_fops = NULL; + fsd->short_fops = (void *)((unsigned long)d_fsd & + ~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT | + DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT)); + } else { + fsd->real_fops = (void *)((unsigned long)d_fsd & + ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); + fsd->short_fops = NULL; + } refcount_set(&fsd->active_users, 1); init_completion(&fsd->active_users_drained); INIT_LIST_HEAD(&fsd->cancellations); @@ -241,9 +249,10 @@ static int debugfs_locked_down(struct inode *inode, { if ((inode->i_mode & 07777 & ~0444) == 0 && !(filp->f_mode & FMODE_WRITE) && - !real_fops->unlocked_ioctl && - !real_fops->compat_ioctl && - !real_fops->mmap) + (!real_fops || + (!real_fops->unlocked_ioctl && + !real_fops->compat_ioctl && + !real_fops->mmap))) return 0; if (security_locked_down(LOCKDOWN_DEBUGFS)) @@ -316,19 +325,38 @@ static ret_type full_proxy_ ## name(proto) \ return r; \ } -FULL_PROXY_FUNC(llseek, loff_t, filp, - PROTO(struct file *filp, loff_t offset, int whence), - ARGS(filp, offset, whence)); +#define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args) \ +static ret_type full_proxy_ ## name(proto) \ +{ \ + struct dentry *dentry = F_DENTRY(filp); \ + struct debugfs_fsdata *fsd; \ + ret_type r; \ + \ + r = debugfs_file_get(dentry); \ + if (unlikely(r)) \ + return r; \ + fsd = dentry->d_fsdata; \ + if (fsd->real_fops) \ + r = fsd->real_fops->name(args); \ + else \ + r = fsd->short_fops->name(args); \ + debugfs_file_put(dentry); \ + return r; \ +} + +FULL_PROXY_FUNC_BOTH(llseek, loff_t, filp, + PROTO(struct file *filp, loff_t offset, int whence), + ARGS(filp, offset, whence)); -FULL_PROXY_FUNC(read, ssize_t, filp, - PROTO(struct file *filp, char __user *buf, size_t size, - loff_t *ppos), - ARGS(filp, buf, size, ppos)); +FULL_PROXY_FUNC_BOTH(read, ssize_t, filp, + PROTO(struct file *filp, char __user *buf, size_t size, + loff_t *ppos), + ARGS(filp, buf, size, ppos)); -FULL_PROXY_FUNC(write, ssize_t, filp, - PROTO(struct file *filp, const char __user *buf, size_t size, - loff_t *ppos), - ARGS(filp, buf, size, ppos)); +FULL_PROXY_FUNC_BOTH(write, ssize_t, filp, + PROTO(struct file *filp, const char __user *buf, + size_t size, loff_t *ppos), + ARGS(filp, buf, size, ppos)); FULL_PROXY_FUNC(unlocked_ioctl, long, filp, PROTO(struct file *filp, unsigned int cmd, unsigned long arg), @@ -363,7 +391,7 @@ static int full_proxy_release(struct inode *inode, struct file *filp) * not to leak any resources. Releasers must not assume that * ->i_private is still being meaningful here. */ - if (real_fops->release) + if (real_fops && real_fops->release) r = real_fops->release(inode, filp); replace_fops(filp, d_inode(dentry)->i_fop); @@ -373,39 +401,48 @@ static int full_proxy_release(struct inode *inode, struct file *filp) } static void __full_proxy_fops_init(struct file_operations *proxy_fops, - const struct file_operations *real_fops) + struct debugfs_fsdata *fsd) { proxy_fops->release = full_proxy_release; - if (real_fops->llseek) + + if ((fsd->real_fops && fsd->real_fops->llseek) || + (fsd->short_fops && fsd->short_fops->llseek)) proxy_fops->llseek = full_proxy_llseek; - if (real_fops->read) + + if ((fsd->real_fops && fsd->real_fops->read) || + (fsd->short_fops && fsd->short_fops->read)) proxy_fops->read = full_proxy_read; - if (real_fops->write) + + if ((fsd->real_fops && fsd->real_fops->write) || + (fsd->short_fops && fsd->short_fops->write)) proxy_fops->write = full_proxy_write; - if (real_fops->poll) + + if (fsd->real_fops && fsd->real_fops->poll) proxy_fops->poll = full_proxy_poll; - if (real_fops->unlocked_ioctl) + + if (fsd->real_fops && fsd->real_fops->unlocked_ioctl) proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl; } static int full_proxy_open(struct inode *inode, struct file *filp) { struct dentry *dentry = F_DENTRY(filp); - const struct file_operations *real_fops = NULL; + const struct file_operations *real_fops; struct file_operations *proxy_fops = NULL; + struct debugfs_fsdata *fsd; int r; r = debugfs_file_get(dentry); if (r) return r == -EIO ? -ENOENT : r; - real_fops = debugfs_real_fops(filp); - + fsd = dentry->d_fsdata; + real_fops = fsd->real_fops; r = debugfs_locked_down(inode, filp, real_fops); if (r) goto out; - if (!fops_get(real_fops)) { + if (real_fops && !fops_get(real_fops)) { #ifdef CONFIG_MODULES if (real_fops->owner && real_fops->owner->state == MODULE_STATE_GOING) { @@ -426,11 +463,14 @@ static int full_proxy_open(struct inode *inode, struct file *filp) r = -ENOMEM; goto free_proxy; } - __full_proxy_fops_init(proxy_fops, real_fops); + __full_proxy_fops_init(proxy_fops, fsd); replace_fops(filp, proxy_fops); - if (real_fops->open) { - r = real_fops->open(inode, filp); + if (!real_fops || real_fops->open) { + if (real_fops) + r = real_fops->open(inode, filp); + else + r = simple_open(inode, filp); if (r) { replace_fops(filp, d_inode(dentry)->i_fop); goto free_proxy; diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 66d9b3b4c588..38a9c7eb97e6 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -412,7 +412,7 @@ static struct dentry *end_creating(struct dentry *dentry) static struct dentry *__debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *proxy_fops, - const struct file_operations *real_fops) + const void *real_fops) { struct dentry *dentry; struct inode *inode; @@ -450,49 +450,38 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, return end_creating(dentry); } -/** - * debugfs_create_file - create a file in the debugfs filesystem - * @name: a pointer to a string containing the name of the file to create. - * @mode: the permission that the file should have. - * @parent: a pointer to the parent dentry for this file. This should be a - * directory dentry if set. If this parameter is NULL, then the - * file will be created in the root of the debugfs filesystem. - * @data: a pointer to something that the caller will want to get to later - * on. The inode.i_private pointer will point to this value on - * the open() call. - * @fops: a pointer to a struct file_operations that should be used for - * this file. - * - * This is the basic "create a file" function for debugfs. It allows for a - * wide range of flexibility in creating a file, or a directory (if you want - * to create a directory, the debugfs_create_dir() function is - * recommended to be used instead.) - * - * This function will return a pointer to a dentry if it succeeds. This - * pointer must be passed to the debugfs_remove() function when the file is - * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be - * returned. - * - * If debugfs is not enabled in the kernel, the value -%ENODEV will be - * returned. - * - * NOTE: it's expected that most callers should _ignore_ the errors returned - * by this function. Other debugfs functions handle the fact that the "dentry" - * passed to them could be an error and they don't crash in that case. - * Drivers should generally work fine even if debugfs fails to init anyway. - */ -struct dentry *debugfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops) +struct dentry *debugfs_create_file_full(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) { + if (WARN_ON((unsigned long)fops & + (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT | + DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) + return ERR_PTR(-EINVAL); return __debugfs_create_file(name, mode, parent, data, fops ? &debugfs_full_proxy_file_operations : &debugfs_noop_file_operations, fops); } -EXPORT_SYMBOL_GPL(debugfs_create_file); +EXPORT_SYMBOL_GPL(debugfs_create_file_full); + +struct dentry *debugfs_create_file_short(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct debugfs_short_fops *fops) +{ + if (WARN_ON((unsigned long)fops & + (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT | + DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) + return ERR_PTR(-EINVAL); + + return __debugfs_create_file(name, mode, parent, data, + fops ? &debugfs_full_proxy_file_operations : + &debugfs_noop_file_operations, + (const void *)((unsigned long)fops | + DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT)); +} +EXPORT_SYMBOL_GPL(debugfs_create_file_short); /** * debugfs_create_file_unsafe - create a file in the debugfs filesystem diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index dae80c2a469e..a3edfa4f0d8e 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -18,6 +18,7 @@ extern const struct file_operations debugfs_full_proxy_file_operations; struct debugfs_fsdata { const struct file_operations *real_fops; + const struct debugfs_short_fops *short_fops; union { /* automount_fn is used when real_fops is NULL */ debugfs_automount_t automount; @@ -39,6 +40,11 @@ struct debugfs_fsdata { * pointer gets its lowest bit set. */ #define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) +/* + * A dentry's ->d_fsdata, when pointing to real fops, is with + * short fops instead of full fops. + */ +#define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1) /* Access BITS */ #define DEBUGFS_ALLOW_API BIT(0) diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 0928a6c8ae1e..59444b495d49 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -71,9 +71,63 @@ typedef struct vfsmount *(*debugfs_automount_t)(struct dentry *, void *); struct dentry *debugfs_lookup(const char *name, struct dentry *parent); -struct dentry *debugfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); +struct debugfs_short_fops { + ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); + ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); + loff_t (*llseek) (struct file *, loff_t, int); +}; + +struct dentry *debugfs_create_file_full(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops); +struct dentry *debugfs_create_file_short(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct debugfs_short_fops *fops); + +/** + * debugfs_create_file - create a file in the debugfs filesystem + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have. + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is NULL, then the + * file will be created in the root of the debugfs filesystem. + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + * @fops: a pointer to a struct file_operations or struct debugfs_short_fops that + * should be used for this file. + * + * This is the basic "create a file" function for debugfs. It allows for a + * wide range of flexibility in creating a file, or a directory (if you want + * to create a directory, the debugfs_create_dir() function is + * recommended to be used instead.) + * + * This function will return a pointer to a dentry if it succeeds. This + * pointer must be passed to the debugfs_remove() function when the file is + * to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be + * returned. + * + * If debugfs is not enabled in the kernel, the value -%ENODEV will be + * returned. + * + * If fops points to a struct debugfs_short_fops, then simple_open() will be + * used for the open, and only read/write/llseek are supported and are proxied, + * so no module reference or release are needed. + * + * NOTE: it's expected that most callers should _ignore_ the errors returned + * by this function. Other debugfs functions handle the fact that the "dentry" + * passed to them could be an error and they don't crash in that case. + * Drivers should generally work fine even if debugfs fails to init anyway. + */ +#define debugfs_create_file(name, mode, parent, data, fops) \ + _Generic(fops, \ + const struct file_operations *: debugfs_create_file_full, \ + const struct debugfs_short_fops *: debugfs_create_file_short, \ + struct file_operations *: debugfs_create_file_full, \ + struct debugfs_short_fops *: debugfs_create_file_short) \ + (name, mode, parent, data, fops) + struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); @@ -207,7 +261,7 @@ static inline struct dentry *debugfs_lookup(const char *name, static inline struct dentry *debugfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, - const struct file_operations *fops) + const void *fops) { return ERR_PTR(-ENODEV); } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 389f92e4d980..3c552b648b27 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1793,7 +1793,6 @@ enum netdev_reg_state { * @wireless_handlers: List of functions to handle Wireless Extensions, * instead of ioctl, * see <net/iw_handler.h> for details. - * @wireless_data: Instance data managed by the core of wireless extensions * * @netdev_ops: Includes several pointers to callbacks, * if one wants to override the ndo_*() functions @@ -2172,7 +2171,6 @@ struct net_device { #ifdef CONFIG_WIRELESS_EXT const struct iw_handler_def *wireless_handlers; - struct iw_public_data *wireless_data; #endif const struct ethtool_ops *ethtool_ops; #ifdef CONFIG_NET_L3_MASTER_DEV diff --git a/include/linux/wireless.h b/include/linux/wireless.h index e6e34d74dda0..03e5d3fe226d 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -21,8 +21,7 @@ struct compat_iw_point { __u16 length; __u16 flags; }; -#endif -#ifdef CONFIG_COMPAT + struct __compat_iw_event { __u16 len; /* Real length of this stuff */ __u16 cmd; /* Wireless IOCTL */ @@ -49,5 +48,5 @@ struct __compat_iw_event { #define IW_EV_COMPAT_POINT_LEN \ (IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \ IW_EV_COMPAT_POINT_OFF) -#endif +#endif /* CONFIG_COMPAT */ #endif /* _LINUX_WIRELESS_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 69ec1eb41a09..8f9853b1a5d1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1460,7 +1460,6 @@ struct cfg80211_unsol_bcast_probe_resp { * @crypto: crypto settings * @privacy: the BSS uses privacy * @auth_type: Authentication type (algorithm) - * @smps_mode: SMPS mode * @inactivity_timeout: time in seconds to determine station's inactivity. * @p2p_ctwindow: P2P CT Window * @p2p_opp_ps: P2P opportunistic PS @@ -1498,7 +1497,6 @@ struct cfg80211_ap_settings { struct cfg80211_crypto_settings crypto; bool privacy; enum nl80211_auth_type auth_type; - enum nl80211_smps_mode smps_mode; int inactivity_timeout; u8 p2p_ctwindow; bool p2p_opp_ps; @@ -2269,6 +2267,7 @@ static inline int cfg80211_get_station(struct net_device *dev, * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering * @MONITOR_FLAG_COOK_FRAMES: report frames after processing * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address + * @MONITOR_FLAG_SKIP_TX: do not pass locally transmitted frames */ enum monitor_flags { MONITOR_FLAG_CHANGED = BIT(__NL80211_MNTR_FLAG_INVALID), @@ -2278,6 +2277,7 @@ enum monitor_flags { MONITOR_FLAG_OTHER_BSS = BIT(NL80211_MNTR_FLAG_OTHER_BSS), MONITOR_FLAG_COOK_FRAMES = BIT(NL80211_MNTR_FLAG_COOK_FRAMES), MONITOR_FLAG_ACTIVE = BIT(NL80211_MNTR_FLAG_ACTIVE), + MONITOR_FLAG_SKIP_TX = BIT(NL80211_MNTR_FLAG_SKIP_TX), }; /** @@ -4696,6 +4696,7 @@ struct cfg80211_ops { struct ieee80211_channel *chan); int (*set_monitor_channel)(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_chan_def *chandef); int (*scan)(struct wiphy *wiphy, @@ -5436,6 +5437,8 @@ struct wiphy_radio_freq_range { * @iface_combinations: Valid interface combinations array, should not * list single interface types. * @n_iface_combinations: number of entries in @iface_combinations array. + * + * @antenna_mask: bitmask of antennas connected to this radio. */ struct wiphy_radio { const struct wiphy_radio_freq_range *freq_range; @@ -5443,6 +5446,8 @@ struct wiphy_radio { const struct ieee80211_iface_combination *iface_combinations; int n_iface_combinations; + + u32 antenna_mask; }; #define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff @@ -6223,6 +6228,7 @@ enum ieee80211_ap_reg_power { * entered. * @links.cac_time_ms: CAC time in ms * @valid_links: bitmap describing what elements of @links are valid + * @radio_mask: Bitmask of radios that this interface is allowed to operate on. */ struct wireless_dev { struct wiphy *wiphy; @@ -6335,6 +6341,8 @@ struct wireless_dev { unsigned int cac_time_ms; } links[IEEE80211_MLD_MAX_NUM_LINKS]; u16 valid_links; + + u32 radio_mask; }; static inline const u8 *wdev_address(struct wireless_dev *wdev) @@ -6521,6 +6529,17 @@ bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio, const struct cfg80211_chan_def *chandef); /** + * cfg80211_wdev_channel_allowed - Check if the wdev may use the channel + * + * @wdev: the wireless device + * @chan: channel to check + * + * Return: whether or not the wdev may use the channel + */ +bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev, + struct ieee80211_channel *chan); + +/** * ieee80211_get_response_rate - get basic rate for a given rate * * @sband: the band to look for rates in diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index 7af1082ea9a0..b80e474cb0aa 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h @@ -279,8 +279,6 @@ #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ /* SET : Omit payload from generated iwevent */ #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */ -/* Driver level flags */ -#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ /****************************** TYPES ******************************/ @@ -373,11 +371,10 @@ struct iw_handler_def { */ struct iw_ioctl_description { __u8 header_type; /* NULL, iw_point or other */ - __u8 token_type; /* Future */ + __u8 flags; /* Special handling of the request */ __u16 token_size; /* Granularity of payload */ __u16 min_tokens; /* Min acceptable token number */ __u16 max_tokens; /* Max acceptable token number */ - __u32 flags; /* Special handling of the request */ }; /* Need to think of short header translation table. Later. */ @@ -404,26 +401,6 @@ struct iw_spy_data { u_char spy_thr_under[IW_MAX_SPY]; }; -/* --------------------- DEVICE WIRELESS DATA --------------------- */ -/* - * This is all the wireless data specific to a device instance that - * is managed by the core of Wireless Extensions or the 802.11 layer. - * We only keep pointer to those structures, so that a driver is free - * to share them between instances. - * This structure should be initialised before registering the device. - * Access to this data follow the same rules as any other struct net_device - * data (i.e. valid as long as struct net_device exist, same locking rules). - */ -/* Forward declaration */ -struct libipw_device; -/* The struct */ -struct iw_public_data { - /* Driver enhanced spy support */ - struct iw_spy_data * spy_data; - /* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */ - struct libipw_device * libipw; -}; - /**************************** PROTOTYPES ****************************/ /* * Functions part of the Wireless Extensions (defined in net/wireless/wext-core.c). @@ -443,22 +420,6 @@ static inline void wireless_nlevent_flush(void) {} /* We may need a function to send a stream of events to user space. * More on that later... */ -/* Standard handler for SIOCSIWSPY */ -int iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -/* Standard handler for SIOCGIWSPY */ -int iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -/* Standard handler for SIOCSIWTHRSPY */ -int iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -/* Standard handler for SIOCGIWTHRSPY */ -int iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -/* Driver call to update spy records */ -void wireless_spy_update(struct net_device *dev, unsigned char *address, - struct iw_quality *wstats); - /************************* INLINE FUNCTIONS *************************/ /* * Function that are so simple that it's more efficient inlining them diff --git a/include/net/lib80211.h b/include/net/lib80211.h deleted file mode 100644 index fd0f15d87d80..000000000000 --- a/include/net/lib80211.h +++ /dev/null @@ -1,122 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * lib80211.h -- common bits for IEEE802.11 wireless drivers - * - * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com> - * - * Some bits copied from old ieee80211 component, w/ original copyright - * notices below: - * - * Original code based on Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <j@w1.fi> - * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * <jketreno@linux.intel.com> - * - * Copyright (c) 2004, Intel Corporation - * - */ - -#ifndef LIB80211_H -#define LIB80211_H - -#include <linux/types.h> -#include <linux/list.h> -#include <linux/atomic.h> -#include <linux/if.h> -#include <linux/skbuff.h> -#include <linux/ieee80211.h> -#include <linux/timer.h> -#include <linux/seq_file.h> - -#define NUM_WEP_KEYS 4 - -enum { - IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0), -}; - -struct module; - -struct lib80211_crypto_ops { - const char *name; - struct list_head list; - - /* init new crypto context (e.g., allocate private data space, - * select IV, etc.); returns NULL on failure or pointer to allocated - * private data on success */ - void *(*init) (int keyidx); - - /* deinitialize crypto context and free allocated private data */ - void (*deinit) (void *priv); - - /* encrypt/decrypt return < 0 on error or >= 0 on success. The return - * value from decrypt_mpdu is passed as the keyidx value for - * decrypt_msdu. skb must have enough head and tail room for the - * encryption; if not, error will be returned; these functions are - * called for all MPDUs (i.e., fragments). - */ - int (*encrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv); - int (*decrypt_mpdu) (struct sk_buff * skb, int hdr_len, void *priv); - - /* These functions are called for full MSDUs, i.e. full frames. - * These can be NULL if full MSDU operations are not needed. */ - int (*encrypt_msdu) (struct sk_buff * skb, int hdr_len, void *priv); - int (*decrypt_msdu) (struct sk_buff * skb, int keyidx, int hdr_len, - void *priv); - - int (*set_key) (void *key, int len, u8 * seq, void *priv); - int (*get_key) (void *key, int len, u8 * seq, void *priv); - - /* procfs handler for printing out key information and possible - * statistics */ - void (*print_stats) (struct seq_file *m, void *priv); - - /* Crypto specific flag get/set for configuration settings */ - unsigned long (*get_flags) (void *priv); - unsigned long (*set_flags) (unsigned long flags, void *priv); - - /* maximum number of bytes added by encryption; encrypt buf is - * allocated with extra_prefix_len bytes, copy of in_buf, and - * extra_postfix_len; encrypt need not use all this space, but - * the result must start at the beginning of the buffer and correct - * length must be returned */ - int extra_mpdu_prefix_len, extra_mpdu_postfix_len; - int extra_msdu_prefix_len, extra_msdu_postfix_len; - - struct module *owner; -}; - -struct lib80211_crypt_data { - struct list_head list; /* delayed deletion list */ - const struct lib80211_crypto_ops *ops; - void *priv; - atomic_t refcnt; -}; - -struct lib80211_crypt_info { - char *name; - /* Most clients will already have a lock, - so just point to that. */ - spinlock_t *lock; - - struct lib80211_crypt_data *crypt[NUM_WEP_KEYS]; - int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ - struct list_head crypt_deinit_list; - struct timer_list crypt_deinit_timer; - int crypt_quiesced; -}; - -int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name, - spinlock_t *lock); -void lib80211_crypt_info_free(struct lib80211_crypt_info *info); -int lib80211_register_crypto_ops(const struct lib80211_crypto_ops *ops); -int lib80211_unregister_crypto_ops(const struct lib80211_crypto_ops *ops); -const struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name); -void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info, - struct lib80211_crypt_data **crypt); - -#endif /* LIB80211_H */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 333e0fae6796..b4f246cdcca4 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -213,7 +213,7 @@ struct ieee80211_low_level_stats { * @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed * @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel, * this is used only with channel switching with CSA - * @IEEE80211_CHANCTX_CHANGE_MIN_WIDTH: The min required channel width changed + * @IEEE80211_CHANCTX_CHANGE_MIN_DEF: The min chandef changed * @IEEE80211_CHANCTX_CHANGE_AP: The AP channel definition changed, so (wider * bandwidth) OFDMA settings need to be changed * @IEEE80211_CHANCTX_CHANGE_PUNCTURING: The punctured channel(s) bitmap @@ -224,7 +224,7 @@ enum ieee80211_chanctx_change { IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2), IEEE80211_CHANCTX_CHANGE_CHANNEL = BIT(3), - IEEE80211_CHANCTX_CHANGE_MIN_WIDTH = BIT(4), + IEEE80211_CHANCTX_CHANGE_MIN_DEF = BIT(4), IEEE80211_CHANCTX_CHANGE_AP = BIT(5), IEEE80211_CHANCTX_CHANGE_PUNCTURING = BIT(6), }; @@ -740,6 +740,19 @@ struct ieee80211_parsed_tpe { * @eht_80mhz_full_bw_ul_mumimo: in AP-mode, does this BSS support the * reception of an EHT TB PPDU on an RU that spans the entire PPDU * bandwidth + * @bss_param_ch_cnt: in BSS-mode, the BSS params change count. This + * information is the latest known value. It can come from this link's + * beacon or from a beacon sent by another link. + * @bss_param_ch_cnt_link_id: in BSS-mode, the link_id to which the beacon + * that updated &bss_param_ch_cnt belongs. E.g. if link 1 doesn't hear + * its beacons, and link 2 sent a beacon with an RNR element that updated + * link 1's BSS params change count, then, link 1's + * bss_param_ch_cnt_link_id will be 2. That means that link 1 knows that + * link 2 was the link that updated its bss_param_ch_cnt value. + * In case link 1 hears its beacon again, bss_param_ch_cnt_link_id will + * be updated to 1, even if bss_param_ch_cnt didn't change. This allows + * the link to know that it heard the latest value from its own beacon + * (as opposed to hearing its value from another link's beacon). */ struct ieee80211_bss_conf { struct ieee80211_vif *vif; @@ -834,6 +847,8 @@ struct ieee80211_bss_conf { bool eht_su_beamformee; bool eht_mu_beamformer; bool eht_80mhz_full_bw_ul_mumimo; + u8 bss_param_ch_cnt; + u8 bss_param_ch_cnt_link_id; }; /** @@ -1448,8 +1463,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU * @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected * on this subframe - * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC - * is stored in the @ampdu_delimiter_crc field) * @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was * done by the hardware * @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without @@ -1521,7 +1534,7 @@ enum mac80211_rx_flags { RX_FLAG_AMPDU_LAST_KNOWN = BIT(12), RX_FLAG_AMPDU_IS_LAST = BIT(13), RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(14), - RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(15), + /* one free bit at 15 */ RX_FLAG_MACTIME = BIT(16) | BIT(17), RX_FLAG_MACTIME_PLCP_START = 1 << 16, RX_FLAG_MACTIME_START = 2 << 16, @@ -1618,7 +1631,6 @@ enum mac80211_rx_encoding { * @rx_flags: internal RX flags for mac80211 * @ampdu_reference: A-MPDU reference number, must be a different value for * each A-MPDU but the same for each subframe within one A-MPDU - * @ampdu_delimiter_crc: A-MPDU delimiter CRC * @zero_length_psdu_type: radiotap type of the 0-length PSDU * @link_valid: if the link which is identified by @link_id is valid. This flag * is set only when connection is MLO. @@ -1656,7 +1668,6 @@ struct ieee80211_rx_status { s8 signal; u8 chains; s8 chain_signal[IEEE80211_MAX_CHAINS]; - u8 ampdu_delimiter_crc; u8 zero_length_psdu_type; u8 link_valid:1, link_id:4; }; @@ -2683,6 +2694,11 @@ struct ieee80211_txq { * a virtual monitor interface when monitor interfaces are the only * active interfaces. * + * @IEEE80211_HW_NO_VIRTUAL_MONITOR: The driver would like to be informed + * of any monitor interface, as well as their configured channel. + * This is useful for supporting multiple monitor interfaces on different + * channels. + * * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to * be created. It is expected user-space will create vifs as * desired (and thus have them named as desired). @@ -2842,6 +2858,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_DYNAMIC_PS, IEEE80211_HW_MFP_CAPABLE, IEEE80211_HW_WANT_MONITOR_VIF, + IEEE80211_HW_NO_VIRTUAL_MONITOR, IEEE80211_HW_NO_AUTO_VIF, IEEE80211_HW_SW_CRYPTO_CONTROL, IEEE80211_HW_SUPPORT_FAST_XMIT, @@ -4075,8 +4092,8 @@ struct ieee80211_prep_tx_info { * in @sta_state. * The callback can sleep. * - * @sta_rc_update: Notifies the driver of changes to the bitrates that can be - * used to transmit to the station. The changes are advertised with bits + * @link_sta_rc_update: Notifies the driver of changes to the bitrates that can + * be used to transmit to the station. The changes are advertised with bits * from &enum ieee80211_rate_control_changed and the values are reflected * in the station data. This callback should only be used when the driver * uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL) since @@ -4444,6 +4461,12 @@ struct ieee80211_prep_tx_info { * if the requested TID-To-Link mapping can be accepted or not. * If it's not accepted the driver may suggest a preferred mapping and * modify @ttlm parameter with the suggested TID-to-Link mapping. + * @prep_add_interface: prepare for interface addition. This can be used by + * drivers to prepare for the addition of a new interface, e.g., allocate + * the needed resources etc. This callback doesn't guarantee that an + * interface with the specified type would be added, and thus drivers that + * implement this callback need to handle such cases. The type is the full + * &enum nl80211_iftype. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -4560,10 +4583,10 @@ struct ieee80211_ops { void (*sta_pre_rcu_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); - void (*sta_rc_update)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - u32 changed); + void (*link_sta_rc_update)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_sta *link_sta, + u32 changed); void (*sta_rate_tbl_update)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); @@ -4828,6 +4851,8 @@ struct ieee80211_ops { enum ieee80211_neg_ttlm_res (*can_neg_ttlm)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_neg_ttlm *ttlm); + void (*prep_add_interface)(struct ieee80211_hw *hw, + enum nl80211_iftype type); }; /** @@ -7681,6 +7706,33 @@ void ieee80211_set_active_links_async(struct ieee80211_vif *vif, */ void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif); +/** + * ieee80211_chan_width_to_rx_bw - convert channel width to STA RX bandwidth + * @width: the channel width value to convert + * Return: the STA RX bandwidth value for the channel width + */ +static inline enum ieee80211_sta_rx_bandwidth +ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) +{ + switch (width) { + default: + WARN_ON_ONCE(1); + fallthrough; + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + return IEEE80211_STA_RX_BW_20; + case NL80211_CHAN_WIDTH_40: + return IEEE80211_STA_RX_BW_40; + case NL80211_CHAN_WIDTH_80: + return IEEE80211_STA_RX_BW_80; + case NL80211_CHAN_WIDTH_160: + case NL80211_CHAN_WIDTH_80P80: + return IEEE80211_STA_RX_BW_160; + case NL80211_CHAN_WIDTH_320: + return IEEE80211_STA_RX_BW_320; + } +} + /* for older drivers - let's not document these ... */ int ieee80211_emulate_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx); diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f97f5adc8d51..6d11437596b9 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2868,6 +2868,9 @@ enum nl80211_commands { * nested item, it contains attributes defined in * &enum nl80211_if_combination_attrs. * + * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32). + * A value of 0 means all radios. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3416,6 +3419,8 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_RADIOS, NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS, + NL80211_ATTR_VIF_RADIO_MASK, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4698,6 +4703,7 @@ enum nl80211_survey_info { * overrides all other flags. * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address * and ACK incoming unicast packets. + * @NL80211_MNTR_FLAG_SKIP_TX: do not pass local tx packets * * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag @@ -4710,6 +4716,7 @@ enum nl80211_mntr_flags { NL80211_MNTR_FLAG_OTHER_BSS, NL80211_MNTR_FLAG_COOK_FRAMES, NL80211_MNTR_FLAG_ACTIVE, + NL80211_MNTR_FLAG_SKIP_TX, /* keep last */ __NL80211_MNTR_FLAG_AFTER_LAST, @@ -8031,6 +8038,8 @@ enum nl80211_ap_settings_flags { * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface * combination for this radio. Attribute may be present multiple times * and contains attributes defined in &enum nl80211_if_combination_attrs. + * @NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK: bitmask (u32) of antennas + * connected to this radio. * * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute @@ -8041,6 +8050,7 @@ enum nl80211_wiphy_radio_attrs { NL80211_WIPHY_RADIO_ATTR_INDEX, NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE, NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, + NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK, /* keep last */ __NL80211_WIPHY_RADIO_ATTR_LAST, diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 1c18b862ef8c..04cb45cfb310 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -797,7 +797,7 @@ void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid, if (!test_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state)) { ieee80211_send_addba_with_timeout(sta, tid_tx); - /* RESPONSE_RECEIVED state whould trigger the flow again */ + /* RESPONSE_RECEIVED state would trigger the flow again */ return; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 847304a3a29a..6c0b228523cb 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -105,8 +105,11 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, } /* also validate MU-MIMO change */ - monitor_sdata = wiphy_dereference(local->hw.wiphy, - local->monitor_sdata); + if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + monitor_sdata = sdata; + else + monitor_sdata = wiphy_dereference(local->hw.wiphy, + local->monitor_sdata); if (!monitor_sdata && (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) @@ -114,7 +117,9 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, /* apply all changes now - no failures allowed */ - if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) + if (monitor_sdata && + (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))) ieee80211_set_mu_mimo_follow(monitor_sdata, params); if (params->flags) { @@ -194,6 +199,24 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, } } + /* Let the driver know that an interface is going to be added. + * Indicate so only for interface types that will be added to the + * driver. + */ + switch (type) { + case NL80211_IFTYPE_AP_VLAN: + break; + case NL80211_IFTYPE_MONITOR: + if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) || + !(params->flags & MONITOR_FLAG_ACTIVE)) + break; + fallthrough; + default: + drv_prep_add_interface(local, + ieee80211_vif_type_p2p(&sdata->vif)); + break; + } + return wdev; } @@ -879,6 +902,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, } static int ieee80211_set_monitor_channel(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_chan_def *chandef) { struct ieee80211_local *local = wiphy_priv(wiphy); @@ -888,22 +912,25 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, lockdep_assert_wiphy(local->hw.wiphy); - if (cfg80211_chandef_identical(&local->monitor_chanreq.oper, - &chanreq.oper)) - return 0; + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { + if (cfg80211_chandef_identical(&local->monitor_chanreq.oper, + &chanreq.oper)) + return 0; - sdata = wiphy_dereference(local->hw.wiphy, - local->monitor_sdata); - if (!sdata) - goto done; + sdata = wiphy_dereference(wiphy, local->monitor_sdata); + if (!sdata) + goto done; + } - if (cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper, + if (rcu_access_pointer(sdata->deflink.conf->chanctx_conf) && + cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper, &chanreq.oper)) return 0; ieee80211_link_release_channel(&sdata->deflink); ret = ieee80211_link_use_channel(&sdata->deflink, &chanreq, - IEEE80211_CHANCTX_EXCLUSIVE); + IEEE80211_CHANCTX_SHARED); if (ret) return ret; done: @@ -1294,9 +1321,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, if (old) return -EALREADY; - if (params->smps_mode != NL80211_SMPS_OFF) - return -EOPNOTSUPP; - link->smps_mode = IEEE80211_SMPS_OFF; link->needed_rx_chains = sdata->local->rx_chains; @@ -1705,7 +1729,7 @@ static int sta_apply_auth_flags(struct ieee80211_local *local, * before drv_sta_state() is called. */ if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) - rate_control_rate_init(sta); + rate_control_rate_init_all_links(sta); ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); if (ret) @@ -2134,7 +2158,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, */ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) && test_sta_flag(sta, WLAN_STA_ASSOC)) - rate_control_rate_init(sta); + rate_control_rate_init_all_links(sta); return sta_info_insert(sta); } @@ -3046,13 +3070,30 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting txp_type = type; bool update_txp_type = false; bool has_monitor = false; + int user_power_level; lockdep_assert_wiphy(local->hw.wiphy); + switch (type) { + case NL80211_TX_POWER_AUTOMATIC: + user_power_level = IEEE80211_UNSET_POWER_LEVEL; + txp_type = NL80211_TX_POWER_LIMITED; + break; + case NL80211_TX_POWER_LIMITED: + case NL80211_TX_POWER_FIXED: + if (mbm < 0 || (mbm % 100)) + return -EOPNOTSUPP; + user_power_level = MBM_TO_DBM(mbm); + break; + default: + return -EINVAL; + } + if (wdev) { sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) return -EOPNOTSUPP; @@ -3062,57 +3103,67 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, return -EOPNOTSUPP; } - switch (type) { - case NL80211_TX_POWER_AUTOMATIC: - sdata->deflink.user_power_level = - IEEE80211_UNSET_POWER_LEVEL; - txp_type = NL80211_TX_POWER_LIMITED; - break; - case NL80211_TX_POWER_LIMITED: - case NL80211_TX_POWER_FIXED: - if (mbm < 0 || (mbm % 100)) - return -EOPNOTSUPP; - sdata->deflink.user_power_level = MBM_TO_DBM(mbm); - break; - } + for (int link_id = 0; + link_id < ARRAY_SIZE(sdata->link); + link_id++) { + struct ieee80211_link_data *link = + wiphy_dereference(wiphy, sdata->link[link_id]); - if (txp_type != sdata->vif.bss_conf.txpower_type) { - update_txp_type = true; - sdata->vif.bss_conf.txpower_type = txp_type; - } + if (!link) + continue; - ieee80211_recalc_txpower(sdata, update_txp_type); + link->user_power_level = user_power_level; + + if (txp_type != link->conf->txpower_type) { + update_txp_type = true; + link->conf->txpower_type = txp_type; + } + ieee80211_recalc_txpower(link, update_txp_type); + } return 0; } - switch (type) { - case NL80211_TX_POWER_AUTOMATIC: - local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; - txp_type = NL80211_TX_POWER_LIMITED; - break; - case NL80211_TX_POWER_LIMITED: - case NL80211_TX_POWER_FIXED: - if (mbm < 0 || (mbm % 100)) - return -EOPNOTSUPP; - local->user_power_level = MBM_TO_DBM(mbm); - break; - } + local->user_power_level = user_power_level; list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { has_monitor = true; continue; } - sdata->deflink.user_power_level = local->user_power_level; - if (txp_type != sdata->vif.bss_conf.txpower_type) - update_txp_type = true; - sdata->vif.bss_conf.txpower_type = txp_type; + + for (int link_id = 0; + link_id < ARRAY_SIZE(sdata->link); + link_id++) { + struct ieee80211_link_data *link = + wiphy_dereference(wiphy, sdata->link[link_id]); + + if (!link) + continue; + + link->user_power_level = local->user_power_level; + if (txp_type != link->conf->txpower_type) + update_txp_type = true; + link->conf->txpower_type = txp_type; + } } list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) continue; - ieee80211_recalc_txpower(sdata, update_txp_type); + + for (int link_id = 0; + link_id < ARRAY_SIZE(sdata->link); + link_id++) { + struct ieee80211_link_data *link = + wiphy_dereference(wiphy, sdata->link[link_id]); + + if (!link) + continue; + + ieee80211_recalc_txpower(link, update_txp_type); + } } if (has_monitor) { @@ -3124,7 +3175,8 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, update_txp_type = true; sdata->vif.bss_conf.txpower_type = txp_type; - ieee80211_recalc_txpower(sdata, update_txp_type); + ieee80211_recalc_txpower(&sdata->deflink, + update_txp_type); } } @@ -4301,7 +4353,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, if (chanctx_conf) { *chandef = link->conf->chanreq.oper; ret = 0; - } else if (local->open_count > 0 && + } else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && + local->open_count > 0 && local->open_count == local->monitors && sdata->vif.type == NL80211_IFTYPE_MONITOR) { *chandef = local->monitor_chanreq.oper; @@ -5023,6 +5076,13 @@ ieee80211_add_link_station(struct wiphy *wiphy, struct net_device *dev, return ret; } + if (test_sta_flag(sta, WLAN_STA_ASSOC)) { + struct link_sta_info *link_sta; + + link_sta = sdata_dereference(sta->link[params->link_id], sdata); + rate_control_rate_init(link_sta); + } + /* ieee80211_sta_activate_link frees the link upon failure */ return ieee80211_sta_activate_link(sta, params->link_id); } diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index cca6d14084d2..a442cb667520 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -323,22 +323,34 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, continue; switch (link->sdata->vif.type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - width = ieee80211_get_max_required_bw(link); - break; case NL80211_IFTYPE_STATION: + if (!link->sdata->vif.cfg.assoc) { + /* + * The AP's sta->bandwidth may not yet be set + * at this point (pre-association), so simply + * take the width from the chandef. We cannot + * have TDLS peers yet (only after association). + */ + width = link->conf->chanreq.oper.width; + break; + } /* - * The ap's sta->bandwidth is not set yet at this - * point, so take the width from the chandef, but - * account also for TDLS peers + * otherwise just use min_def like in AP, depending on what + * we currently think the AP STA (and possibly TDLS peers) + * require(s) */ - width = max(link->conf->chanreq.oper.width, - ieee80211_get_max_required_bw(link)); + fallthrough; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + width = ieee80211_get_max_required_bw(link); break; case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_NAN: continue; + case NL80211_IFTYPE_MONITOR: + WARN_ON_ONCE(!ieee80211_hw_check(&local->hw, + NO_VIRTUAL_MONITOR)); + fallthrough; case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_OCB: @@ -347,7 +359,6 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local, case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: - case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: WARN_ON_ONCE(1); @@ -409,7 +420,7 @@ _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local, if (!ctx->driver_present) return 0; - return IEEE80211_CHANCTX_CHANGE_MIN_WIDTH; + return IEEE80211_CHANCTX_CHANGE_MIN_DEF; } static void ieee80211_chan_bw_change(struct ieee80211_local *local, @@ -462,12 +473,12 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local, continue; /* vif changed to narrow BW and narrow BW for station wasn't - * requested or vise versa */ + * requested or vice versa */ if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed) continue; link_sta->pub->bandwidth = new_sta_bw; - rate_control_rate_update(local, sband, sta, link_id, + rate_control_rate_update(local, sband, link_sta, IEEE80211_RC_BW_CHANGED); } } @@ -905,7 +916,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, } if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { - ieee80211_recalc_txpower(sdata, false); + ieee80211_recalc_txpower(link, false); ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false); } @@ -956,6 +967,10 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, if (!link->sdata->u.mgd.associated) continue; break; + case NL80211_IFTYPE_MONITOR: + if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + continue; + break; case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: @@ -968,6 +983,11 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf) continue; + if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) { + rx_chains_dynamic = rx_chains_static = local->rx_chains; + break; + } + switch (link->smps_mode) { default: WARN_ONCE(1, "Invalid SMPS mode %d\n", @@ -1118,7 +1138,7 @@ ieee80211_replace_chanctx(struct ieee80211_local *local, * * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and * link2 from ctx1 request new different chandefs starting 2 - * in-place reserations with ctx4 and ctx5 replacing ctx1 and + * in-place reservations with ctx4 and ctx5 replacing ctx1 and * ctx2 respectively. Next link5 and link6 from ctx3 reserve * ctx4. If link3 and link4 remain on ctx2 as they are then this * fails unless `replace_ctx` from ctx5 is replaced with ctx3. @@ -1169,7 +1189,7 @@ ieee80211_replace_chanctx(struct ieee80211_local *local, static bool ieee80211_find_available_radio(struct ieee80211_local *local, const struct ieee80211_chan_req *chanreq, - int *radio_idx) + u32 radio_mask, int *radio_idx) { struct wiphy *wiphy = local->hw.wiphy; const struct wiphy_radio *radio; @@ -1180,6 +1200,9 @@ ieee80211_find_available_radio(struct ieee80211_local *local, return true; for (i = 0; i < wiphy->n_radio; i++) { + if (!(radio_mask & BIT(i))) + continue; + radio = &wiphy->radio[i]; if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper)) continue; @@ -1213,7 +1236,9 @@ int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); if (!new_ctx) { if (ieee80211_can_create_new_chanctx(local, -1) && - ieee80211_find_available_radio(local, chanreq, &radio_idx)) + ieee80211_find_available_radio(local, chanreq, + sdata->wdev.radio_mask, + &radio_idx)) new_ctx = ieee80211_new_chanctx(local, chanreq, mode, false, radio_idx); else @@ -1712,7 +1737,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) link, changed); - ieee80211_recalc_txpower(sdata, false); + ieee80211_recalc_txpower(link, false); } ieee80211_recalc_chanctx_chantype(local, ctx); @@ -1883,7 +1908,9 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, /* Note: context is now reserved */ if (ctx) reserved = true; - else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx)) + else if (!ieee80211_find_available_radio(local, chanreq, + sdata->wdev.radio_mask, + &radio_idx)) ctx = ERR_PTR(-EBUSY); else ctx = ieee80211_new_chanctx(local, chanreq, mode, diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 02b5476a4376..be2e486907f9 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -42,9 +42,8 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ } #define DEBUGFS_READONLY_FILE_OPS(name) \ -static const struct file_operations name## _ops = { \ +static const struct debugfs_short_fops name## _ops = { \ .read = name## _read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ }; @@ -142,10 +141,9 @@ static ssize_t aqm_write(struct file *file, return -EINVAL; } -static const struct file_operations aqm_ops = { +static const struct debugfs_short_fops aqm_ops = { .write = aqm_write, .read = aqm_read, - .open = simple_open, .llseek = default_llseek, }; @@ -194,10 +192,9 @@ static ssize_t airtime_flags_write(struct file *file, return count; } -static const struct file_operations airtime_flags_ops = { +static const struct debugfs_short_fops airtime_flags_ops = { .write = airtime_flags_write, .read = airtime_flags_read, - .open = simple_open, .llseek = default_llseek, }; @@ -225,9 +222,8 @@ static ssize_t aql_pending_read(struct file *file, buf, len); } -static const struct file_operations aql_pending_ops = { +static const struct debugfs_short_fops aql_pending_ops = { .read = aql_pending_read, - .open = simple_open, .llseek = default_llseek, }; @@ -305,10 +301,9 @@ static ssize_t aql_txq_limit_write(struct file *file, return count; } -static const struct file_operations aql_txq_limit_ops = { +static const struct debugfs_short_fops aql_txq_limit_ops = { .write = aql_txq_limit_write, .read = aql_txq_limit_read, - .open = simple_open, .llseek = default_llseek, }; @@ -355,10 +350,9 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, return count; } -static const struct file_operations aql_enable_ops = { +static const struct debugfs_short_fops aql_enable_ops = { .write = aql_enable_write, .read = aql_enable_read, - .open = simple_open, .llseek = default_llseek, }; @@ -406,10 +400,9 @@ static ssize_t force_tx_status_write(struct file *file, return count; } -static const struct file_operations force_tx_status_ops = { +static const struct debugfs_short_fops force_tx_status_ops = { .write = force_tx_status_write, .read = force_tx_status_read, - .open = simple_open, .llseek = default_llseek, }; @@ -434,9 +427,8 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, return count; } -static const struct file_operations reset_ops = { +static const struct debugfs_short_fops reset_ops = { .write = reset_write, - .open = simple_open, .llseek = noop_llseek, }; #endif @@ -456,6 +448,7 @@ static const char *hw_flag_names[] = { FLAG(SUPPORTS_DYNAMIC_PS), FLAG(MFP_CAPABLE), FLAG(WANT_MONITOR_VIF), + FLAG(NO_VIRTUAL_MONITOR), FLAG(NO_AUTO_VIF), FLAG(SW_CRYPTO_CONTROL), FLAG(SUPPORT_FAST_XMIT), @@ -623,9 +616,8 @@ static ssize_t stats_ ##name## _read(struct file *file, \ print_devstats_##name); \ } \ \ -static const struct file_operations stats_ ##name## _ops = { \ +static const struct debugfs_short_fops stats_ ##name## _ops = { \ .read = stats_ ##name## _read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ }; diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 7e54da508765..b3a64edea0f2 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -26,17 +26,15 @@ static ssize_t key_##name##_read(struct file *file, \ #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") #define KEY_OPS(name) \ -static const struct file_operations key_ ##name## _ops = { \ +static const struct debugfs_short_fops key_ ##name## _ops = { \ .read = key_##name##_read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } #define KEY_OPS_W(name) \ -static const struct file_operations key_ ##name## _ops = { \ +static const struct debugfs_short_fops key_ ##name## _ops = { \ .read = key_##name##_read, \ .write = key_##name##_write, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } @@ -49,9 +47,8 @@ static const struct file_operations key_ ##name## _ops = { \ #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") #define KEY_CONF_OPS(name) \ -static const struct file_operations key_ ##name## _ops = { \ +static const struct debugfs_short_fops key_ ##name## _ops = { \ .read = key_conf_##name##_read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 68596ef78b15..a9bc2fd59f55 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -221,10 +221,9 @@ static ssize_t ieee80211_if_fmt_##name( \ } #define _IEEE80211_IF_FILE_OPS(name, _read, _write) \ -static const struct file_operations name##_ops = { \ +static const struct debugfs_short_fops name##_ops = { \ .read = (_read), \ .write = (_write), \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 1e9389c49a57..a67a9d316008 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -30,17 +30,15 @@ static ssize_t sta_ ##name## _read(struct file *file, \ #define STA_READ_D(name, field) STA_READ(name, field, "%d\n") #define STA_OPS(name) \ -static const struct file_operations sta_ ##name## _ops = { \ +static const struct debugfs_short_fops sta_ ##name## _ops = { \ .read = sta_##name##_read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } #define STA_OPS_RW(name) \ -static const struct file_operations sta_ ##name## _ops = { \ +static const struct debugfs_short_fops sta_ ##name## _ops = { \ .read = sta_##name##_read, \ .write = sta_##name##_write, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } @@ -450,9 +448,8 @@ STA_OPS_RW(agg_status); /* link sta attributes */ #define LINK_STA_OPS(name) \ -static const struct file_operations link_sta_ ##name## _ops = { \ +static const struct debugfs_short_fops link_sta_ ##name## _ops = { \ .read = link_sta_##name##_read, \ - .open = simple_open, \ .llseek = generic_file_llseek, \ } diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index fe868b521622..299d38e9e863 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -65,6 +65,7 @@ int drv_add_interface(struct ieee80211_local *local, if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || (sdata->vif.type == NL80211_IFTYPE_MONITOR && !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)))) return -EINVAL; @@ -181,9 +182,10 @@ int drv_sta_set_txpwr(struct ieee80211_local *local, return ret; } -void drv_sta_rc_update(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, u32 changed) +void drv_link_sta_rc_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_sta *link_sta, + u32 changed) { sdata = get_bss_sdata(sdata); if (!check_sdata_in_driver(sdata)) @@ -193,10 +195,10 @@ void drv_sta_rc_update(struct ieee80211_local *local, (sdata->vif.type != NL80211_IFTYPE_ADHOC && sdata->vif.type != NL80211_IFTYPE_MESH_POINT)); - trace_drv_sta_rc_update(local, sdata, sta, changed); - if (local->ops->sta_rc_update) - local->ops->sta_rc_update(&local->hw, &sdata->vif, - sta, changed); + trace_drv_link_sta_rc_update(local, sdata, link_sta, changed); + if (local->ops->link_sta_rc_update) + local->ops->link_sta_rc_update(&local->hw, &sdata->vif, + link_sta, changed); trace_drv_return_void(local); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index d382d9729e85..edd1e4d4ad9d 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -594,9 +594,9 @@ int drv_sta_set_txpwr(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, struct sta_info *sta); -void drv_sta_rc_update(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, u32 changed); +void drv_link_sta_rc_update(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_sta *link_sta, u32 changed); static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, @@ -1728,4 +1728,16 @@ drv_can_neg_ttlm(struct ieee80211_local *local, return res; } + +static inline void +drv_prep_add_interface(struct ieee80211_local *local, + enum nl80211_iftype type) +{ + trace_drv_prep_add_interface(local, type); + if (local->ops->prep_add_interface) + local->ops->prep_add_interface(&local->hw, type); + + trace_drv_return_void(local); +} + #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c index ddc7acc68335..7a3116c36df9 100644 --- a/net/mac80211/eht.c +++ b/net/mac80211/eht.c @@ -2,7 +2,7 @@ /* * EHT handling * - * Copyright(c) 2021-2023 Intel Corporation + * Copyright(c) 2021-2024 Intel Corporation */ #include "ieee80211_i.h" @@ -75,4 +75,23 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata, link_sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(link_sta); link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); + + switch (u8_get_bits(eht_cap->eht_cap_elem.mac_cap_info[0], + IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK)) { + case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454: + link_sta->pub->agg.max_amsdu_len = + IEEE80211_MAX_MPDU_LEN_VHT_11454; + break; + case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991: + link_sta->pub->agg.max_amsdu_len = + IEEE80211_MAX_MPDU_LEN_VHT_7991; + break; + case IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_3895: + default: + link_sta->pub->agg.max_amsdu_len = + IEEE80211_MAX_MPDU_LEN_VHT_3895; + break; + } + + ieee80211_sta_recalc_aggregates(&link_sta->sta->sta); } diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3f74bbceeca5..a1b4178deccf 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -569,7 +569,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) if (!sta->sdata->u.ibss.control_port) sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED); - rate_control_rate_init(sta); + rate_control_rate_init(&sta->deflink); /* If it fails, maybe we raced another insertion? */ if (sta_info_insert_rcu(sta)) @@ -1068,11 +1068,12 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, /* Force rx_nss recalculation */ sta->sta.deflink.rx_nss = 0; - rate_control_rate_init(sta); + rate_control_rate_init(&sta->deflink); if (sta->sta.deflink.rx_nss != rx_nss) changed |= IEEE80211_RC_NSS_CHANGED; - drv_sta_rc_update(local, sdata, &sta->sta, changed); + drv_link_sta_rc_update(local, sdata, &sta->sta.deflink, + changed); } rcu_read_unlock(); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4f0390918b60..7dcb46120abc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1015,8 +1015,6 @@ struct ieee80211_link_data_managed { int wmm_last_param_set; int mu_edca_last_param_set; - - u8 bss_param_ch_cnt; }; struct ieee80211_link_data_ap { @@ -1370,7 +1368,7 @@ struct ieee80211_local { spinlock_t queue_stop_reason_lock; int open_count; - int monitors, cooked_mntrs; + int monitors, cooked_mntrs, tx_mntrs; /* number of interfaces with corresponding FIF_ flags */ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll, fif_probe_req; @@ -2035,8 +2033,8 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); int ieee80211_add_virtual_monitor(struct ieee80211_local *local); void ieee80211_del_virtual_monitor(struct ieee80211_local *local); -bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata); -void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, +bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link); +void ieee80211_recalc_txpower(struct ieee80211_link_data *link, bool update_bss); void ieee80211_recalc_offload(struct ieee80211_local *local); @@ -2196,8 +2194,6 @@ ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta) return _ieee80211_sta_cur_vht_bw(link_sta, NULL); } void ieee80211_sta_init_nss(struct link_sta_info *link_sta); -enum ieee80211_sta_rx_bandwidth -ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width); enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct link_sta_info *link_sta); void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, @@ -2452,7 +2448,7 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local) /* * If quiescing is set, we are racing with __ieee80211_suspend. * __ieee80211_suspend flushes the workers after setting quiescing, - * and we check quiescing / suspended before enqueing new workers. + * and we check quiescing / suspended before enqueuing new workers. * We should abort the worker to avoid the races below. */ if (local->quiescing) @@ -2545,8 +2541,8 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, const struct cfg80211_chan_def *chandef); u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata); -u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef); -u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, +u8 *ieee80211_ie_build_he_oper(u8 *pos, const struct cfg80211_chan_def *chandef); +u8 *ieee80211_ie_build_eht_oper(u8 *pos, const struct cfg80211_chan_def *chandef, const struct ieee80211_sta_eht_cap *eht_cap); int ieee80211_parse_bitrates(enum nl80211_chan_width width, const struct ieee80211_supported_band *sband, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6ef0990d3d29..a8fbedd530f4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -44,13 +44,13 @@ static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work); -bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) +bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link) { struct ieee80211_chanctx_conf *chanctx_conf; int power; rcu_read_lock(); - chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf); + chanctx_conf = rcu_dereference(link->conf->chanctx_conf); if (!chanctx_conf) { rcu_read_unlock(); return false; @@ -59,27 +59,26 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) power = ieee80211_chandef_max_power(&chanctx_conf->def); rcu_read_unlock(); - if (sdata->deflink.user_power_level != IEEE80211_UNSET_POWER_LEVEL) - power = min(power, sdata->deflink.user_power_level); + if (link->user_power_level != IEEE80211_UNSET_POWER_LEVEL) + power = min(power, link->user_power_level); - if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL) - power = min(power, sdata->deflink.ap_power_level); + if (link->ap_power_level != IEEE80211_UNSET_POWER_LEVEL) + power = min(power, link->ap_power_level); - if (power != sdata->vif.bss_conf.txpower) { - sdata->vif.bss_conf.txpower = power; - ieee80211_hw_config(sdata->local, 0); + if (power != link->conf->txpower) { + link->conf->txpower = power; return true; } return false; } -void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata, +void ieee80211_recalc_txpower(struct ieee80211_link_data *link, bool update_bss) { - if (__ieee80211_recalc_txpower(sdata) || - (update_bss && ieee80211_sdata_running(sdata))) - ieee80211_link_info_change_notify(sdata, &sdata->deflink, + if (__ieee80211_recalc_txpower(link) || + (update_bss && ieee80211_sdata_running(link->sdata))) + ieee80211_link_info_change_notify(link->sdata, link, BSS_CHANGED_TXPOWER); } @@ -279,8 +278,13 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata, ret = eth_mac_addr(sdata->dev, sa); if (ret == 0) { - memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); - ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr); + if (check_dup) { + memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); + ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr); + } else { + memset(sdata->vif.addr, 0, ETH_ALEN); + memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN); + } } /* Regardless of eth_mac_addr() return we still want to add the @@ -699,9 +703,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do ieee80211_recalc_idle(local); ieee80211_recalc_offload(local); - if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) + if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) break; + ieee80211_link_release_channel(&sdata->deflink); fallthrough; default: if (!going_down) @@ -1087,6 +1093,8 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, ADJUST(CONTROL, control); ADJUST(CONTROL, pspoll); ADJUST(OTHER_BSS, other_bss); + if (!(flags & MONITOR_FLAG_SKIP_TX)) + local->tx_mntrs += offset; #undef ADJUST } @@ -1131,7 +1139,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) ASSERT_RTNL(); lockdep_assert_wiphy(local->hw.wiphy); - if (local->monitor_sdata) + if (local->monitor_sdata || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) return 0; sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); @@ -1193,6 +1202,9 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; + if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + return; + ASSERT_RTNL(); lockdep_assert_wiphy(local->hw.wiphy); @@ -1328,7 +1340,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) break; } - if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { + if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { res = drv_add_interface(local, sdata); if (res) goto err_stop; @@ -2176,9 +2189,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, ieee80211_set_default_queues(sdata); - sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL; - sdata->deflink.user_power_level = local->user_power_level; - /* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); diff --git a/net/mac80211/link.c b/net/mac80211/link.c index 0bbac64d5fa0..e8def387d0f8 100644 --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -36,6 +36,9 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata, link->conf = link_conf; link_conf->link_id = link_id; link_conf->vif = &sdata->vif; + link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; + link->user_power_level = sdata->local->user_power_level; + link_conf->txpower = INT_MIN; wiphy_work_init(&link->csa.finalize_work, ieee80211_csa_finalize_work); @@ -385,6 +388,37 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata, jiffies); } + for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { + struct ieee80211_link_data *link; + + link = sdata_dereference(sdata->link[link_id], sdata); + + /* + * This call really should not fail. Unfortunately, it appears + * that this may happen occasionally with some drivers. Should + * it happen, we are stuck in a bad place as going backwards is + * not really feasible. + * + * So lets just tell link_use_channel that it must not fail to + * assign the channel context (from mac80211's perspective) and + * assume the driver is going to trigger a recovery flow if it + * had a failure. + * That really is not great nor guaranteed to work. But at least + * the internal mac80211 state remains consistent and there is + * a chance that we can recover. + */ + ret = _ieee80211_link_use_channel(link, + &link->conf->chanreq, + IEEE80211_CHANCTX_SHARED, + true); + WARN_ON_ONCE(ret); + + /* + * inform about the link info changed parameters after all + * stations are also added + */ + } + list_for_each_entry(sta, &local->sta_list, list) { if (sdata != sta->sdata) continue; @@ -428,26 +462,6 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata, link = sdata_dereference(sdata->link[link_id], sdata); - /* - * This call really should not fail. Unfortunately, it appears - * that this may happen occasionally with some drivers. Should - * it happen, we are stuck in a bad place as going backwards is - * not really feasible. - * - * So lets just tell link_use_channel that it must not fail to - * assign the channel context (from mac80211's perspective) and - * assume the driver is going to trigger a recovery flow if it - * had a failure. - * That really is not great nor guaranteed to work. But at least - * the internal mac80211 state remains consistent and there is - * a chance that we can recover. - */ - ret = _ieee80211_link_use_channel(link, - &link->conf->chanreq, - IEEE80211_CHANCTX_SHARED, - true); - WARN_ON_ONCE(ret); - ieee80211_mgd_set_link_qos_params(link); ieee80211_link_info_change_notify(sdata, link, BSS_CHANGED_ERP_CTS_PROT | diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 640239f4425b..cb5f16366b9c 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1482,7 +1482,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (!elems) return; - /* ignore non-mesh or secure / unsecure mismatch */ + /* ignore non-mesh or secure / insecure mismatch */ if ((!elems->mesh_id || !elems->mesh_config) || (elems->rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) || (!elems->rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 579d0f24ac9d..4e9546e998b6 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -220,12 +220,12 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, /** * mesh_path_error_tx - Sends a PERR mesh management frame * + * @sdata: local mesh subif * @ttl: allowed remaining hops * @target: broken destination * @target_sn: SN of the broken destination * @target_rcode: reason code for this PERR * @ra: node this frame is addressed to - * @sdata: local mesh subif * * Note: This function may be called with driver locks taken that the driver * also acquires in the TX path. To avoid a deadlock we don't transmit the @@ -1137,8 +1137,8 @@ enddiscovery: /** * mesh_nexthop_resolve - lookup next hop; conditionally start path discovery * - * @skb: 802.11 frame to be sent * @sdata: network subif the frame will be sent through + * @skb: 802.11 frame to be sent * * Lookup next hop for given skb and start path discovery if no * forwarding information is found. @@ -1245,8 +1245,8 @@ void mesh_path_refresh(struct ieee80211_sub_if_data *sdata, * this function is considered "using" the associated mpath, so preempt a path * refresh if this mpath expires soon. * - * @skb: 802.11 frame to be sent * @sdata: network subif the frame will be sent through + * @skb: 802.11 frame to be sent * * Returns: 0 if the next hop was found. Nonzero otherwise. */ diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 30c0d89203af..9f9cb5af0a97 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -300,8 +300,8 @@ __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx) /** * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index - * @idx: index * @sdata: local subif, or NULL for all entries + * @idx: index * * Returns: pointer to the mesh path structure, or NULL if not found. * @@ -315,8 +315,8 @@ mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) /** * mpp_path_lookup_by_idx - look up a path in the proxy path table by its index - * @idx: index * @sdata: local subif, or NULL for all entries + * @idx: index * * Returns: pointer to the proxy path structure, or NULL if not found. * @@ -670,8 +670,8 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata, /** * mesh_path_add - allocate and add a new path to the mesh path table - * @dst: destination address of the path (ETH_ALEN length) * @sdata: local subif + * @dst: destination address of the path (ETH_ALEN length) * * Returns: 0 on success * @@ -916,8 +916,8 @@ static int table_path_del(struct mesh_table *tbl, /** * mesh_path_del - delete a mesh path from the table * - * @addr: dst address (ETH_ALEN length) * @sdata: local subif + * @addr: dst address (ETH_ALEN length) * * Returns: 0 if successful */ @@ -996,8 +996,8 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) /** * mesh_path_discard_frame - discard a frame whose path could not be resolved * - * @skb: frame to discard * @sdata: network subif the frame was to be sent through + * @skb: frame to discard * * Locking: the function must me called within a rcu_read_lock region */ diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 8f2b492a9fe9..6ea35c88dc48 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -486,10 +486,11 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, sta->sta.deflink.bandwidth = IEEE80211_STA_RX_BW_20; } + /* FIXME: this check is wrong without SW rate control */ if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) - rate_control_rate_init(sta); + rate_control_rate_init(&sta->deflink); else - rate_control_rate_update(local, sband, sta, 0, changed); + rate_control_rate_update(local, sband, &sta->deflink, changed); out: spin_unlock_bh(&sta->mesh->plink_lock); } @@ -667,7 +668,7 @@ void mesh_plink_timer(struct timer_list *t) /* * This STA is valid because sta_info_destroy() will * del_timer_sync() this timer after having made sure - * it cannot be readded (by deleting the plink.) + * it cannot be re-added (by deleting the plink.) */ sta = mesh->plink_sta; diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 8cf3f395f52f..3a66b4cefca7 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -175,7 +175,7 @@ static void mesh_sync_offset_adjust_tsf(struct ieee80211_sub_if_data *sdata, spin_lock_bh(&ifmsh->sync_offset_lock); if (ifmsh->sync_offset_clockdrift_max > TOFFSET_MINIMUM_ADJUSTMENT) { - /* Since ajusting the tsf here would + /* Since adjusting the tsf here would * require a possibly blocking call * to the driver tsf setter, we punt * the tsf adjustment to the mesh tasklet diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0303972c23e4..480b664151c9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -31,6 +31,8 @@ #include "led.h" #include "fils_aead.h" +#include <kunit/static_stub.h> + #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) @@ -2643,9 +2645,91 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link, &ifmgd->csa_connection_drop_work); } +struct sta_bss_param_ch_cnt_data { + struct ieee80211_sub_if_data *sdata; + u8 reporting_link_id; + u8 mld_id; +}; + +static enum cfg80211_rnr_iter_ret +ieee80211_sta_bss_param_ch_cnt_iter(void *_data, u8 type, + const struct ieee80211_neighbor_ap_info *info, + const u8 *tbtt_info, u8 tbtt_info_len) +{ + struct sta_bss_param_ch_cnt_data *data = _data; + struct ieee80211_sub_if_data *sdata = data->sdata; + const struct ieee80211_tbtt_info_ge_11 *ti; + u8 bss_param_ch_cnt; + int link_id; + + if (type != IEEE80211_TBTT_INFO_TYPE_TBTT) + return RNR_ITER_CONTINUE; + + if (tbtt_info_len < sizeof(*ti)) + return RNR_ITER_CONTINUE; + + ti = (const void *)tbtt_info; + + if (ti->mld_params.mld_id != data->mld_id) + return RNR_ITER_CONTINUE; + + link_id = le16_get_bits(ti->mld_params.params, + IEEE80211_RNR_MLD_PARAMS_LINK_ID); + bss_param_ch_cnt = + le16_get_bits(ti->mld_params.params, + IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT); + + if (bss_param_ch_cnt != 255 && + link_id < ARRAY_SIZE(sdata->link)) { + struct ieee80211_link_data *link = + sdata_dereference(sdata->link[link_id], sdata); + + if (link && link->conf->bss_param_ch_cnt != bss_param_ch_cnt) { + link->conf->bss_param_ch_cnt = bss_param_ch_cnt; + link->conf->bss_param_ch_cnt_link_id = + data->reporting_link_id; + } + } + + return RNR_ITER_CONTINUE; +} + +static void +ieee80211_mgd_update_bss_param_ch_cnt(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss_conf *bss_conf, + struct ieee802_11_elems *elems) +{ + struct sta_bss_param_ch_cnt_data data = { + .reporting_link_id = bss_conf->link_id, + .sdata = sdata, + }; + int bss_param_ch_cnt; + + if (!elems->ml_basic) + return; + + data.mld_id = ieee80211_mle_get_mld_id((const void *)elems->ml_basic); + + cfg80211_iter_rnr(elems->ie_start, elems->total_len, + ieee80211_sta_bss_param_ch_cnt_iter, &data); + + bss_param_ch_cnt = + ieee80211_mle_get_bss_param_ch_cnt((const void *)elems->ml_basic); + + /* + * Update bss_param_ch_cnt_link_id even if bss_param_ch_cnt + * didn't change to indicate that we got a beacon on our own + * link. + */ + if (bss_param_ch_cnt >= 0 && bss_param_ch_cnt != 255) { + bss_conf->bss_param_ch_cnt = bss_param_ch_cnt; + bss_conf->bss_param_ch_cnt_link_id = + bss_conf->link_id; + } +} + static bool -ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *channel, +ieee80211_find_80211h_pwr_constr(struct ieee80211_channel *channel, const u8 *country_ie, u8 country_ie_len, const u8 *pwr_constr_elem, int *chan_pwr, int *pwr_reduction) @@ -2715,8 +2799,7 @@ ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata, return have_chan_pwr; } -static void ieee80211_find_cisco_dtpc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *channel, +static void ieee80211_find_cisco_dtpc(struct ieee80211_channel *channel, const u8 *cisco_dtpc_ie, int *pwr_level) { @@ -2750,7 +2833,7 @@ static u64 ieee80211_handle_pwr_constr(struct ieee80211_link_data *link, (capab & cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT) || capab & cpu_to_le16(WLAN_CAPABILITY_RADIO_MEASURE))) { has_80211h_pwr = ieee80211_find_80211h_pwr_constr( - sdata, channel, country_ie, country_ie_len, + channel, country_ie, country_ie_len, pwr_constr_ie, &chan_pwr, &pwr_reduction_80211h); pwr_level_80211h = max_t(int, 0, chan_pwr - pwr_reduction_80211h); @@ -2758,7 +2841,7 @@ static u64 ieee80211_handle_pwr_constr(struct ieee80211_link_data *link, if (cisco_dtpc_ie) { ieee80211_find_cisco_dtpc( - sdata, channel, cisco_dtpc_ie, &pwr_level_cisco); + channel, cisco_dtpc_ie, &pwr_level_cisco); has_cisco_pwr = true; } @@ -2791,7 +2874,7 @@ static u64 ieee80211_handle_pwr_constr(struct ieee80211_link_data *link, } link->ap_power_level = new_ap_level; - if (__ieee80211_recalc_txpower(sdata)) + if (__ieee80211_recalc_txpower(link)) return BSS_CHANGED_TXPOWER; return 0; } @@ -4101,8 +4184,13 @@ EXPORT_SYMBOL(ieee80211_beacon_loss); void ieee80211_connection_loss(struct ieee80211_vif *vif) { - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_hw *hw = &sdata->local->hw; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_hw *hw; + + KUNIT_STATIC_STUB_REDIRECT(ieee80211_connection_loss, vif); + + sdata = vif_to_sdata(vif); + hw = &sdata->local->hw; trace_api_connection_loss(sdata); @@ -4667,7 +4755,8 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, ret = false; goto out; } - link->u.mgd.bss_param_ch_cnt = bss_param_ch_cnt; + bss_conf->bss_param_ch_cnt = bss_param_ch_cnt; + bss_conf->bss_param_ch_cnt_link_id = link_id; } } else if (elems->parse_error & IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC || !elems->prof || @@ -4677,6 +4766,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, } else { const u8 *ptr = elems->prof->variable + elems->prof->sta_info_len - 1; + int bss_param_ch_cnt; /* * During parsing, we validated that these fields exist, @@ -4684,8 +4774,10 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, */ capab_info = get_unaligned_le16(ptr); assoc_data->link[link_id].status = get_unaligned_le16(ptr + 2); - link->u.mgd.bss_param_ch_cnt = + bss_param_ch_cnt = ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(elems->prof); + bss_conf->bss_param_ch_cnt = bss_param_ch_cnt; + bss_conf->bss_param_ch_cnt_link_id = link_id; if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) { link_info(link, "association response status code=%u\n", @@ -5665,7 +5757,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, /* links might have changed due to rejected ones, set them again */ ieee80211_vif_set_links(sdata, valid_links, dormant_links); - rate_control_rate_init(sta); + rate_control_rate_init_all_links(sta); if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) { set_sta_flag(sta, WLAN_STA_MFP); @@ -6913,6 +7005,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, /* note that after this elems->ml_basic can no longer be used fully */ ieee80211_mgd_check_cross_link_csa(sdata, rx_status->link_id, elems); + ieee80211_mgd_update_bss_param_ch_cnt(sdata, bss_conf, elems); + if (!link->u.mgd.disable_wmm_tracking && ieee80211_sta_wmm_params(local, link, elems->wmm_param, elems->wmm_param_len, diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c index f4c51e4a1e29..6218abc3e441 100644 --- a/net/mac80211/ocb.c +++ b/net/mac80211/ocb.c @@ -4,7 +4,7 @@ * * Copyright: (c) 2014 Czech Technical University in Prague * (c) 2014 Volkswagen Group Research - * Copyright (C) 2022 - 2023 Intel Corporation + * Copyright (C) 2022 - 2024 Intel Corporation * Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz> * Funded by: Volkswagen Group Research */ @@ -96,7 +96,7 @@ static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta) sta_info_move_state(sta, IEEE80211_STA_ASSOC); sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); - rate_control_rate_init(sta); + rate_control_rate_init(&sta->deflink); /* If it fails, maybe we raced another insertion? */ if (sta_info_insert_rcu(sta)) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3dc9752188d5..0d056db9f81e 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -28,8 +28,9 @@ module_param(ieee80211_default_rc_algo, charp, 0644); MODULE_PARM_DESC(ieee80211_default_rc_algo, "Default rate control algorithm for mac80211 to use"); -void rate_control_rate_init(struct sta_info *sta) +void rate_control_rate_init(struct link_sta_info *link_sta) { + struct sta_info *sta = link_sta->sta; struct ieee80211_local *local = sta->sdata->local; struct rate_control_ref *ref = sta->rate_ctrl; struct ieee80211_sta *ista = &sta->sta; @@ -37,11 +38,15 @@ void rate_control_rate_init(struct sta_info *sta) struct ieee80211_supported_band *sband; struct ieee80211_chanctx_conf *chanctx_conf; - ieee80211_sta_init_nss(&sta->deflink); + ieee80211_sta_init_nss(link_sta); if (!ref) return; + /* SW rate control isn't supported with MLO right now */ + if (WARN_ON(ieee80211_vif_is_mld(&sta->sdata->vif))) + return; + rcu_read_lock(); chanctx_conf = rcu_dereference(sta->sdata->vif.bss_conf.chanctx_conf); @@ -67,6 +72,21 @@ void rate_control_rate_init(struct sta_info *sta) set_sta_flag(sta, WLAN_STA_RATE_CONTROL); } +void rate_control_rate_init_all_links(struct sta_info *sta) +{ + int link_id; + + for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) { + struct link_sta_info *link_sta; + + link_sta = sdata_dereference(sta->link[link_id], sta->sdata); + if (!link_sta) + continue; + + rate_control_rate_init(link_sta); + } +} + void rate_control_tx_status(struct ieee80211_local *local, struct ieee80211_tx_status *st) { @@ -93,16 +113,15 @@ void rate_control_tx_status(struct ieee80211_local *local, void rate_control_rate_update(struct ieee80211_local *local, struct ieee80211_supported_band *sband, - struct sta_info *sta, unsigned int link_id, + struct link_sta_info *link_sta, u32 changed) { struct rate_control_ref *ref = local->rate_ctrl; + struct sta_info *sta = link_sta->sta; struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; struct ieee80211_chanctx_conf *chanctx_conf; - WARN_ON(link_id != 0); - if (ref && ref->ops->rate_update) { rcu_read_lock(); @@ -120,7 +139,8 @@ void rate_control_rate_update(struct ieee80211_local *local, } if (sta->uploaded) - drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); + drv_link_sta_rc_update(local, sta->sdata, link_sta->pub, + changed); } int ieee80211_rate_control_register(const struct rate_control_ops *ops) @@ -229,9 +249,8 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf, ref->ops->name, len); } -const struct file_operations rcname_ops = { +const struct debugfs_short_fops rcname_ops = { .read = rcname_read, - .open = simple_open, .llseek = default_llseek, }; #endif diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index d6190f10fe7c..5e4bde598212 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -3,7 +3,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022, 2024 Intel Corporation */ #ifndef IEEE80211_RATE_H @@ -29,11 +29,11 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, void rate_control_tx_status(struct ieee80211_local *local, struct ieee80211_tx_status *st); -void rate_control_rate_init(struct sta_info *sta); +void rate_control_rate_init(struct link_sta_info *link_sta); +void rate_control_rate_init_all_links(struct sta_info *sta); void rate_control_rate_update(struct ieee80211_local *local, struct ieee80211_supported_band *sband, - struct sta_info *sta, - unsigned int link_id, + struct link_sta_info *link_sta, u32 changed); static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, @@ -62,7 +62,7 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta) #endif } -extern const struct file_operations rcname_ops; +extern const struct debugfs_short_fops rcname_ops; static inline void rate_control_add_debugfs(struct ieee80211_local *local) { diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 6bf3b4444a43..706cbc99f718 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -1053,7 +1053,7 @@ minstrel_ht_refill_sample_rates(struct minstrel_ht_sta *mi) * - max_prob_rate must use only one stream, as a tradeoff between delivery * probability and throughput during strong fluctuations * - as long as the max prob rate has a probability of more than 75%, pick - * higher throughput rates, even if the probablity is a bit lower + * higher throughput rates, even if the probability is a bit lower */ static void minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 694b43091fec..2bec18fc1b03 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -508,18 +508,13 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; - if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) - flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; if (status->flag & RX_FLAG_AMPDU_EOF_BIT_KNOWN) flags |= IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN; if (status->flag & RX_FLAG_AMPDU_EOF_BIT) flags |= IEEE80211_RADIOTAP_AMPDU_EOF; put_unaligned_le16(flags, pos); pos += 2; - if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) - *pos++ = status->ampdu_delimiter_crc; - else - *pos++ = 0; + *pos++ = 0; *pos++ = 0; } @@ -767,8 +762,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, struct ieee80211_rate *rate) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); - struct ieee80211_sub_if_data *sdata; - struct sk_buff *monskb = NULL; + struct ieee80211_sub_if_data *sdata, *prev_sdata = NULL; + struct sk_buff *skb, *monskb = NULL; int present_fcs_len = 0; unsigned int rtap_space = 0; struct ieee80211_sub_if_data *monitor_sdata = @@ -842,40 +837,52 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space); list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) { - bool last_monitor = list_is_last(&sdata->u.mntr.list, - &local->mon_list); + struct cfg80211_chan_def *chandef; + + chandef = &sdata->vif.bss_conf.chanreq.oper; + if (chandef->chan && + chandef->chan->center_freq != status->freq) + continue; + + if (!prev_sdata) { + prev_sdata = sdata; + continue; + } + + if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space); if (!monskb) monskb = ieee80211_make_monitor_skb(local, &origskb, rate, rtap_space, - only_monitor && - last_monitor); + false); + if (!monskb) + continue; - if (monskb) { - struct sk_buff *skb; + skb = skb_clone(monskb, GFP_ATOMIC); + if (!skb) + continue; - if (last_monitor) { - skb = monskb; - monskb = NULL; - } else { - skb = skb_clone(monskb, GFP_ATOMIC); - } + skb->dev = prev_sdata->dev; + dev_sw_netstats_rx_add(skb->dev, skb->len); + netif_receive_skb(skb); + prev_sdata = sdata; + } - if (skb) { - skb->dev = sdata->dev; - dev_sw_netstats_rx_add(skb->dev, skb->len); - netif_receive_skb(skb); - } + if (prev_sdata) { + if (monskb) + skb = monskb; + else + skb = ieee80211_make_monitor_skb(local, &origskb, + rate, rtap_space, + only_monitor); + if (skb) { + skb->dev = prev_sdata->dev; + dev_sw_netstats_rx_add(skb->dev, skb->len); + netif_receive_skb(skb); } - - if (last_monitor) - break; } - /* this happens if last_monitor was erroneously false */ - dev_kfree_skb(monskb); - - /* ditto */ if (!origskb) return NULL; @@ -3568,7 +3575,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sband = rx->local->hw.wiphy->bands[status->band]; - rate_control_rate_update(local, sband, rx->sta, 0, + rate_control_rate_update(local, sband, rx->link_sta, IEEE80211_RC_SMPS_CHANGED); cfg80211_sta_opmode_change_notify(sdata->dev, rx->sta->addr, @@ -3605,7 +3612,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; - rate_control_rate_update(local, sband, rx->sta, 0, + rate_control_rate_update(local, sband, rx->link_sta, IEEE80211_RC_BW_CHANGED); cfg80211_sta_opmode_change_notify(sdata->dev, rx->sta->addr, diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index adb88c06b598..cb7079071885 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -1176,14 +1176,14 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, unsigned int n_channels) { struct ieee80211_local *local = sdata->local; - int ret = -EBUSY, i, n_ch = 0; + int i, n_ch = 0; enum nl80211_band band; lockdep_assert_wiphy(local->hw.wiphy); /* busy scanning */ if (local->scan_req) - goto unlock; + return -EBUSY; /* fill internal scan request */ if (!channels) { @@ -1200,7 +1200,9 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, &local->hw.wiphy->bands[band]->channels[i]; if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_DISABLED)) + IEEE80211_CHAN_DISABLED) || + !cfg80211_wdev_channel_allowed(&sdata->wdev, + tmp_ch)) continue; local->int_scan_req->channels[n_ch] = tmp_ch; @@ -1209,21 +1211,23 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, } if (WARN_ON_ONCE(n_ch == 0)) - goto unlock; + return -EINVAL; local->int_scan_req->n_channels = n_ch; } else { for (i = 0; i < n_channels; i++) { if (channels[i]->flags & (IEEE80211_CHAN_NO_IR | - IEEE80211_CHAN_DISABLED)) + IEEE80211_CHAN_DISABLED) || + !cfg80211_wdev_channel_allowed(&sdata->wdev, + channels[i])) continue; local->int_scan_req->channels[n_ch] = channels[i]; n_ch++; } - if (WARN_ON_ONCE(n_ch == 0)) - goto unlock; + if (n_ch == 0) + return -EINVAL; local->int_scan_req->n_channels = n_ch; } @@ -1233,9 +1237,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); local->int_scan_req->ssids[0].ssid_len = ssid_len; - ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); - unlock: - return ret; + return __ieee80211_start_scan(sdata, sdata->local->int_scan_req); } void ieee80211_scan_cancel(struct ieee80211_local *local) diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 073ff9e0f397..c6015cd00372 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -377,13 +377,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, /* capture the AP chandef before (potential) downgrading */ csa_ie->chanreq.ap = new_chandef; - if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_320 && - new_chandef.width == NL80211_CHAN_WIDTH_320) - ieee80211_chandef_downgrade(&new_chandef, NULL); - - if (conn->bw_limit < IEEE80211_CONN_BW_LIMIT_160 && - (new_chandef.width == NL80211_CHAN_WIDTH_80P80 || - new_chandef.width == NL80211_CHAN_WIDTH_160)) + while (conn->bw_limit < + ieee80211_min_bw_limit_from_chandef(&new_chandef)) ieee80211_chandef_downgrade(&new_chandef, NULL); if (!cfg80211_chandef_compatible(&new_chandef, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 9195d5a2de0a..9f89fb5bee37 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -169,7 +169,7 @@ struct sta_info; * @buf_size: reorder buffer size at receiver * @failed_bar_ssn: ssn of the last failed BAR tx attempt * @bar_pending: BAR needs to be re-sent - * @amsdu: support A-MSDU withing A-MDPU + * @amsdu: support A-MSDU within A-MDPU * @ssn: starting sequence number of the session * * This structure's lifetime is managed by RCU, assignments to diff --git a/net/mac80211/status.c b/net/mac80211/status.c index b41b867f43b2..5f28f3633fa0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -927,6 +927,9 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb, if (!ieee80211_sdata_running(sdata)) continue; + if (sdata->u.mntr.flags & MONITOR_FLAG_SKIP_TX) + continue; + if ((sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) && !send_to_cooked) continue; @@ -1099,7 +1102,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, * This is a bit racy but we can avoid a lot of work * with this test... */ - if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { + if (!local->tx_mntrs && (!send_to_cooked || !local->cooked_mntrs)) { if (status->free_list) list_add_tail(&skb->list, status->free_list); else diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index f07b40916485..2f92e7c7f203 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -1342,7 +1342,8 @@ static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata, bw = min(bw, ieee80211_sta_cap_rx_bw(&sta->deflink)); if (bw != sta->sta.deflink.bandwidth) { sta->sta.deflink.bandwidth = bw; - rate_control_rate_update(local, sband, sta, 0, + rate_control_rate_update(local, sband, + &sta->deflink, IEEE80211_RC_BW_CHANGED); /* * if a TDLS peer BW was updated, we need to diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 880a1fa8705a..94c00e71f6f8 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -313,7 +313,7 @@ int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx, * Record previously received IV, will be copied into the * key information after MIC verification. It is possible * that we don't catch replays of fragments but that's ok - * because the Michael MIC verication will then fail. + * because the Michael MIC verification will then fail. */ *out_iv32 = iv32; *out_iv16 = iv16; diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index dc498cd8cd91..7a4985fc2b16 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -939,31 +939,34 @@ TRACE_EVENT(drv_sta_set_txpwr, ) ); -TRACE_EVENT(drv_sta_rc_update, +TRACE_EVENT(drv_link_sta_rc_update, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta *sta, + struct ieee80211_link_sta *link_sta, u32 changed), - TP_ARGS(local, sdata, sta, changed), + TP_ARGS(local, sdata, link_sta, changed), TP_STRUCT__entry( LOCAL_ENTRY VIF_ENTRY STA_ENTRY __field(u32, changed) + __field(u32, link_id) ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - STA_ASSIGN; + STA_NAMED_ASSIGN(link_sta->sta); __entry->changed = changed; + __entry->link_id = link_sta->link_id; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " changed: 0x%x", - LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->changed + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " (link %d) changed: 0x%x", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->link_id, + __entry->changed ) ); @@ -3154,6 +3157,25 @@ TRACE_EVENT(drv_neg_ttlm_res, LOCAL_PR_ARG, VIF_PR_ARG, __entry->res ) ); + +TRACE_EVENT(drv_prep_add_interface, + TP_PROTO(struct ieee80211_local *local, + enum nl80211_iftype type), + + TP_ARGS(local, type), + TP_STRUCT__entry(LOCAL_ENTRY + __field(u32, type) + ), + + TP_fast_assign(LOCAL_ASSIGN; + __entry->type = type; + ), + + TP_printk(LOCAL_PR_FMT " type: %u\n ", + LOCAL_PR_ARG, __entry->type + ) +); + #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0ff8b56f5807..a24636bda679 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1763,7 +1763,8 @@ static bool __ieee80211_tx(struct ieee80211_local *local, switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: - if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { + if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { vif = &sdata->vif; break; } @@ -3952,7 +3953,8 @@ begin: switch (tx.sdata->vif.type) { case NL80211_IFTYPE_MONITOR: - if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) { + if ((tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) || + ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) { vif = &tx.sdata->vif; break; } @@ -6214,7 +6216,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, goto start_xmit; /* update QoS header to prioritize control port frames if possible, - * priorization also happens for control port frames send over + * prioritization also happens for control port frames send over * AF_PACKET */ rcu_read_lock(); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f94faa86ba8a..a4e1301cc999 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -756,7 +756,8 @@ static void __iterate_interfaces(struct ieee80211_local *local, lockdep_is_held(&local->hw.wiphy->mtx)) { switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: - if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) + if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) continue; break; case NL80211_IFTYPE_AP_VLAN: @@ -1010,7 +1011,7 @@ void ieee80211_set_wmm_default(struct ieee80211_link_data *link, else aCWmin = 15; - /* Confiure old 802.11b/g medium access rules. */ + /* Configure old 802.11b/g medium access rules. */ qparam.cw_max = aCWmax; qparam.cw_min = aCWmin; qparam.txop = 0; @@ -1873,8 +1874,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) } list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + continue; if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_MONITOR && ieee80211_sdata_running(sdata)) { res = drv_add_interface(local, sdata); if (WARN_ON(res)) @@ -1887,11 +1890,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) */ if (res) { list_for_each_entry_continue_reverse(sdata, &local->interfaces, - list) + list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) + continue; if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_MONITOR && ieee80211_sdata_running(sdata)) drv_remove_interface(local, sdata); + } ieee80211_handle_reconfig_failure(local); return res; } @@ -2752,7 +2758,7 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, return pos + sizeof(struct ieee80211_vht_operation); } -u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef) +u8 *ieee80211_ie_build_he_oper(u8 *pos, const struct cfg80211_chan_def *chandef) { struct ieee80211_he_operation *he_oper; struct ieee80211_he_6ghz_oper *he_6ghz_op; @@ -2844,7 +2850,7 @@ out: return pos; } -u8 *ieee80211_ie_build_eht_oper(u8 *pos, struct cfg80211_chan_def *chandef, +u8 *ieee80211_ie_build_eht_oper(u8 *pos, const struct cfg80211_chan_def *chandef, const struct ieee80211_sta_eht_cap *eht_cap) { diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index bf6ef45af757..6a20fa099190 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -280,10 +280,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, /* * This is a workaround for VHT-enabled STAs which break the spec * and have the VHT-MCS Rx map filled in with value 3 for all eight - * spacial streams, an example is AR9462. + * spatial streams, an example is AR9462. * * As per spec, in section 22.1.1 Introduction to the VHT PHY - * A VHT STA shall support at least single spactial stream VHT-MCSs + * A VHT STA shall support at least single spatial stream VHT-MCSs * 0 to 7 (transmit and receive) in all supported channel widths. */ if (vht_cap->vht_mcs.rx_mcs_map == cpu_to_le16(0xFFFF)) { @@ -479,28 +479,6 @@ ieee80211_sta_rx_bw_to_chan_width(struct link_sta_info *link_sta) } } -enum ieee80211_sta_rx_bandwidth -ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) -{ - switch (width) { - case NL80211_CHAN_WIDTH_20_NOHT: - case NL80211_CHAN_WIDTH_20: - return IEEE80211_STA_RX_BW_20; - case NL80211_CHAN_WIDTH_40: - return IEEE80211_STA_RX_BW_40; - case NL80211_CHAN_WIDTH_80: - return IEEE80211_STA_RX_BW_80; - case NL80211_CHAN_WIDTH_160: - case NL80211_CHAN_WIDTH_80P80: - return IEEE80211_STA_RX_BW_160; - case NL80211_CHAN_WIDTH_320: - return IEEE80211_STA_RX_BW_320; - default: - WARN_ON_ONCE(1); - return IEEE80211_STA_RX_BW_20; - } -} - /* FIXME: rename/move - this deals with everything not just VHT */ enum ieee80211_sta_rx_bandwidth _ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta, @@ -766,8 +744,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, if (changed > 0) { ieee80211_recalc_min_chandef(sdata, link_sta->link_id); - rate_control_rate_update(local, sband, link_sta->sta, - link_sta->link_id, changed); + rate_control_rate_update(local, sband, link_sta, changed); } } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 293afa3f57c5..40d5d9e48479 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -598,9 +598,6 @@ static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad, memcpy(j_0, hdr->addr2, ETH_ALEN); memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN); - j_0[13] = 0; - j_0[14] = 0; - j_0[AES_BLOCK_SIZE - 1] = 0x01; ccmp_gcmp_aad(skb, aad, spp_amsdu); } diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 10345388ad13..2d67b5f2010e 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -11,9 +11,6 @@ config WEXT_PROC depends on PROC_FS depends on WEXT_CORE -config WEXT_SPY - bool - config WEXT_PRIV bool @@ -188,19 +185,12 @@ config CFG80211_CRDA_SUPPORT If unsure, say Y. config CFG80211_WEXT - bool "cfg80211 wireless extensions compatibility" if !CFG80211_WEXT_EXPORT + bool "cfg80211 wireless extensions compatibility" select WEXT_CORE - default y if CFG80211_WEXT_EXPORT help Enable this option if you need old userspace for wireless extensions with cfg80211-based drivers. -config CFG80211_WEXT_EXPORT - bool - help - Drivers should select this option if they require cfg80211's - wext compatibility symbols to be exported. - config CFG80211_KUNIT_TEST tristate "KUnit tests for cfg80211" if !KUNIT_ALL_TESTS depends on KUNIT @@ -212,36 +202,3 @@ config CFG80211_KUNIT_TEST If unsure, say N. endif # CFG80211 - -config LIB80211 - tristate - default n - help - This options enables a library of common routines used - by IEEE802.11 wireless LAN drivers. - - Drivers should select this themselves if needed. - -config LIB80211_CRYPT_WEP - tristate - select CRYPTO_LIB_ARC4 - -config LIB80211_CRYPT_CCMP - tristate - select CRYPTO - select CRYPTO_AES - select CRYPTO_CCM - -config LIB80211_CRYPT_TKIP - tristate - select CRYPTO_LIB_ARC4 - -config LIB80211_DEBUG - bool "lib80211 debugging messages" - depends on LIB80211 - default n - help - You can enable this if you want verbose debugging messages - from lib80211. - - If unsure, say N. diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 1d49cc8b6da1..62a83faf0e07 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -1,14 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CFG80211) += cfg80211.o -obj-$(CONFIG_LIB80211) += lib80211.o -obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o -obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o -obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o obj-y += tests/ obj-$(CONFIG_WEXT_CORE) += wext-core.o obj-$(CONFIG_WEXT_PROC) += wext-proc.o -obj-$(CONFIG_WEXT_SPY) += wext-spy.o obj-$(CONFIG_WEXT_PRIV) += wext-priv.o cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o diff --git a/net/wireless/chan.c b/net/wireless/chan.c index e579d7e1425f..40b6375a5de4 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -289,7 +289,7 @@ static bool cfg80211_valid_center_freq(u32 center, /* * Valid channels are packed from lowest frequency towards higher ones. - * So test that the lower frequency alignes with one of these steps. + * So test that the lower frequency aligns with one of these steps. */ return (center - bw / 2 - 5945) % step == 0; } @@ -1628,6 +1628,7 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy, EXPORT_SYMBOL(cfg80211_reg_check_beaconing); int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, + struct net_device *dev, struct cfg80211_chan_def *chandef) { if (!rdev->ops->set_monitor_channel) @@ -1635,7 +1636,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, if (!cfg80211_has_monitors_only(rdev)) return -EBUSY; - return rdev_set_monitor_channel(rdev, chandef); + return rdev_set_monitor_channel(rdev, dev, chandef); } bool cfg80211_any_usable_channels(struct wiphy *wiphy, diff --git a/net/wireless/core.c b/net/wireless/core.c index 661adfc77644..93d62a1d3a45 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -603,16 +603,20 @@ use_default_name: } EXPORT_SYMBOL(wiphy_new_nm); -static int wiphy_verify_combinations(struct wiphy *wiphy) +static +int wiphy_verify_iface_combinations(struct wiphy *wiphy, + const struct ieee80211_iface_combination *iface_comb, + int n_iface_comb, + bool combined_radio) { const struct ieee80211_iface_combination *c; int i, j; - for (i = 0; i < wiphy->n_iface_combinations; i++) { + for (i = 0; i < n_iface_comb; i++) { u32 cnt = 0; u16 all_iftypes = 0; - c = &wiphy->iface_combinations[i]; + c = &iface_comb[i]; /* * Combinations with just one interface aren't real, @@ -625,9 +629,13 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) if (WARN_ON(!c->num_different_channels)) return -EINVAL; - /* DFS only works on one channel. */ - if (WARN_ON(c->radar_detect_widths && - (c->num_different_channels > 1))) + /* DFS only works on one channel. Avoid this check + * for multi-radio global combination, since it hold + * the capabilities of all radio combinations. + */ + if (!combined_radio && + WARN_ON(c->radar_detect_widths && + c->num_different_channels > 1)) return -EINVAL; if (WARN_ON(!c->n_limits)) @@ -648,13 +656,21 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) if (WARN_ON(wiphy->software_iftypes & types)) return -EINVAL; - /* Only a single P2P_DEVICE can be allowed */ - if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && + /* Only a single P2P_DEVICE can be allowed, avoid this + * check for multi-radio global combination, since it + * hold the capabilities of all radio combinations. + */ + if (!combined_radio && + WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && c->limits[j].max > 1)) return -EINVAL; - /* Only a single NAN can be allowed */ - if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && + /* Only a single NAN can be allowed, avoid this + * check for multi-radio global combination, since it + * hold the capabilities of all radio combinations. + */ + if (!combined_radio && + WARN_ON(types & BIT(NL80211_IFTYPE_NAN) && c->limits[j].max > 1)) return -EINVAL; @@ -693,6 +709,34 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) return 0; } +static int wiphy_verify_combinations(struct wiphy *wiphy) +{ + int i, ret; + bool combined_radio = false; + + if (wiphy->n_radio) { + for (i = 0; i < wiphy->n_radio; i++) { + const struct wiphy_radio *radio = &wiphy->radio[i]; + + ret = wiphy_verify_iface_combinations(wiphy, + radio->iface_combinations, + radio->n_iface_combinations, + false); + if (ret) + return ret; + } + + combined_radio = true; + } + + ret = wiphy_verify_iface_combinations(wiphy, + wiphy->iface_combinations, + wiphy->n_iface_combinations, + combined_radio); + + return ret; +} + int wiphy_register(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); @@ -1386,6 +1430,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) /* allow mac80211 to determine the timeout */ wdev->ps_timeout = -1; + wdev->radio_mask = BIT(wdev->wiphy->n_radio) - 1; + if ((wdev->iftype == NL80211_IFTYPE_STATION || wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) diff --git a/net/wireless/core.h b/net/wireless/core.h index 3b3e3cd7027a..4c45f994a8c0 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -516,6 +516,7 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start) } int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, + struct net_device *dev, struct cfg80211_chan_def *chandef); int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, diff --git a/net/wireless/lib80211.c b/net/wireless/lib80211.c deleted file mode 100644 index 64c447040786..000000000000 --- a/net/wireless/lib80211.c +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * lib80211 -- common bits for IEEE802.11 drivers - * - * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com> - * - * Portions copied from old ieee80211 component, w/ original copyright - * notices below: - * - * Host AP crypto routines - * - * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi> - * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com> - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/ctype.h> -#include <linux/ieee80211.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> - -#include <net/lib80211.h> - -#define DRV_DESCRIPTION "common routines for IEEE802.11 drivers" - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR("John W. Linville <linville@tuxdriver.com>"); -MODULE_LICENSE("GPL"); - -struct lib80211_crypto_alg { - struct list_head list; - const struct lib80211_crypto_ops *ops; -}; - -static LIST_HEAD(lib80211_crypto_algs); -static DEFINE_SPINLOCK(lib80211_crypto_lock); - -static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, - int force); -static void lib80211_crypt_quiescing(struct lib80211_crypt_info *info); -static void lib80211_crypt_deinit_handler(struct timer_list *t); - -int lib80211_crypt_info_init(struct lib80211_crypt_info *info, char *name, - spinlock_t *lock) -{ - memset(info, 0, sizeof(*info)); - - info->name = name; - info->lock = lock; - - INIT_LIST_HEAD(&info->crypt_deinit_list); - timer_setup(&info->crypt_deinit_timer, lib80211_crypt_deinit_handler, - 0); - - return 0; -} -EXPORT_SYMBOL(lib80211_crypt_info_init); - -void lib80211_crypt_info_free(struct lib80211_crypt_info *info) -{ - int i; - - lib80211_crypt_quiescing(info); - del_timer_sync(&info->crypt_deinit_timer); - lib80211_crypt_deinit_entries(info, 1); - - for (i = 0; i < NUM_WEP_KEYS; i++) { - struct lib80211_crypt_data *crypt = info->crypt[i]; - if (crypt) { - if (crypt->ops) { - crypt->ops->deinit(crypt->priv); - module_put(crypt->ops->owner); - } - kfree(crypt); - info->crypt[i] = NULL; - } - } -} -EXPORT_SYMBOL(lib80211_crypt_info_free); - -static void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *info, - int force) -{ - struct lib80211_crypt_data *entry, *next; - unsigned long flags; - - spin_lock_irqsave(info->lock, flags); - list_for_each_entry_safe(entry, next, &info->crypt_deinit_list, list) { - if (atomic_read(&entry->refcnt) != 0 && !force) - continue; - - list_del(&entry->list); - - if (entry->ops) { - entry->ops->deinit(entry->priv); - module_put(entry->ops->owner); - } - kfree(entry); - } - spin_unlock_irqrestore(info->lock, flags); -} - -/* After this, crypt_deinit_list won't accept new members */ -static void lib80211_crypt_quiescing(struct lib80211_crypt_info *info) -{ - unsigned long flags; - - spin_lock_irqsave(info->lock, flags); - info->crypt_quiesced = 1; - spin_unlock_irqrestore(info->lock, flags); -} - -static void lib80211_crypt_deinit_handler(struct timer_list *t) -{ - struct lib80211_crypt_info *info = from_timer(info, t, - crypt_deinit_timer); - unsigned long flags; - - lib80211_crypt_deinit_entries(info, 0); - - spin_lock_irqsave(info->lock, flags); - if (!list_empty(&info->crypt_deinit_list) && !info->crypt_quiesced) { - printk(KERN_DEBUG "%s: entries remaining in delayed crypt " - "deletion list\n", info->name); - info->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&info->crypt_deinit_timer); - } - spin_unlock_irqrestore(info->lock, flags); -} - -void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info, - struct lib80211_crypt_data **crypt) -{ - struct lib80211_crypt_data *tmp; - unsigned long flags; - - if (*crypt == NULL) - return; - - tmp = *crypt; - *crypt = NULL; - - /* must not run ops->deinit() while there may be pending encrypt or - * decrypt operations. Use a list of delayed deinits to avoid needing - * locking. */ - - spin_lock_irqsave(info->lock, flags); - if (!info->crypt_quiesced) { - list_add(&tmp->list, &info->crypt_deinit_list); - if (!timer_pending(&info->crypt_deinit_timer)) { - info->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&info->crypt_deinit_timer); - } - } - spin_unlock_irqrestore(info->lock, flags); -} -EXPORT_SYMBOL(lib80211_crypt_delayed_deinit); - -int lib80211_register_crypto_ops(const struct lib80211_crypto_ops *ops) -{ - unsigned long flags; - struct lib80211_crypto_alg *alg; - - alg = kzalloc(sizeof(*alg), GFP_KERNEL); - if (alg == NULL) - return -ENOMEM; - - alg->ops = ops; - - spin_lock_irqsave(&lib80211_crypto_lock, flags); - list_add(&alg->list, &lib80211_crypto_algs); - spin_unlock_irqrestore(&lib80211_crypto_lock, flags); - - printk(KERN_DEBUG "lib80211_crypt: registered algorithm '%s'\n", - ops->name); - - return 0; -} -EXPORT_SYMBOL(lib80211_register_crypto_ops); - -int lib80211_unregister_crypto_ops(const struct lib80211_crypto_ops *ops) -{ - struct lib80211_crypto_alg *alg; - unsigned long flags; - - spin_lock_irqsave(&lib80211_crypto_lock, flags); - list_for_each_entry(alg, &lib80211_crypto_algs, list) { - if (alg->ops == ops) - goto found; - } - spin_unlock_irqrestore(&lib80211_crypto_lock, flags); - return -EINVAL; - - found: - printk(KERN_DEBUG "lib80211_crypt: unregistered algorithm '%s'\n", - ops->name); - list_del(&alg->list); - spin_unlock_irqrestore(&lib80211_crypto_lock, flags); - kfree(alg); - return 0; -} -EXPORT_SYMBOL(lib80211_unregister_crypto_ops); - -const struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name) -{ - struct lib80211_crypto_alg *alg; - unsigned long flags; - - spin_lock_irqsave(&lib80211_crypto_lock, flags); - list_for_each_entry(alg, &lib80211_crypto_algs, list) { - if (strcmp(alg->ops->name, name) == 0) - goto found; - } - spin_unlock_irqrestore(&lib80211_crypto_lock, flags); - return NULL; - - found: - spin_unlock_irqrestore(&lib80211_crypto_lock, flags); - return alg->ops; -} -EXPORT_SYMBOL(lib80211_get_crypto_ops); - -static void *lib80211_crypt_null_init(int keyidx) -{ - return (void *)1; -} - -static void lib80211_crypt_null_deinit(void *priv) -{ -} - -static const struct lib80211_crypto_ops lib80211_crypt_null = { - .name = "NULL", - .init = lib80211_crypt_null_init, - .deinit = lib80211_crypt_null_deinit, - .owner = THIS_MODULE, -}; - -static int __init lib80211_init(void) -{ - pr_info(DRV_DESCRIPTION "\n"); - return lib80211_register_crypto_ops(&lib80211_crypt_null); -} - -static void __exit lib80211_exit(void) -{ - lib80211_unregister_crypto_ops(&lib80211_crypt_null); - BUG_ON(!list_empty(&lib80211_crypto_algs)); -} - -module_init(lib80211_init); -module_exit(lib80211_exit); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d7d099f7118a..1ac8a196f376 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -829,6 +829,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MLO_TTLM_DLINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8), [NL80211_ATTR_MLO_TTLM_ULINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8), [NL80211_ATTR_ASSOC_SPP_AMSDU] = { .type = NLA_FLAG }, + [NL80211_ATTR_VIF_RADIO_MASK] = { .type = NLA_U32 }, }; /* policy for the key attributes */ @@ -2430,6 +2431,11 @@ static int nl80211_put_radio(struct wiphy *wiphy, struct sk_buff *msg, int idx) if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx)) goto nla_put_failure; + if (r->antenna_mask && + nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK, + r->antenna_mask)) + goto nla_put_failure; + for (i = 0; i < r->n_freq_range; i++) { const struct wiphy_radio_freq_range *range = &r->freq_range[i]; @@ -3561,7 +3567,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_MESH_POINT: return cfg80211_set_mesh_channel(rdev, wdev, &chandef); case NL80211_IFTYPE_MONITOR: - return cfg80211_set_monitor_channel(rdev, &chandef); + return cfg80211_set_monitor_channel(rdev, dev, &chandef); default: break; } @@ -3996,7 +4002,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->devlist_generation ^ (cfg80211_rdev_list_generation << 2)) || - nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr)) + nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr) || + nla_put_u32(msg, NL80211_ATTR_VIF_RADIO_MASK, wdev->radio_mask)) goto nla_put_failure; if (rdev->ops->get_channel && !wdev->valid_links) { @@ -4199,6 +4206,7 @@ static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = { [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG }, [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG }, [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG }, + [NL80211_MNTR_FLAG_SKIP_TX] = { .type = NLA_FLAG }, }; static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) @@ -4312,6 +4320,29 @@ static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev, return -EOPNOTSUPP; } +static int nl80211_parse_vif_radio_mask(struct genl_info *info, + u32 *radio_mask) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct nlattr *attr = info->attrs[NL80211_ATTR_VIF_RADIO_MASK]; + u32 mask, allowed; + + if (!attr) { + *radio_mask = 0; + return 0; + } + + allowed = BIT(rdev->wiphy.n_radio) - 1; + mask = nla_get_u32(attr); + if (mask & ~allowed) + return -EINVAL; + if (!mask) + mask = allowed; + *radio_mask = mask; + + return 1; +} + static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -4319,6 +4350,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) int err; enum nl80211_iftype otype, ntype; struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + u32 radio_mask = 0; bool change = false; memset(¶ms, 0, sizeof(params)); @@ -4332,8 +4365,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[NL80211_ATTR_MESH_ID]) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - if (ntype != NL80211_IFTYPE_MESH_POINT) return -EINVAL; if (otype != NL80211_IFTYPE_MESH_POINT) @@ -4364,6 +4395,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (err > 0) change = true; + err = nl80211_parse_vif_radio_mask(info, &radio_mask); + if (err < 0) + return err; + if (err && netif_running(dev)) + return -EBUSY; + if (change) err = cfg80211_change_iface(rdev, dev, ntype, ¶ms); else @@ -4372,11 +4409,11 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) if (!err && params.use_4addr != -1) dev->ieee80211_ptr->use_4addr = params.use_4addr; - if (change && !err) { - struct wireless_dev *wdev = dev->ieee80211_ptr; + if (radio_mask) + wdev->radio_mask = radio_mask; + if (change && !err) nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE); - } return err; } @@ -4387,6 +4424,7 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) struct vif_params params; struct wireless_dev *wdev; struct sk_buff *msg; + u32 radio_mask; int err; enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; @@ -4424,6 +4462,10 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) if (err < 0) return err; + err = nl80211_parse_vif_radio_mask(info, &radio_mask); + if (err < 0) + return err; + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -4465,6 +4507,9 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) break; } + if (radio_mask) + wdev->radio_mask = radio_mask; + if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0, rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) { nlmsg_free(msg); @@ -6227,33 +6272,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) goto out; } - if (info->attrs[NL80211_ATTR_SMPS_MODE]) { - params->smps_mode = - nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]); - switch (params->smps_mode) { - case NL80211_SMPS_OFF: - break; - case NL80211_SMPS_STATIC: - if (!(rdev->wiphy.features & - NL80211_FEATURE_STATIC_SMPS)) { - err = -EINVAL; - goto out; - } - break; - case NL80211_SMPS_DYNAMIC: - if (!(rdev->wiphy.features & - NL80211_FEATURE_DYNAMIC_SMPS)) { - err = -EINVAL; - goto out; - } - break; - default: - err = -EINVAL; - goto out; - } - } else { - params->smps_mode = NL80211_SMPS_OFF; - } + if (info->attrs[NL80211_ATTR_SMPS_MODE] && + nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]) != NL80211_SMPS_OFF) + return -EOPNOTSUPP; params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]); if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) { @@ -9180,6 +9201,9 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, lockdep_assert_wiphy(wdev->wiphy); + if (!cfg80211_wdev_channel_allowed(wdev, chan)) + return false; + if (!cfg80211_beaconing_iface_active(wdev)) return true; @@ -9392,7 +9416,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) } /* ignore disabled channels */ - if (chan->flags & IEEE80211_CHAN_DISABLED) + if (chan->flags & IEEE80211_CHAN_DISABLED || + !cfg80211_wdev_channel_allowed(wdev, chan)) continue; request->channels[i] = chan; @@ -9412,7 +9437,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) chan = &wiphy->bands[band]->channels[j]; - if (chan->flags & IEEE80211_CHAN_DISABLED) + if (chan->flags & IEEE80211_CHAN_DISABLED || + !cfg80211_wdev_channel_allowed(wdev, chan)) continue; request->channels[i] = chan; @@ -12446,7 +12472,7 @@ static int nl80211_del_pmksa(struct sk_buff *skb, struct genl_info *info) if (info->attrs[NL80211_ATTR_MAC]) { pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); } else if (info->attrs[NL80211_ATTR_SSID]) { - /* SSID based pmksa flush suppported only for FILS, + /* SSID based pmksa flush supported only for FILS, * OWE/SAE OFFLOAD cases */ if (info->attrs[NL80211_ATTR_FILS_CACHE_ID] && @@ -14061,8 +14087,6 @@ void cfg80211_free_coalesce(struct cfg80211_coalesce *coalesce) for (i = 0; i < coalesce->n_rules; i++) { rule = &coalesce->rules[i]; - if (!rule) - continue; for (j = 0; j < rule->n_patterns; j++) kfree(rule->patterns[j].mask); kfree(rule->patterns); @@ -15498,7 +15522,7 @@ static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info) if (tsid >= IEEE80211_FIRST_TSPEC_TSID) { /* TODO: handle 802.11 TSPEC/admission control * need more attributes for that (e.g. BA session requirement); - * change the WMM adminssion test above to allow both then + * change the WMM admission test above to allow both then */ return -EINVAL; } diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index b7e3e46ec16d..326faea38ca3 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -200,7 +200,7 @@ static void find_ns(struct ieee80211_radiotap_iterator *iterator, * present fields. @this_arg can be changed by the caller (eg, * incremented to move inside a compound argument like * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in - * little-endian format whatever the endianess of your CPU. + * little-endian format whatever the endianness of your CPU. * * Alignment Gotcha: * You must take care when dereferencing iterator.this_arg diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index f5adbf6b5c84..adb6105bbb7d 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -445,11 +445,12 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev, static inline int rdev_set_monitor_channel(struct cfg80211_registered_device *rdev, + struct net_device *dev, struct cfg80211_chan_def *chandef) { int ret; - trace_rdev_set_monitor_channel(&rdev->wiphy, chandef); - ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef); + trace_rdev_set_monitor_channel(&rdev->wiphy, dev, chandef); + ret = rdev->ops->set_monitor_channel(&rdev->wiphy, dev, chandef); trace_rdev_return_int(&rdev->wiphy, ret); return ret; } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6489ba943a63..1df65a5a44f7 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1147,7 +1147,7 @@ static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy) /* * Follow the driver's regulatory domain, if present, unless a country - * IE has been processed or a user wants to help complaince further + * IE has been processed or a user wants to help compliance further */ if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && lr->initiator != NL80211_REGDOM_SET_BY_USER && diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 59a90bf3c0d6..8e3d46bf4836 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -956,7 +956,8 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) struct ieee80211_channel *chan = ieee80211_get_channel(&rdev->wiphy, ap->center_freq); - if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) + if (!chan || chan->flags & IEEE80211_CHAN_DISABLED || + !cfg80211_wdev_channel_allowed(rdev_req->wdev, chan)) continue; for (i = 0; i < rdev_req->n_channels; i++) { @@ -3515,9 +3516,12 @@ int cfg80211_wext_siwscan(struct net_device *dev, continue; for (j = 0; j < wiphy->bands[band]->n_channels; j++) { + struct ieee80211_channel *chan; + /* ignore disabled channels */ - if (wiphy->bands[band]->channels[j].flags & - IEEE80211_CHAN_DISABLED) + chan = &wiphy->bands[band]->channels[j]; + if (chan->flags & IEEE80211_CHAN_DISABLED || + !cfg80211_wdev_channel_allowed(creq->wdev, chan)) continue; /* If we have a wireless request structure and the @@ -3594,7 +3598,6 @@ int cfg80211_wext_siwscan(struct net_device *dev, kfree(creq); return err; } -EXPORT_WEXT_HANDLER(cfg80211_wext_siwscan); static char *ieee80211_scan_add_ies(struct iw_request_info *info, const struct cfg80211_bss_ies *ies, @@ -3966,5 +3969,4 @@ int cfg80211_wext_giwscan(struct net_device *dev, return res; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwscan); #endif diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 97c21b627791..d5c9bb614fa6 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1318,19 +1318,21 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel, ); TRACE_EVENT(rdev_set_monitor_channel, - TP_PROTO(struct wiphy *wiphy, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, struct cfg80211_chan_def *chandef), - TP_ARGS(wiphy, chandef), + TP_ARGS(wiphy, netdev, chandef), TP_STRUCT__entry( WIPHY_ENTRY + NETDEV_ENTRY CHAN_DEF_ENTRY ), TP_fast_assign( WIPHY_ASSIGN; + NETDEV_ASSIGN; CHAN_DEF_ASSIGN(chandef); ), - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, - WIPHY_PR_ARG, CHAN_DEF_PR_ARG) + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT, + WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG) ); TRACE_EVENT(rdev_auth, diff --git a/net/wireless/util.c b/net/wireless/util.c index f49b55724f83..040d62051eb9 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -743,7 +743,7 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen, return NULL; /* - * When reusing framents, copy some data to the head to simplify + * When reusing fragments, copy some data to the head to simplify * ethernet header handling and speed up protocol header processing * in the stack later. */ @@ -2923,3 +2923,32 @@ bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio, return true; } EXPORT_SYMBOL(cfg80211_radio_chandef_valid); + +bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev, + struct ieee80211_channel *chan) +{ + struct wiphy *wiphy = wdev->wiphy; + const struct wiphy_radio *radio; + struct cfg80211_chan_def chandef; + u32 radio_mask; + int i; + + radio_mask = wdev->radio_mask; + if (!wiphy->n_radio || radio_mask == BIT(wiphy->n_radio) - 1) + return true; + + cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20); + for (i = 0; i < wiphy->n_radio; i++) { + if (!(radio_mask & BIT(i))) + continue; + + radio = &wiphy->radio[i]; + if (!cfg80211_radio_chandef_valid(radio, &chandef)) + continue; + + return true; + } + + return false; +} +EXPORT_SYMBOL(cfg80211_wdev_channel_allowed); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 2371069f3c43..90d5c0592667 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -30,7 +30,6 @@ int cfg80211_wext_giwname(struct net_device *dev, strcpy(wrqu->name, "IEEE 802.11"); return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwname); int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -69,7 +68,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, return ret; } -EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -105,7 +103,6 @@ int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, } return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwmode); int cfg80211_wext_giwrange(struct net_device *dev, @@ -220,7 +217,6 @@ int cfg80211_wext_giwrange(struct net_device *dev, return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwrange); /** @@ -281,7 +277,6 @@ out: wiphy_unlock(&rdev->wiphy); return err; } -EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts); int cfg80211_wext_giwrts(struct net_device *dev, struct iw_request_info *info, @@ -296,7 +291,6 @@ int cfg80211_wext_giwrts(struct net_device *dev, return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwrts); int cfg80211_wext_siwfrag(struct net_device *dev, struct iw_request_info *info, @@ -327,7 +321,6 @@ out: return err; } -EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag); int cfg80211_wext_giwfrag(struct net_device *dev, struct iw_request_info *info, @@ -342,7 +335,6 @@ int cfg80211_wext_giwfrag(struct net_device *dev, return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwfrag); static int cfg80211_wext_siwretry(struct net_device *dev, struct iw_request_info *info, @@ -413,7 +405,6 @@ int cfg80211_wext_giwretry(struct net_device *dev, return 0; } -EXPORT_WEXT_HANDLER(cfg80211_wext_giwretry); static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, struct net_device *dev, bool pairwise, @@ -830,7 +821,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, ret = -EINVAL; break; } - ret = cfg80211_set_monitor_channel(rdev, &chandef); + ret = cfg80211_set_monitor_channel(rdev, dev, &chandef); break; case NL80211_IFTYPE_MESH_POINT: freq = cfg80211_wext_freq(wextfreq); @@ -1204,7 +1195,7 @@ static int cfg80211_wext_siwpower(struct net_device *dev, switch (wrq->flags & IW_POWER_MODE) { case IW_POWER_ON: /* If not specified */ case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitely state all */ + case IW_POWER_ALL_R: /* If explicitly state all */ ps = true; break; default: /* Otherwise we ignore */ diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index c02eb789e676..8251ca5df8ae 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h @@ -5,12 +5,6 @@ #include <net/iw_handler.h> #include <linux/wireless.h> -#ifdef CONFIG_CFG80211_WEXT_EXPORT -#define EXPORT_WEXT_HANDLER(h) EXPORT_SYMBOL_GPL(h) -#else -#define EXPORT_WEXT_HANDLER(h) -#endif /* CONFIG_CFG80211_WEXT_EXPORT */ - int cfg80211_ibss_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *wextfreq, char *extra); diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 838ad6541a17..3bb04b05c5ce 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -1159,7 +1159,7 @@ char *iwe_stream_add_event(struct iw_request_info *info, char *stream, /* Check if it's possible */ if (likely((stream + event_len) < ends)) { iwe->len = event_len; - /* Beware of alignement issues on 64 bits */ + /* Beware of alignment issues on 64 bits */ memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); memcpy(stream + lcp_len, &iwe->u, event_len - lcp_len); |