wireless-next patches for v5.19
Second set of patches for v5.19 and most likely the last one. rtw89 got support for 8852ce devices and mt76 now supports Wireless Ethernet Dispatch. Major changes: cfg80211/mac80211 * support disabling EHT mode rtw89 * add support for Realtek 8852ce devices mt76 * Wireless Ethernet Dispatch support for flow offload * non-standard VHT MCS10-11 support * mt7921 AP mode support * mt7921 ipv6 NS offload support ath11k * enable keepalive during WoWLAN suspend * implement remain-on-channel support -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmKGYt4RHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZuK2gf/ZswLtwE2CIwrEhz/Q0MDtxUvw8ulRhKl d+1PC+bCd/VArMESjpu7le+WNAZ1OPBWdh1pgkDm8QpCQZYe7/hRED82DB/Jw3Cl KmOx2nr6Xb4uEN+yjqZrSXzA+Hrysy24bCQRG2CJKjdToe/fwTuRiz8WIcPKtxio b/d/Kz0LpSoHTlU1PzqIsXulN8QUKJA4kRw70rJHAlMJVYiTBuAD+AmXfbhHD8uX t2CJDH2fykDd1CAWFQwcmI++2tS+xclYL81vDg3aEinQJ9aNcDz06qSE5qr2H+K5 lUYy42yc+ONkIIh8LlxrLgZie7oSmkrb7aA0Zc+F0SWp/B6ZO/k8FA== =aILH -----END PGP SIGNATURE----- Merge tag 'wireless-next-2022-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next Kalle Valo says: ==================== wireless-next patches for v5.19 Second set of patches for v5.19 and most likely the last one. rtw89 got support for 8852ce devices and mt76 now supports Wireless Ethernet Dispatch. Major changes: cfg80211/mac80211 - support disabling EHT mode rtw89 - add support for Realtek 8852ce devices mt76 - Wireless Ethernet Dispatch support for flow offload - non-standard VHT MCS10-11 support - mt7921 AP mode support - mt7921 ipv6 NS offload support ath11k - enable keepalive during WoWLAN suspend - implement remain-on-channel support * tag 'wireless-next-2022-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (135 commits) iwlwifi: mei: fix potential NULL-ptr deref iwlwifi: mei: clear the sap data header before sending iwlwifi: mvm: remove vif_count iwlwifi: mvm: always tell the firmware to accept MCAST frames in BSS iwlwifi: mvm: add OTP info in case of init failure iwlwifi: mvm: fix assert 1F04 upon reconfig iwlwifi: fw: init SAR GEO table only if data is present iwlwifi: mvm: clean up authorized condition iwlwifi: mvm: use NULL instead of ERR_PTR when parsing wowlan status iwlwifi: pcie: simplify MSI-X cause mapping rtw89: pci: only mask out INT indicator register for disable interrupt v1 rtw89: convert rtw89_band to nl80211_band precisely rtw89: 8852c: update txpwr tables to HALRF_027_00_052 rtw89: cfo: check mac_id to avoid out-of-bounds rtw89: 8852c: set TX antenna path rtw89: add ieee80211::sta_rc_update ops wireless: Fix Makefile to be in alphabetical order mac80211: refactor freeing the next_beacon cfg80211: fix kernel-doc for cfg80211_beacon_data mac80211: minstrel_ht: support ieee80211_rate_status ... ==================== Link: https://lore.kernel.org/r/20220519153334.8D051C385AA@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d353e1a3ba
|
@ -11,6 +11,8 @@
|
|||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
@ -182,9 +184,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
|||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->parent = bus->dev;
|
||||
#if IS_BUILTIN(CONFIG_OF)
|
||||
chip->of_node = cc->core->dev.of_node;
|
||||
#endif
|
||||
chip->fwnode = dev_fwnode(&cc->core->dev);
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM4707:
|
||||
case BCMA_CHIP_ID_BCM5357:
|
||||
|
|
|
@ -14,6 +14,7 @@ obj-$(CONFIG_WLAN_VENDOR_MARVELL) += marvell/
|
|||
obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) += mediatek/
|
||||
obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) += microchip/
|
||||
obj-$(CONFIG_WLAN_VENDOR_PURELIFI) += purelifi/
|
||||
obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
|
||||
obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
|
||||
obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
|
||||
obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
|
||||
|
@ -21,7 +22,6 @@ obj-$(CONFIG_WLAN_VENDOR_SILABS) += silabs/
|
|||
obj-$(CONFIG_WLAN_VENDOR_ST) += st/
|
||||
obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
|
||||
obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
|
||||
obj-$(CONFIG_WLAN_VENDOR_QUANTENNA) += quantenna/
|
||||
|
||||
# 16-bit wireless PCMCIA client drivers
|
||||
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
|
||||
|
|
|
@ -1233,6 +1233,7 @@ success:
|
|||
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
char boardname[100];
|
||||
|
||||
if (bd_ie_type == ATH10K_BD_IE_BOARD) {
|
||||
if (!ar->hw_params.fw.board) {
|
||||
|
@ -1240,9 +1241,19 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",
|
||||
ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
|
||||
|
||||
ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
boardname);
|
||||
if (IS_ERR(ar->normal_mode_fw.board)) {
|
||||
fw = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
ar->normal_mode_fw.board = fw;
|
||||
}
|
||||
|
||||
if (IS_ERR(ar->normal_mode_fw.board))
|
||||
return PTR_ERR(ar->normal_mode_fw.board);
|
||||
|
||||
|
|
|
@ -2692,8 +2692,10 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
|
|||
static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
|
||||
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
|
||||
switch (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
||||
return MODE_11AC_VHT160;
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
|
||||
|
@ -6926,6 +6928,9 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
|
|||
struct ieee80211_sta *sta,
|
||||
u32 rate_ctrl_flag, u8 nss)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
|
||||
|
||||
if (nss > sta->deflink.rx_nss) {
|
||||
ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
|
||||
nss, sta->deflink.rx_nss);
|
||||
|
@ -6933,19 +6938,19 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
|
|||
}
|
||||
|
||||
if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
|
||||
if (!sta->deflink.vht_cap.vht_supported) {
|
||||
if (!vht_cap->vht_supported) {
|
||||
ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
|
||||
if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) {
|
||||
if (!ht_cap->ht_supported || vht_cap->vht_supported) {
|
||||
ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported)
|
||||
if (ht_cap->ht_supported || vht_cap->vht_supported)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/iommu.h>
|
||||
#include "ahb.h"
|
||||
#include "debug.h"
|
||||
#include "hif.h"
|
||||
|
@ -757,6 +759,172 @@ static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
struct device *dev = ab->dev;
|
||||
struct device_node *node;
|
||||
struct resource r;
|
||||
int ret;
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
if (!node)
|
||||
return -ENOENT;
|
||||
|
||||
ret = of_address_to_resource(node, 0, &r);
|
||||
of_node_put(node);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to resolve msa fixed region\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ab_ahb->fw.msa_paddr = r.start;
|
||||
ab_ahb->fw.msa_size = resource_size(&r);
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "memory-region", 1);
|
||||
if (!node)
|
||||
return -ENOENT;
|
||||
|
||||
ret = of_address_to_resource(node, 0, &r);
|
||||
of_node_put(node);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to resolve ce fixed region\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ab_ahb->fw.ce_paddr = r.start;
|
||||
ab_ahb->fw.ce_size = resource_size(&r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
struct device *host_dev = ab->dev;
|
||||
struct platform_device_info info = {0};
|
||||
struct iommu_domain *iommu_dom;
|
||||
struct platform_device *pdev;
|
||||
struct device_node *node;
|
||||
int ret;
|
||||
|
||||
/* Chipsets not requiring MSA need not initialize
|
||||
* MSA resources, return success in such cases.
|
||||
*/
|
||||
if (!ab->hw_params.fixed_fw_mem)
|
||||
return 0;
|
||||
|
||||
ret = ath11k_ahb_setup_msa_resources(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to setup msa resources\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
|
||||
if (!node) {
|
||||
ab_ahb->fw.use_tz = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
info.fwnode = &node->fwnode;
|
||||
info.parent = host_dev;
|
||||
info.name = node->name;
|
||||
info.dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
pdev = platform_device_register_full(&info);
|
||||
if (IS_ERR(pdev)) {
|
||||
of_node_put(node);
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
ret = of_dma_configure(&pdev->dev, node, true);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "dma configure fail: %d\n", ret);
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ab_ahb->fw.dev = &pdev->dev;
|
||||
|
||||
iommu_dom = iommu_domain_alloc(&platform_bus_type);
|
||||
if (!iommu_dom) {
|
||||
ath11k_err(ab, "failed to allocate iommu domain\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "could not attach device: %d\n", ret);
|
||||
goto err_iommu_free;
|
||||
}
|
||||
|
||||
ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr,
|
||||
ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size,
|
||||
IOMMU_READ | IOMMU_WRITE);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to map firmware region: %d\n", ret);
|
||||
goto err_iommu_detach;
|
||||
}
|
||||
|
||||
ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr,
|
||||
ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size,
|
||||
IOMMU_READ | IOMMU_WRITE);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to map firmware CE region: %d\n", ret);
|
||||
goto err_iommu_unmap;
|
||||
}
|
||||
|
||||
ab_ahb->fw.use_tz = false;
|
||||
ab_ahb->fw.iommu_domain = iommu_dom;
|
||||
of_node_put(node);
|
||||
|
||||
return 0;
|
||||
|
||||
err_iommu_unmap:
|
||||
iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
|
||||
|
||||
err_iommu_detach:
|
||||
iommu_detach_device(iommu_dom, ab_ahb->fw.dev);
|
||||
|
||||
err_iommu_free:
|
||||
iommu_domain_free(iommu_dom);
|
||||
|
||||
err_unregister:
|
||||
platform_device_unregister(pdev);
|
||||
of_node_put(node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
|
||||
struct iommu_domain *iommu;
|
||||
size_t unmapped_size;
|
||||
|
||||
if (ab_ahb->fw.use_tz)
|
||||
return 0;
|
||||
|
||||
iommu = ab_ahb->fw.iommu_domain;
|
||||
|
||||
unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
|
||||
if (unmapped_size != ab_ahb->fw.msa_size)
|
||||
ath11k_err(ab, "failed to unmap firmware: %zu\n",
|
||||
unmapped_size);
|
||||
|
||||
unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size);
|
||||
if (unmapped_size != ab_ahb->fw.ce_size)
|
||||
ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n",
|
||||
unmapped_size);
|
||||
|
||||
iommu_detach_device(iommu, ab_ahb->fw.dev);
|
||||
iommu_domain_free(iommu);
|
||||
|
||||
platform_device_unregister(to_platform_device(ab_ahb->fw.dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ath11k_base *ab;
|
||||
|
@ -816,10 +984,14 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_core_free;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
ret = ath11k_ahb_fw_resources_init(ab);
|
||||
if (ret)
|
||||
goto err_core_free;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
if (ret)
|
||||
goto err_fw_deinit;
|
||||
|
||||
ret = ath11k_ce_alloc_pipes(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
|
||||
|
@ -856,6 +1028,9 @@ err_ce_free:
|
|||
err_hal_srng_deinit:
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
|
||||
err_fw_deinit:
|
||||
ath11k_ahb_fw_resource_deinit(ab);
|
||||
|
||||
err_core_free:
|
||||
ath11k_core_free(ab);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
@ -891,6 +1066,7 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
|
|||
qmi_fail:
|
||||
ath11k_ahb_free_irq(ab);
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
ath11k_ahb_fw_resource_deinit(ab);
|
||||
ath11k_ce_free_pipes(ab);
|
||||
ath11k_core_free(ab);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
|
|
@ -12,6 +12,15 @@ struct ath11k_base;
|
|||
|
||||
struct ath11k_ahb {
|
||||
struct rproc *tgt_rproc;
|
||||
struct {
|
||||
struct device *dev;
|
||||
struct iommu_domain *iommu_domain;
|
||||
dma_addr_t msa_paddr;
|
||||
u32 msa_size;
|
||||
dma_addr_t ce_paddr;
|
||||
u32 ce_size;
|
||||
bool use_tz;
|
||||
} fw;
|
||||
};
|
||||
|
||||
static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
|
||||
|
|
|
@ -110,6 +110,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 0,
|
||||
.ce_window_idx = 0,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
|
@ -185,6 +186,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 0,
|
||||
.ce_window_idx = 0,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
},
|
||||
{
|
||||
.name = "qca6390 hw2.0",
|
||||
|
@ -259,6 +261,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 0,
|
||||
.ce_window_idx = 0,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
},
|
||||
{
|
||||
.name = "qcn9074 hw1.0",
|
||||
|
@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 3,
|
||||
.ce_window_idx = 2,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = false,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.0",
|
||||
|
@ -407,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 0,
|
||||
.ce_window_idx = 0,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
|
@ -480,6 +485,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 0,
|
||||
.ce_window_idx = 0,
|
||||
.fixed_fw_mem = false,
|
||||
.support_off_channel_tx = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6750 hw1.0",
|
||||
|
@ -553,6 +559,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|||
.dp_window_idx = 1,
|
||||
.ce_window_idx = 2,
|
||||
.fixed_fw_mem = true,
|
||||
.support_off_channel_tx = false,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1620,9 +1627,11 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
|
|||
|
||||
ieee80211_stop_queues(ar->hw);
|
||||
ath11k_mac_drain_tx(ar);
|
||||
ar->state_11d = ATH11K_11D_IDLE;
|
||||
complete(&ar->completed_11d_scan);
|
||||
complete(&ar->scan.started);
|
||||
complete(&ar->scan.completed);
|
||||
complete(&ar->scan.on_channel);
|
||||
complete(&ar->peer_assoc_done);
|
||||
complete(&ar->peer_delete_done);
|
||||
complete(&ar->install_key_done);
|
||||
|
@ -1768,7 +1777,6 @@ static void ath11k_core_reset(struct work_struct *work)
|
|||
ATH11K_RECOVER_START_TIMEOUT_HZ);
|
||||
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_qmi_free_resource(ab);
|
||||
ath11k_hif_power_up(ab);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
|
||||
|
|
|
@ -520,6 +520,7 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
|
|||
struct hal_tx_status *ts)
|
||||
{
|
||||
struct ieee80211_tx_status status = { 0 };
|
||||
struct ieee80211_rate_status status_rate = { 0 };
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath11k_skb_cb *skb_cb;
|
||||
|
@ -603,7 +604,12 @@ static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,
|
|||
status.skb = msdu;
|
||||
status.info = info;
|
||||
rate = arsta->last_txrate;
|
||||
status.rate = &rate;
|
||||
|
||||
status_rate.rate_idx = rate;
|
||||
status_rate.try_count = 1;
|
||||
|
||||
status.rates = &status_rate;
|
||||
status.n_rates = 1;
|
||||
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ struct ath11k_base;
|
|||
#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
|
||||
#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
|
||||
#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
|
||||
#define HAL_REO1_MISC_CTL 0x00000630
|
||||
#define HAL_REO1_MISC_CTL(ab) ab->hw_params.regs->hal_reo1_misc_ctl
|
||||
#define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb
|
||||
#define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb
|
||||
#define HAL_REO1_RING_ID(ab) ab->hw_params.regs->hal_reo1_ring_id
|
||||
|
|
|
@ -771,10 +771,10 @@ static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab)
|
|||
FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
|
||||
ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
|
||||
|
||||
val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL);
|
||||
val = ath11k_hif_read32(ab, reo_base + HAL_REO1_MISC_CTL(ab));
|
||||
val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DST_RING;
|
||||
val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DST_RING, HAL_SRNG_RING_ID_REO2SW1);
|
||||
ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL, val);
|
||||
ath11k_hif_write32(ab, reo_base + HAL_REO1_MISC_CTL(ab), val);
|
||||
|
||||
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
|
||||
HAL_DEFAULT_REO_TIMEOUT_USEC);
|
||||
|
@ -1983,6 +1983,9 @@ const struct ath11k_hw_regs ipq8074_regs = {
|
|||
|
||||
/* Shadow register area */
|
||||
.hal_shadow_base_addr = 0x0,
|
||||
|
||||
/* REO misc control register, not used in IPQ8074 */
|
||||
.hal_reo1_misc_ctl = 0x0,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_regs qca6390_regs = {
|
||||
|
@ -2065,6 +2068,9 @@ const struct ath11k_hw_regs qca6390_regs = {
|
|||
|
||||
/* Shadow register area */
|
||||
.hal_shadow_base_addr = 0x000008fc,
|
||||
|
||||
/* REO misc control register, not used in QCA6390 */
|
||||
.hal_reo1_misc_ctl = 0x0,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_regs qcn9074_regs = {
|
||||
|
@ -2147,6 +2153,9 @@ const struct ath11k_hw_regs qcn9074_regs = {
|
|||
|
||||
/* Shadow register area */
|
||||
.hal_shadow_base_addr = 0x0,
|
||||
|
||||
/* REO misc control register, not used in QCN9074 */
|
||||
.hal_reo1_misc_ctl = 0x0,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_regs wcn6855_regs = {
|
||||
|
@ -2229,6 +2238,11 @@ const struct ath11k_hw_regs wcn6855_regs = {
|
|||
|
||||
/* Shadow register area */
|
||||
.hal_shadow_base_addr = 0x000008fc,
|
||||
|
||||
/* REO misc control register, used for fragment
|
||||
* destination ring config in WCN6855.
|
||||
*/
|
||||
.hal_reo1_misc_ctl = 0x00000630,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_regs wcn6750_regs = {
|
||||
|
@ -2311,6 +2325,11 @@ const struct ath11k_hw_regs wcn6750_regs = {
|
|||
|
||||
/* Shadow register area */
|
||||
.hal_shadow_base_addr = 0x00000504,
|
||||
|
||||
/* REO misc control register, used for fragment
|
||||
* destination ring config in WCN6750.
|
||||
*/
|
||||
.hal_reo1_misc_ctl = 0x000005d8,
|
||||
};
|
||||
|
||||
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
|
||||
|
|
|
@ -204,6 +204,7 @@ struct ath11k_hw_params {
|
|||
u8 dp_window_idx;
|
||||
u8 ce_window_idx;
|
||||
bool fixed_fw_mem;
|
||||
bool support_off_channel_tx;
|
||||
};
|
||||
|
||||
struct ath11k_hw_ops {
|
||||
|
@ -379,6 +380,7 @@ struct ath11k_hw_regs {
|
|||
u32 pcie_pcs_osc_dtct_config_base;
|
||||
|
||||
u32 hal_shadow_base_addr;
|
||||
u32 hal_reo1_misc_ctl;
|
||||
};
|
||||
|
||||
extern const struct ath11k_hw_regs ipq8074_regs;
|
||||
|
|
|
@ -1951,7 +1951,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
|
|||
/* Calculate peer NSS capability from VHT capabilities if STA
|
||||
* supports VHT.
|
||||
*/
|
||||
for (i = 0, max_nss = 0, vht_mcs = 0; i < NL80211_VHT_NSS_MAX; i++) {
|
||||
for (i = 0, max_nss = 0; i < NL80211_VHT_NSS_MAX; i++) {
|
||||
vht_mcs = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) >>
|
||||
(2 * i) & 3;
|
||||
|
||||
|
@ -2272,7 +2272,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
|||
/* Calculate peer NSS capability from HE capabilities if STA
|
||||
* supports HE.
|
||||
*/
|
||||
for (i = 0, max_nss = 0, he_mcs = 0; i < NL80211_HE_NSS_MAX; i++) {
|
||||
for (i = 0, max_nss = 0; i < NL80211_HE_NSS_MAX; i++) {
|
||||
he_mcs = he_tx_mcs >> (2 * i) & 3;
|
||||
|
||||
/* In case of fixed rates, MCS Range in he_tx_mcs might have
|
||||
|
@ -5551,8 +5551,8 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
arvif = ath11k_vif_to_arvif(skb_cb->vif);
|
||||
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
|
||||
arvif->is_started) {
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
|
||||
ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
|
||||
|
@ -5570,6 +5570,7 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
|||
arvif->is_started);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6155,6 +6156,11 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar)
|
|||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n",
|
||||
ar->vdev_id_11d_scan);
|
||||
|
||||
if (ar->state_11d == ATH11K_11D_PREPARING) {
|
||||
ar->state_11d = ATH11K_11D_IDLE;
|
||||
complete(&ar->completed_11d_scan);
|
||||
}
|
||||
|
||||
if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) {
|
||||
vdev_id = ar->vdev_id_11d_scan;
|
||||
|
||||
|
@ -7741,6 +7747,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
|
|||
bool he_fixed_rate = false, vht_fixed_rate = false;
|
||||
struct ath11k_peer *peer, *tmp;
|
||||
const u16 *vht_mcs_mask, *he_mcs_mask;
|
||||
struct ieee80211_link_sta *deflink;
|
||||
u8 vht_nss, he_nss;
|
||||
bool ret = true;
|
||||
|
||||
|
@ -7763,13 +7770,16 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
|
|||
spin_lock_bh(&ar->ab->base_lock);
|
||||
list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
|
||||
if (peer->sta) {
|
||||
if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported ||
|
||||
peer->sta->deflink.rx_nss < vht_nss)) {
|
||||
deflink = &peer->sta->deflink;
|
||||
|
||||
if (vht_fixed_rate && (!deflink->vht_cap.vht_supported ||
|
||||
deflink->rx_nss < vht_nss)) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he ||
|
||||
peer->sta->deflink.rx_nss < he_nss)) {
|
||||
|
||||
if (he_fixed_rate && (!deflink->he_cap.has_he ||
|
||||
deflink->rx_nss < he_nss)) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
@ -8345,6 +8355,118 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->scan.roc_notify = false;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath11k_scan_abort(ar);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_remain_on_channel(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel *chan,
|
||||
int duration,
|
||||
enum ieee80211_roc_type type)
|
||||
{
|
||||
struct ath11k *ar = hw->priv;
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct scan_req_params arg;
|
||||
int ret;
|
||||
u32 scan_time_msec;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
switch (ar->scan.state) {
|
||||
case ATH11K_SCAN_IDLE:
|
||||
reinit_completion(&ar->scan.started);
|
||||
reinit_completion(&ar->scan.completed);
|
||||
reinit_completion(&ar->scan.on_channel);
|
||||
ar->scan.state = ATH11K_SCAN_STARTING;
|
||||
ar->scan.is_roc = true;
|
||||
ar->scan.vdev_id = arvif->vdev_id;
|
||||
ar->scan.roc_freq = chan->center_freq;
|
||||
ar->scan.roc_notify = true;
|
||||
ret = 0;
|
||||
break;
|
||||
case ATH11K_SCAN_STARTING:
|
||||
case ATH11K_SCAN_RUNNING:
|
||||
case ATH11K_SCAN_ABORTING:
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
ath11k_wmi_start_scan_init(ar, &arg);
|
||||
arg.num_chan = 1;
|
||||
arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
|
||||
GFP_KERNEL);
|
||||
if (!arg.chan_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.scan_id = ATH11K_SCAN_ID;
|
||||
arg.chan_list[0] = chan->center_freq;
|
||||
arg.dwell_time_active = scan_time_msec;
|
||||
arg.dwell_time_passive = scan_time_msec;
|
||||
arg.max_scan_time = scan_time_msec;
|
||||
arg.scan_flags |= WMI_SCAN_FLAG_PASSIVE;
|
||||
arg.scan_flags |= WMI_SCAN_FILTER_PROBE_REQ;
|
||||
arg.burst_duration = duration;
|
||||
|
||||
ret = ath11k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to start roc scan: %d\n", ret);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->scan.state = ATH11K_SCAN_IDLE;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
goto free_chan_list;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.on_channel, 3 * HZ);
|
||||
if (ret == 0) {
|
||||
ath11k_warn(ar->ab, "failed to switch to channel for roc scan\n");
|
||||
ret = ath11k_scan_stop(ar);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to stop scan: %d\n", ret);
|
||||
ret = -ETIMEDOUT;
|
||||
goto free_chan_list;
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
|
||||
msecs_to_jiffies(duration));
|
||||
|
||||
ret = 0;
|
||||
|
||||
free_chan_list:
|
||||
kfree(arg.chan_list);
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops ath11k_ops = {
|
||||
.tx = ath11k_mac_op_tx,
|
||||
.start = ath11k_mac_op_start,
|
||||
|
@ -8397,6 +8519,8 @@ static const struct ieee80211_ops ath11k_ops = {
|
|||
#endif
|
||||
|
||||
.set_sar_specs = ath11k_mac_op_set_bios_sar_specs,
|
||||
.remain_on_channel = ath11k_mac_op_remain_on_channel,
|
||||
.cancel_remain_on_channel = ath11k_mac_op_cancel_remain_on_channel,
|
||||
};
|
||||
|
||||
static void ath11k_mac_update_ch_list(struct ath11k *ar,
|
||||
|
@ -8986,6 +9110,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
|
|||
init_completion(&ar->bss_survey_done);
|
||||
init_completion(&ar->scan.started);
|
||||
init_completion(&ar->scan.completed);
|
||||
init_completion(&ar->scan.on_channel);
|
||||
init_completion(&ar->thermal.wmi_sync);
|
||||
|
||||
INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
|
||||
|
@ -9026,3 +9151,34 @@ void ath11k_mac_destroy(struct ath11k_base *ab)
|
|||
pdev->ar = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct wmi_sta_keepalive_arg arg = {};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_STA_KEEP_ALIVE, ar->ab->wmi_ab.svc_map))
|
||||
return 0;
|
||||
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.enabled = 1;
|
||||
arg.method = method;
|
||||
arg.interval = interval;
|
||||
|
||||
ret = ath11k_wmi_sta_keepalive(ar, &arg);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set keepalive on vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "wmi.h"
|
||||
|
||||
struct ath11k;
|
||||
struct ath11k_base;
|
||||
|
@ -173,4 +174,7 @@ void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb);
|
|||
void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id);
|
||||
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif);
|
||||
int ath11k_mac_wait_tx_complete(struct ath11k *ar);
|
||||
int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval);
|
||||
#endif
|
||||
|
|
|
@ -1970,6 +1970,21 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|||
|
||||
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
chunk = &ab->qmi.target_mem[i];
|
||||
|
||||
/* Firmware reloads in coldboot/firmware recovery.
|
||||
* in such case, no need to allocate memory for FW again.
|
||||
*/
|
||||
if (chunk->vaddr) {
|
||||
if (chunk->prev_type == chunk->type ||
|
||||
chunk->prev_size == chunk->size)
|
||||
continue;
|
||||
|
||||
/* cannot reuse the existing chunk */
|
||||
dma_free_coherent(ab->dev, chunk->size,
|
||||
chunk->vaddr, chunk->paddr);
|
||||
chunk->vaddr = NULL;
|
||||
}
|
||||
|
||||
chunk->vaddr = dma_alloc_coherent(ab->dev,
|
||||
chunk->size,
|
||||
&chunk->paddr,
|
||||
|
@ -1990,6 +2005,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|||
chunk->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
chunk->prev_type = chunk->type;
|
||||
chunk->prev_size = chunk->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2466,9 +2483,6 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
|
|||
char path[100];
|
||||
int ret;
|
||||
|
||||
if (m3_mem->vaddr || m3_mem->size)
|
||||
return 0;
|
||||
|
||||
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
|
||||
if (IS_ERR(fw)) {
|
||||
ret = PTR_ERR(fw);
|
||||
|
@ -2478,6 +2492,9 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (m3_mem->vaddr || m3_mem->size)
|
||||
goto skip_m3_alloc;
|
||||
|
||||
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
|
||||
fw->size, &m3_mem->paddr,
|
||||
GFP_KERNEL);
|
||||
|
@ -2488,6 +2505,7 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skip_m3_alloc:
|
||||
memcpy(m3_mem->vaddr, fw->data, fw->size);
|
||||
m3_mem->size = fw->size;
|
||||
release_firmware(fw);
|
||||
|
|
|
@ -97,6 +97,8 @@ struct ath11k_qmi_event_msg {
|
|||
struct target_mem_chunk {
|
||||
u32 size;
|
||||
u32 type;
|
||||
u32 prev_size;
|
||||
u32 prev_type;
|
||||
dma_addr_t paddr;
|
||||
u32 *vaddr;
|
||||
void __iomem *iaddr;
|
||||
|
|
|
@ -139,6 +139,9 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
|
|||
"reg hw scan wait left time %d\n", left);
|
||||
}
|
||||
|
||||
if (ar->state == ATH11K_STATE_RESTARTING)
|
||||
return 0;
|
||||
|
||||
bands = hw->wiphy->bands;
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
if (!bands[band])
|
||||
|
|
|
@ -625,10 +625,25 @@ struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len)
|
|||
return skb;
|
||||
}
|
||||
|
||||
static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar,
|
||||
struct ieee80211_tx_info *info)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
u32 freq = 0;
|
||||
|
||||
if (ab->hw_params.support_off_channel_tx &&
|
||||
ar->scan.is_roc &&
|
||||
(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
|
||||
freq = ar->scan.roc_freq;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
|
||||
struct sk_buff *frame)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);
|
||||
struct wmi_mgmt_send_cmd *cmd;
|
||||
struct wmi_tlv *frame_tlv;
|
||||
struct sk_buff *skb;
|
||||
|
@ -649,7 +664,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
|
|||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
cmd->vdev_id = vdev_id;
|
||||
cmd->desc_id = buf_id;
|
||||
cmd->chanfreq = 0;
|
||||
cmd->chanfreq = ath11k_wmi_mgmt_get_freq(ar, info);
|
||||
cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr);
|
||||
cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr);
|
||||
cmd->frame_len = frame->len;
|
||||
|
@ -5264,6 +5279,8 @@ static void ath11k_wmi_event_scan_started(struct ath11k *ar)
|
|||
break;
|
||||
case ATH11K_SCAN_STARTING:
|
||||
ar->scan.state = ATH11K_SCAN_RUNNING;
|
||||
if (ar->scan.is_roc)
|
||||
ieee80211_ready_on_channel(ar->hw);
|
||||
complete(&ar->scan.started);
|
||||
break;
|
||||
}
|
||||
|
@ -5346,6 +5363,8 @@ static void ath11k_wmi_event_scan_foreign_chan(struct ath11k *ar, u32 freq)
|
|||
case ATH11K_SCAN_RUNNING:
|
||||
case ATH11K_SCAN_ABORTING:
|
||||
ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq);
|
||||
if (ar->scan.is_roc && ar->scan.roc_freq == freq)
|
||||
complete(&ar->scan.on_channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8959,3 +8978,44 @@ int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar)
|
|||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID);
|
||||
}
|
||||
|
||||
int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
const struct wmi_sta_keepalive_arg *arg)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_sta_keepalive_cmd *cmd;
|
||||
struct wmi_sta_keepalive_arp_resp *arp;
|
||||
struct sk_buff *skb;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*cmd) + sizeof(*arp);
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_sta_keepalive_cmd *)skb->data;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_STA_KEEPALIVE_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
cmd->vdev_id = arg->vdev_id;
|
||||
cmd->enabled = arg->enabled;
|
||||
cmd->interval = arg->interval;
|
||||
cmd->method = arg->method;
|
||||
|
||||
if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE ||
|
||||
arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) {
|
||||
arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1);
|
||||
arp->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_STA_KEEPALVE_ARP_RESPONSE) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE);
|
||||
arp->src_ip4_addr = arg->src_ip4_addr;
|
||||
arp->dest_ip4_addr = arg->dest_ip4_addr;
|
||||
ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr);
|
||||
}
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
|
||||
arg->vdev_id, arg->enabled, arg->method, arg->interval);
|
||||
|
||||
return ath11k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
|
||||
}
|
||||
|
|
|
@ -5907,6 +5907,50 @@ struct wmi_pdev_set_geo_table_cmd {
|
|||
u32 rsvd_len;
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
u32 enabled;
|
||||
|
||||
/* WMI_STA_KEEPALIVE_METHOD_ */
|
||||
u32 method;
|
||||
|
||||
/* in seconds */
|
||||
u32 interval;
|
||||
|
||||
/* following this structure is the TLV for struct
|
||||
* wmi_sta_keepalive_arp_resp
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_arp_resp {
|
||||
u32 tlv_header;
|
||||
u32 src_ip4_addr;
|
||||
u32 dest_ip4_addr;
|
||||
struct wmi_mac_addr dest_mac_addr;
|
||||
} __packed;
|
||||
|
||||
struct wmi_sta_keepalive_arg {
|
||||
u32 vdev_id;
|
||||
u32 enabled;
|
||||
u32 method;
|
||||
u32 interval;
|
||||
u32 src_ip4_addr;
|
||||
u32 dest_ip4_addr;
|
||||
const u8 dest_mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
enum wmi_sta_keepalive_method {
|
||||
WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1,
|
||||
WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE = 2,
|
||||
WMI_STA_KEEPALIVE_METHOD_ETHERNET_LOOPBACK = 3,
|
||||
WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST = 4,
|
||||
WMI_STA_KEEPALIVE_METHOD_MGMT_VENDOR_ACTION = 5,
|
||||
};
|
||||
|
||||
#define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30
|
||||
#define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0
|
||||
|
||||
int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
|
||||
u32 cmd_id);
|
||||
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
|
||||
|
@ -6087,5 +6131,7 @@ int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar,
|
|||
struct ath11k_vif *arvif);
|
||||
int ath11k_wmi_pdev_set_bios_sar_table_param(struct ath11k *ar, const u8 *sar_val);
|
||||
int ath11k_wmi_pdev_set_bios_geo_table_param(struct ath11k *ar);
|
||||
int ath11k_wmi_sta_keepalive(struct ath11k *ar,
|
||||
const struct wmi_sta_keepalive_arg *arg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -640,6 +640,24 @@ static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_wow_set_keepalive(struct ath11k *ar,
|
||||
enum wmi_sta_keepalive_method method,
|
||||
u32 interval)
|
||||
{
|
||||
struct ath11k_vif *arvif;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
ret = ath11k_mac_vif_set_keepalive(arvif, method, interval);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
|
||||
struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
|
@ -691,6 +709,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = ath11k_wow_set_keepalive(ar,
|
||||
WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
|
||||
WMI_STA_KEEPALIVE_INTERVAL_DEFAULT);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = ath11k_wow_enable(ar->ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to start wow: %d\n", ret);
|
||||
|
@ -786,6 +812,14 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath11k_wow_set_keepalive(ar,
|
||||
WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
|
||||
WMI_STA_KEEPALIVE_INTERVAL_DISABLE);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (ret) {
|
||||
switch (ar->state) {
|
||||
|
|
|
@ -1391,19 +1391,6 @@ static int temp_show(struct seq_file *s, void *data)
|
|||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(temp);
|
||||
|
||||
/*---------freq------------*/
|
||||
static int freq_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct wil6210_priv *wil = s->private;
|
||||
struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
|
||||
u32 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
|
||||
|
||||
seq_printf(s, "Freq = %d\n", freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(freq);
|
||||
|
||||
/*---------link------------*/
|
||||
static int link_show(struct seq_file *s, void *data)
|
||||
{
|
||||
|
@ -2380,7 +2367,6 @@ static const struct {
|
|||
{"pmcdata", 0444, &fops_pmcdata},
|
||||
{"pmcring", 0444, &fops_pmcring},
|
||||
{"temp", 0444, &temp_fops},
|
||||
{"freq", 0444, &freq_fops},
|
||||
{"link", 0444, &link_fops},
|
||||
{"info", 0444, &info_fops},
|
||||
{"recovery", 0644, &fops_recovery},
|
||||
|
|
|
@ -458,16 +458,14 @@ int wil_if_add(struct wil6210_priv *wil)
|
|||
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
|
||||
wil6210_netdev_poll_rx_edma,
|
||||
NAPI_POLL_WEIGHT);
|
||||
netif_tx_napi_add(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx_edma,
|
||||
NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx_edma);
|
||||
} else {
|
||||
netif_napi_add(&wil->napi_ndev, &wil->napi_rx,
|
||||
wil6210_netdev_poll_rx,
|
||||
NAPI_POLL_WEIGHT);
|
||||
netif_tx_napi_add(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx,
|
||||
NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&wil->napi_ndev,
|
||||
&wil->napi_tx, wil6210_netdev_poll_tx);
|
||||
}
|
||||
|
||||
wil_update_net_queues_bh(wil, vif, NULL, true);
|
||||
|
|
|
@ -202,13 +202,24 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||
char *ptr;
|
||||
s32 err;
|
||||
|
||||
/* retreive mac address */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
sizeof(ifp->mac_addr));
|
||||
if (err < 0) {
|
||||
bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
|
||||
goto done;
|
||||
if (is_valid_ether_addr(ifp->mac_addr)) {
|
||||
/* set mac address */
|
||||
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
ETH_ALEN);
|
||||
if (err < 0) {
|
||||
bphy_err(ifp->drvr, "Setting cur_etheraddr failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* retrieve mac address */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
sizeof(ifp->mac_addr));
|
||||
if (err < 0) {
|
||||
bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
|
||||
memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ struct brcmf_mp_device {
|
|||
bool ignore_probe_fail;
|
||||
struct brcmfmac_pd_cc *country_codes;
|
||||
const char *board_type;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
union {
|
||||
struct brcmfmac_sdio_pd sdio;
|
||||
} bus;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/property.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/addrconf.h>
|
||||
|
@ -1197,7 +1198,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
|
|||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
/* add primary networking interface */
|
||||
ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
|
||||
ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d",
|
||||
is_valid_ether_addr(drvr->settings->mac) ? drvr->settings->mac : NULL);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_net.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include "debug.h"
|
||||
|
@ -99,6 +100,8 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
|||
if (err)
|
||||
brcmf_err("failed to get OF country code map (err=%d)\n", err);
|
||||
|
||||
of_get_mac_address(np, settings->mac);
|
||||
|
||||
if (bus_type != BRCMF_BUSTYPE_SDIO)
|
||||
return;
|
||||
|
||||
|
|
|
@ -937,6 +937,9 @@ int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
|
|||
{
|
||||
int i, j;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return -ENODATA;
|
||||
|
||||
if (!iwl_sar_geo_support(fwrt))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
|
|
@ -389,6 +389,8 @@ enum {
|
|||
#define WFPM_LMAC1_PD_NOTIFICATION 0xa0338c
|
||||
#define WFPM_ARC1_PD_NOTIFICATION 0xa03044
|
||||
#define HPM_SECONDARY_DEVICE_STATE 0xa03404
|
||||
#define WFPM_MAC_OTP_CFG7_ADDR 0xa03338
|
||||
#define WFPM_MAC_OTP_CFG7_DATA 0xa0333c
|
||||
|
||||
|
||||
/* For UMAG_GEN_HW_STATUS reg check */
|
||||
|
|
|
@ -493,6 +493,7 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx)
|
|||
if (cb_tx) {
|
||||
struct iwl_sap_cb_data *cb_hdr = skb_push(skb, sizeof(*cb_hdr));
|
||||
|
||||
memset(cb_hdr, 0, sizeof(*cb_hdr));
|
||||
cb_hdr->hdr.type = cpu_to_le16(SAP_MSG_CB_DATA_PACKET);
|
||||
cb_hdr->hdr.len = cpu_to_le16(skb->len - sizeof(cb_hdr->hdr));
|
||||
cb_hdr->hdr.seq_num = cpu_to_le32(atomic_inc_return(&mei->sap_seq_no));
|
||||
|
@ -1019,6 +1020,8 @@ static void iwl_mei_handle_sap_data(struct mei_cl_device *cldev,
|
|||
|
||||
/* We need enough room for the WiFi header + SNAP + IV */
|
||||
skb = netdev_alloc_skb(netdev, len + QOS_HDR_IV_SNAP_LEN);
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
skb_reserve(skb, QOS_HDR_IV_SNAP_LEN);
|
||||
ethhdr = skb_push(skb, sizeof(*ethhdr));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -1956,18 +1956,18 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
|
|||
\
|
||||
if (len < sizeof(*data)) { \
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
|
||||
return ERR_PTR(-EIO); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
data_size = ALIGN(le32_to_cpu(data->wake_packet_bufsize), 4); \
|
||||
if (len != sizeof(*data) + data_size) { \
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); \
|
||||
return ERR_PTR(-EIO); \
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
status = kzalloc(sizeof(*status) + data_size, GFP_KERNEL); \
|
||||
if (!status) \
|
||||
return ERR_PTR(-ENOMEM); \
|
||||
return NULL; \
|
||||
\
|
||||
/* copy all the common fields */ \
|
||||
status->replay_ctr = le64_to_cpu(data->replay_ctr); \
|
||||
|
@ -2097,7 +2097,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
|
||||
if (IS_ERR(status))
|
||||
if (!status)
|
||||
goto out_free_resp;
|
||||
|
||||
BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
|
||||
|
@ -2128,7 +2128,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);
|
||||
if (IS_ERR(status))
|
||||
if (!status)
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
|
||||
|
@ -2141,7 +2141,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
* difference is only in a few not used (reserved) fields.
|
||||
*/
|
||||
status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
|
||||
if (IS_ERR(status))
|
||||
if (!status)
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
|
||||
|
@ -2153,7 +2153,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
|
||||
if (IS_ERR(status))
|
||||
if (!status)
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
|
||||
|
@ -2165,7 +2165,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
|||
IWL_ERR(mvm,
|
||||
"Firmware advertises unknown WoWLAN status response %d!\n",
|
||||
notif_ver);
|
||||
status = ERR_PTR(-EIO);
|
||||
status = NULL;
|
||||
}
|
||||
|
||||
out_free_resp:
|
||||
|
@ -2203,7 +2203,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
|||
struct iwl_mvm_sta *mvm_ap_sta;
|
||||
|
||||
status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
|
||||
if (IS_ERR(status))
|
||||
if (!status)
|
||||
goto out_unlock;
|
||||
|
||||
IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
|
||||
|
@ -2370,7 +2370,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
|
|||
int i, n_matches, ret;
|
||||
|
||||
status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
|
||||
if (!IS_ERR(status)) {
|
||||
if (status) {
|
||||
reasons = status->wakeup_reasons;
|
||||
kfree(status);
|
||||
}
|
||||
|
|
|
@ -287,6 +287,9 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
|
|||
|
||||
static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
|
||||
{
|
||||
#define IWL_FW_PRINT_REG_INFO(reg_name) \
|
||||
IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name))
|
||||
|
||||
struct iwl_trans *trans = mvm->trans;
|
||||
enum iwl_device_family device_family = trans->trans_cfg->device_family;
|
||||
|
||||
|
@ -294,15 +297,15 @@ static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm)
|
|||
return;
|
||||
|
||||
if (device_family <= IWL_DEVICE_FAMILY_9000)
|
||||
IWL_ERR(mvm, "WFPM_ARC1_PD_NOTIFICATION: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, WFPM_ARC1_PD_NOTIFICATION));
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_ARC1_PD_NOTIFICATION);
|
||||
else
|
||||
IWL_ERR(mvm, "WFPM_LMAC1_PD_NOTIFICATION: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, WFPM_LMAC1_PD_NOTIFICATION));
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION);
|
||||
|
||||
IWL_ERR(mvm, "HPM_SECONDARY_DEVICE_STATE: 0x%x\n",
|
||||
iwl_read_umac_prph(trans, HPM_SECONDARY_DEVICE_STATE));
|
||||
IWL_FW_PRINT_REG_INFO(HPM_SECONDARY_DEVICE_STATE);
|
||||
|
||||
/* print OPT info */
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_ADDR);
|
||||
IWL_FW_PRINT_REG_INFO(WFPM_MAC_OTP_CFG7_DATA);
|
||||
}
|
||||
|
||||
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -552,6 +552,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
/* Fill the common data for all mac context types */
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, bssid_override, action);
|
||||
|
||||
/*
|
||||
* We always want to hear MCAST frames, if we're not authorized yet,
|
||||
* we'll drop them.
|
||||
*/
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
|
||||
|
||||
if (vif->p2p) {
|
||||
struct ieee80211_p2p_noa_attr *noa =
|
||||
&vif->bss_conf.p2p_noa_attr;
|
||||
|
@ -567,7 +573,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
|
||||
!force_assoc_off) {
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u8 ap_sta_id = mvmvif->ap_sta_id;
|
||||
u32 dtim_offs;
|
||||
|
||||
/*
|
||||
|
@ -609,29 +614,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
|||
IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
|
||||
ctxt_sta->data_policy |=
|
||||
cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
|
||||
|
||||
/*
|
||||
* allow multicast data frames only as long as the station is
|
||||
* authorized, i.e., GTK keys are already installed (if needed)
|
||||
*/
|
||||
if (ap_sta_id < mvm->fw->ucode_capa.num_stations) {
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[ap_sta_id]);
|
||||
if (!IS_ERR_OR_NULL(sta)) {
|
||||
struct iwl_mvm_sta *mvmsta =
|
||||
iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
if (mvmsta->sta_state ==
|
||||
IEEE80211_STA_AUTHORIZED)
|
||||
cmd.filter_flags |=
|
||||
cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
} else {
|
||||
ctxt_sta->is_assoc = cpu_to_le32(0);
|
||||
|
||||
|
|
|
@ -976,7 +976,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
|
|||
|
||||
ieee80211_wake_queues(mvm->hw);
|
||||
|
||||
mvm->vif_count = 0;
|
||||
mvm->rx_ba_sessions = 0;
|
||||
mvm->fwrt.dump.conf = FW_DBG_INVALID;
|
||||
mvm->monitor_on = false;
|
||||
|
@ -1380,10 +1379,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
|
||||
|
||||
/* Counting number of interfaces is needed for legacy PM */
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->vif_count++;
|
||||
|
||||
/*
|
||||
* The AP binding flow can be done only after the beacon
|
||||
* template is configured (which happens only in the mac80211
|
||||
|
@ -1400,7 +1395,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
ret = iwl_mvm_alloc_bcast_sta(mvm, vif);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to allocate bcast sta\n");
|
||||
goto out_release;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1411,7 +1406,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
0, vif->type,
|
||||
IWL_STA_MULTICAST);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
goto out_unlock;
|
||||
|
@ -1421,7 +1416,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
goto out_unlock;
|
||||
|
||||
ret = iwl_mvm_power_update_mac(mvm);
|
||||
if (ret)
|
||||
|
@ -1498,9 +1493,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
out_remove_mac:
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
out_release:
|
||||
if (vif->type != NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->vif_count--;
|
||||
out_unlock:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
|
@ -1582,9 +1574,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
mvmvif->phy_ctxt = NULL;
|
||||
}
|
||||
|
||||
if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
|
||||
mvm->vif_count--;
|
||||
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
||||
|
|
|
@ -934,7 +934,6 @@ struct iwl_mvm {
|
|||
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
|
||||
u8 fw_key_deleted[STA_KEY_MAX_NUM];
|
||||
|
||||
u8 vif_count;
|
||||
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
|
||||
|
||||
/* -1 for always, 0 for never, >0 for that many times */
|
||||
|
|
|
@ -563,6 +563,9 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
|
|||
struct iwl_power_vifs *power_iterator = _data;
|
||||
bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
|
||||
|
||||
if (!mvmvif->uploaded)
|
||||
return;
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018-2022 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
|
@ -326,17 +326,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
|
||||
rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
|
||||
/*
|
||||
* drop the packet if it has failed being decrypted by HW
|
||||
*/
|
||||
if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
|
||||
&crypt_len)) {
|
||||
IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
|
||||
rx_pkt_status);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep packets with CRC errors (and with overrun) for monitor mode
|
||||
* (otherwise the firmware discards them) but mark them as bad.
|
||||
|
@ -386,6 +375,37 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
|
|||
sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_vif *vif = mvmsta->vif;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
/*
|
||||
* Don't even try to decrypt a MCAST frame that was received
|
||||
* before the managed vif is authorized, we'd fail anyway.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
!mvmvif->authorized &&
|
||||
is_multicast_ether_addr(hdr->addr1)) {
|
||||
IWL_DEBUG_DROP(mvm, "MCAST before the vif is authorized\n");
|
||||
kfree_skb(skb);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* drop the packet if it has failed being decrypted by HW
|
||||
*/
|
||||
if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
|
||||
&crypt_len)) {
|
||||
IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
|
||||
rx_pkt_status);
|
||||
kfree_skb(skb);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct ieee80211_vif *tx_blocked_vif =
|
||||
|
|
|
@ -1085,34 +1085,44 @@ bool iwl_pcie_check_hw_rf_kill(struct iwl_trans *trans)
|
|||
}
|
||||
|
||||
struct iwl_causes_list {
|
||||
u32 cause_num;
|
||||
u32 mask_reg;
|
||||
u16 mask_reg;
|
||||
u8 bit;
|
||||
u8 addr;
|
||||
};
|
||||
|
||||
#define CAUSE(reg, mask) \
|
||||
{ \
|
||||
.mask_reg = reg, \
|
||||
.bit = ilog2(mask), \
|
||||
.addr = ilog2(mask) + \
|
||||
((reg) == CSR_MSIX_FH_INT_MASK_AD ? -16 : \
|
||||
(reg) == CSR_MSIX_HW_INT_MASK_AD ? 16 : \
|
||||
0xffff), /* causes overflow warning */ \
|
||||
}
|
||||
|
||||
static const struct iwl_causes_list causes_list_common[] = {
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH0_NUM, CSR_MSIX_FH_INT_MASK_AD, 0},
|
||||
{MSIX_FH_INT_CAUSES_D2S_CH1_NUM, CSR_MSIX_FH_INT_MASK_AD, 0x1},
|
||||
{MSIX_FH_INT_CAUSES_S2D, CSR_MSIX_FH_INT_MASK_AD, 0x3},
|
||||
{MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5},
|
||||
{MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10},
|
||||
{MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11},
|
||||
{MSIX_HW_INT_CAUSES_REG_RESET_DONE, CSR_MSIX_HW_INT_MASK_AD, 0x12},
|
||||
{MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16},
|
||||
{MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17},
|
||||
{MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18},
|
||||
{MSIX_HW_INT_CAUSES_REG_SCD, CSR_MSIX_HW_INT_MASK_AD, 0x2A},
|
||||
{MSIX_HW_INT_CAUSES_REG_FH_TX, CSR_MSIX_HW_INT_MASK_AD, 0x2B},
|
||||
{MSIX_HW_INT_CAUSES_REG_HW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x2D},
|
||||
{MSIX_HW_INT_CAUSES_REG_HAP, CSR_MSIX_HW_INT_MASK_AD, 0x2E},
|
||||
CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH0_NUM),
|
||||
CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_D2S_CH1_NUM),
|
||||
CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_S2D),
|
||||
CAUSE(CSR_MSIX_FH_INT_MASK_AD, MSIX_FH_INT_CAUSES_FH_ERR),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_ALIVE),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_WAKEUP),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RESET_DONE),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_CT_KILL),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_RF_KILL),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_PERIODIC),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SCD),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_FH_TX),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HW_ERR),
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_HAP),
|
||||
};
|
||||
|
||||
static const struct iwl_causes_list causes_list_pre_bz[] = {
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR, CSR_MSIX_HW_INT_MASK_AD, 0x29},
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR),
|
||||
};
|
||||
|
||||
static const struct iwl_causes_list causes_list_bz[] = {
|
||||
{MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ, CSR_MSIX_HW_INT_MASK_AD, 0x15},
|
||||
CAUSE(CSR_MSIX_HW_INT_MASK_AD, MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ),
|
||||
};
|
||||
|
||||
static void iwl_pcie_map_list(struct iwl_trans *trans,
|
||||
|
@ -1124,7 +1134,7 @@ static void iwl_pcie_map_list(struct iwl_trans *trans,
|
|||
for (i = 0; i < arr_size; i++) {
|
||||
iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
|
||||
iwl_clear_bit(trans, causes[i].mask_reg,
|
||||
causes[i].cause_num);
|
||||
BIT(causes[i].bit));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,15 +162,15 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
|
|||
if (!sta)
|
||||
return;
|
||||
|
||||
if (!status->aggr && !(status->flag & RX_FLAG_8023)) {
|
||||
mt76_rx_aggr_check_ctl(skb, frames);
|
||||
if (!status->aggr) {
|
||||
if (!(status->flag & RX_FLAG_8023))
|
||||
mt76_rx_aggr_check_ctl(skb, frames);
|
||||
return;
|
||||
}
|
||||
|
||||
/* not part of a BA session */
|
||||
ackp = status->qos_ctl & IEEE80211_QOS_CTL_ACK_POLICY_MASK;
|
||||
if (ackp != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
|
||||
ackp != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
|
||||
if (ackp == IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
|
||||
return;
|
||||
|
||||
tid = rcu_dereference(wcid->aggr[tidno]);
|
||||
|
|
|
@ -7,6 +7,37 @@
|
|||
#include "mt76.h"
|
||||
#include "dma.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
|
||||
|
||||
#define Q_READ(_dev, _q, _field) ({ \
|
||||
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
|
||||
u32 _val; \
|
||||
if ((_q)->flags & MT_QFLAG_WED) \
|
||||
_val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \
|
||||
((_q)->wed_regs + \
|
||||
_offset)); \
|
||||
else \
|
||||
_val = readl(&(_q)->regs->_field); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define Q_WRITE(_dev, _q, _field, _val) do { \
|
||||
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
|
||||
if ((_q)->flags & MT_QFLAG_WED) \
|
||||
mtk_wed_device_reg_write(&(_dev)->mmio.wed, \
|
||||
((_q)->wed_regs + _offset), \
|
||||
_val); \
|
||||
else \
|
||||
writel(_val, &(_q)->regs->_field); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field)
|
||||
#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field)
|
||||
|
||||
#endif
|
||||
|
||||
static struct mt76_txwi_cache *
|
||||
mt76_alloc_txwi(struct mt76_dev *dev)
|
||||
{
|
||||
|
@ -16,11 +47,11 @@ mt76_alloc_txwi(struct mt76_dev *dev)
|
|||
int size;
|
||||
|
||||
size = L1_CACHE_ALIGN(dev->drv->txwi_size + sizeof(*t));
|
||||
txwi = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
|
||||
txwi = kzalloc(size, GFP_ATOMIC);
|
||||
if (!txwi)
|
||||
return NULL;
|
||||
|
||||
addr = dma_map_single(dev->dev, txwi, dev->drv->txwi_size,
|
||||
addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
|
||||
t->dma_addr = addr;
|
||||
|
@ -73,18 +104,20 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
|
|||
struct mt76_txwi_cache *t;
|
||||
|
||||
local_bh_disable();
|
||||
while ((t = __mt76_get_txwi(dev)) != NULL)
|
||||
dma_unmap_single(dev->dev, t->dma_addr, dev->drv->txwi_size,
|
||||
while ((t = __mt76_get_txwi(dev)) != NULL) {
|
||||
dma_unmap_single(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
kfree(mt76_get_txwi_ptr(dev, t));
|
||||
}
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
writel(q->desc_dma, &q->regs->desc_base);
|
||||
writel(q->ndesc, &q->regs->ring_size);
|
||||
q->head = readl(&q->regs->dma_idx);
|
||||
Q_WRITE(dev, q, desc_base, q->desc_dma);
|
||||
Q_WRITE(dev, q, ring_size, q->ndesc);
|
||||
q->head = Q_READ(dev, q, dma_idx);
|
||||
q->tail = q->head;
|
||||
}
|
||||
|
||||
|
@ -100,41 +133,11 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
|
|||
for (i = 0; i < q->ndesc; i++)
|
||||
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
|
||||
writel(0, &q->regs->cpu_idx);
|
||||
writel(0, &q->regs->dma_idx);
|
||||
Q_WRITE(dev, q, cpu_idx, 0);
|
||||
Q_WRITE(dev, q, dma_idx, 0);
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize,
|
||||
u32 ring_base)
|
||||
{
|
||||
int size;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
spin_lock_init(&q->cleanup_lock);
|
||||
|
||||
q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->buf_size = bufsize;
|
||||
q->hw_idx = idx;
|
||||
|
||||
size = q->ndesc * sizeof(struct mt76_desc);
|
||||
q->desc = dmam_alloc_coherent(dev->dev, size, &q->desc_dma, GFP_KERNEL);
|
||||
if (!q->desc)
|
||||
return -ENOMEM;
|
||||
|
||||
size = q->ndesc * sizeof(*q->entry);
|
||||
q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
|
||||
if (!q->entry)
|
||||
return -ENOMEM;
|
||||
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct mt76_queue_buf *buf, int nbufs, u32 info,
|
||||
|
@ -203,11 +206,11 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
|||
struct mt76_queue_entry *e = &q->entry[idx];
|
||||
|
||||
if (!e->skip_buf0)
|
||||
dma_unmap_single(dev->dev, e->dma_addr[0], e->dma_len[0],
|
||||
dma_unmap_single(dev->dma_dev, e->dma_addr[0], e->dma_len[0],
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (!e->skip_buf1)
|
||||
dma_unmap_single(dev->dev, e->dma_addr[1], e->dma_len[1],
|
||||
dma_unmap_single(dev->dma_dev, e->dma_addr[1], e->dma_len[1],
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
if (e->txwi == DMA_DUMMY_DATA)
|
||||
|
@ -224,7 +227,7 @@ static void
|
|||
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
wmb();
|
||||
writel(q->head, &q->regs->cpu_idx);
|
||||
Q_WRITE(dev, q, cpu_idx, q->head);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -240,7 +243,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
|
|||
if (flush)
|
||||
last = -1;
|
||||
else
|
||||
last = readl(&q->regs->dma_idx);
|
||||
last = Q_READ(dev, q, dma_idx);
|
||||
|
||||
while (q->queued > 0 && q->tail != last) {
|
||||
mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
|
||||
|
@ -252,8 +255,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
|
|||
}
|
||||
|
||||
if (!flush && q->tail == last)
|
||||
last = readl(&q->regs->dma_idx);
|
||||
|
||||
last = Q_READ(dev, q, dma_idx);
|
||||
}
|
||||
spin_unlock_bh(&q->cleanup_lock);
|
||||
|
||||
|
@ -288,7 +290,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
|||
if (info)
|
||||
*info = le32_to_cpu(desc->info);
|
||||
|
||||
dma_unmap_single(dev->dev, buf_addr, buf_len, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(dev->dma_dev, buf_addr, buf_len, DMA_FROM_DEVICE);
|
||||
e->buf = NULL;
|
||||
|
||||
return buf;
|
||||
|
@ -325,9 +327,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
|
|||
if (q->queued + 1 >= q->ndesc - 1)
|
||||
goto error;
|
||||
|
||||
addr = dma_map_single(dev->dev, skb->data, skb->len,
|
||||
addr = dma_map_single(dev->dma_dev, skb->data, skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev, addr)))
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
|
||||
goto error;
|
||||
|
||||
buf.addr = addr;
|
||||
|
@ -374,8 +376,8 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
|||
mt76_insert_hdr_pad(skb);
|
||||
|
||||
len = skb_headlen(skb);
|
||||
addr = dma_map_single(dev->dev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev, addr)))
|
||||
addr = dma_map_single(dev->dma_dev, skb->data, len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
|
||||
goto free;
|
||||
|
||||
tx_info.buf[n].addr = t->dma_addr;
|
||||
|
@ -387,9 +389,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
|||
if (n == ARRAY_SIZE(tx_info.buf))
|
||||
goto unmap;
|
||||
|
||||
addr = dma_map_single(dev->dev, iter->data, iter->len,
|
||||
addr = dma_map_single(dev->dma_dev, iter->data, iter->len,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev, addr)))
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr)))
|
||||
goto unmap;
|
||||
|
||||
tx_info.buf[n].addr = addr;
|
||||
|
@ -402,10 +404,10 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
|||
goto unmap;
|
||||
}
|
||||
|
||||
dma_sync_single_for_cpu(dev->dev, t->dma_addr, dev->drv->txwi_size,
|
||||
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
ret = dev->drv->tx_prepare_skb(dev, txwi, q->qid, wcid, sta, &tx_info);
|
||||
dma_sync_single_for_device(dev->dev, t->dma_addr, dev->drv->txwi_size,
|
||||
dma_sync_single_for_device(dev->dma_dev, t->dma_addr, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
if (ret < 0)
|
||||
goto unmap;
|
||||
|
@ -415,7 +417,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
|||
|
||||
unmap:
|
||||
for (n--; n > 0; n--)
|
||||
dma_unmap_single(dev->dev, tx_info.buf[n].addr,
|
||||
dma_unmap_single(dev->dma_dev, tx_info.buf[n].addr,
|
||||
tx_info.buf[n].len, DMA_TO_DEVICE);
|
||||
|
||||
free:
|
||||
|
@ -460,8 +462,8 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
|||
if (!buf)
|
||||
break;
|
||||
|
||||
addr = dma_map_single(dev->dev, buf, len, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dev, addr))) {
|
||||
addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
|
||||
skb_free_frag(buf);
|
||||
break;
|
||||
}
|
||||
|
@ -481,6 +483,85 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
|||
return frames;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
struct mtk_wed_device *wed = &dev->mmio.wed;
|
||||
int ret, type, ring;
|
||||
u8 flags = q->flags;
|
||||
|
||||
if (!mtk_wed_device_active(wed))
|
||||
q->flags &= ~MT_QFLAG_WED;
|
||||
|
||||
if (!(q->flags & MT_QFLAG_WED))
|
||||
return 0;
|
||||
|
||||
type = FIELD_GET(MT_QFLAG_WED_TYPE, q->flags);
|
||||
ring = FIELD_GET(MT_QFLAG_WED_RING, q->flags);
|
||||
|
||||
switch (type) {
|
||||
case MT76_WED_Q_TX:
|
||||
ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs);
|
||||
if (!ret)
|
||||
q->wed_regs = wed->tx_ring[ring].reg_base;
|
||||
break;
|
||||
case MT76_WED_Q_TXFREE:
|
||||
/* WED txfree queue needs ring to be initialized before setup */
|
||||
q->flags = 0;
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
mt76_dma_rx_fill(dev, q);
|
||||
q->flags = flags;
|
||||
|
||||
ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
|
||||
if (!ret)
|
||||
q->wed_regs = wed->txfree_ring.reg_base;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
int idx, int n_desc, int bufsize,
|
||||
u32 ring_base)
|
||||
{
|
||||
int ret, size;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
spin_lock_init(&q->cleanup_lock);
|
||||
|
||||
q->regs = dev->mmio.regs + ring_base + idx * MT_RING_SIZE;
|
||||
q->ndesc = n_desc;
|
||||
q->buf_size = bufsize;
|
||||
q->hw_idx = idx;
|
||||
|
||||
size = q->ndesc * sizeof(struct mt76_desc);
|
||||
q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
|
||||
if (!q->desc)
|
||||
return -ENOMEM;
|
||||
|
||||
size = q->ndesc * sizeof(*q->entry);
|
||||
q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
|
||||
if (!q->entry)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mt76_dma_wed_setup(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (q->flags != MT_WED_Q_TXFREE)
|
||||
mt76_dma_queue_reset(dev, q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
|
@ -562,14 +643,29 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
|
|||
static int
|
||||
mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
{
|
||||
int len, data_len, done = 0;
|
||||
int len, data_len, done = 0, dma_idx;
|
||||
struct sk_buff *skb;
|
||||
unsigned char *data;
|
||||
bool check_ddone = false;
|
||||
bool more;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
|
||||
q->flags == MT_WED_Q_TXFREE) {
|
||||
dma_idx = Q_READ(dev, q, dma_idx);
|
||||
check_ddone = true;
|
||||
}
|
||||
|
||||
while (done < budget) {
|
||||
u32 info;
|
||||
|
||||
if (check_ddone) {
|
||||
if (q->tail == dma_idx)
|
||||
dma_idx = Q_READ(dev, q, dma_idx);
|
||||
|
||||
if (q->tail == dma_idx)
|
||||
break;
|
||||
}
|
||||
|
||||
data = mt76_dma_dequeue(dev, q, false, &len, &info, &more);
|
||||
if (!data)
|
||||
break;
|
||||
|
@ -710,5 +806,8 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
|||
}
|
||||
|
||||
mt76_free_pending_txwi(dev);
|
||||
|
||||
if (mtk_wed_device_active(&dev->mmio.wed))
|
||||
mtk_wed_device_detach(&dev->mmio.wed);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_dma_cleanup);
|
||||
|
|
|
@ -248,6 +248,8 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
|
|||
vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC;
|
||||
else
|
||||
vht_cap->cap &= ~IEEE80211_VHT_CAP_TXSTBC;
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
|
||||
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < nstream)
|
||||
|
@ -323,8 +325,6 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,
|
|||
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC |
|
||||
IEEE80211_VHT_CAP_RXSTBC_1 |
|
||||
IEEE80211_VHT_CAP_SHORT_GI_80 |
|
||||
IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
|
||||
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
|
||||
(3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
|
||||
|
||||
return 0;
|
||||
|
@ -545,6 +545,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
|
|||
dev->hw = hw;
|
||||
dev->dev = pdev;
|
||||
dev->drv = drv_ops;
|
||||
dev->dma_dev = pdev;
|
||||
|
||||
phy = &dev->phy;
|
||||
phy->dev = dev;
|
||||
|
@ -579,6 +580,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
|
|||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
|
||||
INIT_LIST_HEAD(&dev->txwi_cache);
|
||||
dev->token_size = dev->drv->token_size;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
|
||||
skb_queue_head_init(&dev->rx_skb[i]);
|
||||
|
@ -1303,7 +1305,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
|||
continue;
|
||||
|
||||
mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
|
||||
mtxq->wcid = wcid;
|
||||
mtxq->wcid = wcid->idx;
|
||||
}
|
||||
|
||||
ewma_signal_init(&wcid->rssi);
|
||||
|
@ -1381,7 +1383,9 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
spin_lock_bh(&dev->status_lock);
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], NULL);
|
||||
spin_unlock_bh(&dev->status_lock);
|
||||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
|
||||
|
@ -1578,7 +1582,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
|
|||
|
||||
struct mt76_queue *
|
||||
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
|
||||
int ring_base)
|
||||
int ring_base, u32 flags)
|
||||
{
|
||||
struct mt76_queue *hwq;
|
||||
int err;
|
||||
|
@ -1587,6 +1591,8 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
|
|||
if (!hwq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hwq->flags = flags;
|
||||
|
||||
err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
#include "mt76.h"
|
||||
|
||||
struct sk_buff *
|
||||
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len)
|
||||
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len, gfp_t gfp)
|
||||
{
|
||||
const struct mt76_mcu_ops *ops = dev->mcu_ops;
|
||||
int length = ops->headroom + data_len + ops->tailroom;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(length, GFP_KERNEL);
|
||||
skb = alloc_skb(length, gfp);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
|
@ -25,7 +25,7 @@ mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
|||
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc);
|
||||
EXPORT_SYMBOL_GPL(__mt76_mcu_msg_alloc);
|
||||
|
||||
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
|
||||
unsigned long expires)
|
||||
|
|
|
@ -73,8 +73,13 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
|
|||
spin_lock_irqsave(&dev->mmio.irq_lock, flags);
|
||||
dev->mmio.irqmask &= ~clear;
|
||||
dev->mmio.irqmask |= set;
|
||||
if (addr)
|
||||
mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
|
||||
if (addr) {
|
||||
if (mtk_wed_device_active(&dev->mmio.wed))
|
||||
mtk_wed_device_irq_set_mask(&dev->mmio.wed,
|
||||
dev->mmio.irqmask);
|
||||
else
|
||||
mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/leds.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/soc/mediatek/mtk_wed.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "util.h"
|
||||
#include "testmode.h"
|
||||
|
@ -26,6 +27,16 @@
|
|||
|
||||
#define MT76_TOKEN_FREE_THR 64
|
||||
|
||||
#define MT_QFLAG_WED_RING GENMASK(1, 0)
|
||||
#define MT_QFLAG_WED_TYPE GENMASK(3, 2)
|
||||
#define MT_QFLAG_WED BIT(4)
|
||||
|
||||
#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
|
||||
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
|
||||
FIELD_PREP(MT_QFLAG_WED_RING, _n))
|
||||
#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
|
||||
#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
|
||||
|
||||
struct mt76_dev;
|
||||
struct mt76_phy;
|
||||
struct mt76_wcid;
|
||||
|
@ -42,6 +53,11 @@ enum mt76_bus_type {
|
|||
MT76_BUS_SDIO,
|
||||
};
|
||||
|
||||
enum mt76_wed_type {
|
||||
MT76_WED_Q_TX,
|
||||
MT76_WED_Q_TXFREE,
|
||||
};
|
||||
|
||||
struct mt76_bus_ops {
|
||||
u32 (*rr)(struct mt76_dev *dev, u32 offset);
|
||||
void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
|
||||
|
@ -170,6 +186,9 @@ struct mt76_queue {
|
|||
u8 buf_offset;
|
||||
u8 hw_idx;
|
||||
u8 qid;
|
||||
u8 flags;
|
||||
|
||||
u32 wed_regs;
|
||||
|
||||
dma_addr_t desc_dma;
|
||||
struct sk_buff *rx_head;
|
||||
|
@ -275,7 +294,7 @@ struct mt76_wcid {
|
|||
};
|
||||
|
||||
struct mt76_txq {
|
||||
struct mt76_wcid *wcid;
|
||||
u16 wcid;
|
||||
|
||||
u16 agg_ssn;
|
||||
bool send_bar;
|
||||
|
@ -537,6 +556,8 @@ struct mt76_mmio {
|
|||
void __iomem *regs;
|
||||
spinlock_t irq_lock;
|
||||
u32 irqmask;
|
||||
|
||||
struct mtk_wed_device wed;
|
||||
};
|
||||
|
||||
struct mt76_rx_status {
|
||||
|
@ -698,6 +719,7 @@ struct mt76_dev {
|
|||
const struct mt76_driver_ops *drv;
|
||||
const struct mt76_mcu_ops *mcu_ops;
|
||||
struct device *dev;
|
||||
struct device *dma_dev;
|
||||
|
||||
struct mt76_mcu mcu;
|
||||
|
||||
|
@ -718,7 +740,9 @@ struct mt76_dev {
|
|||
|
||||
spinlock_t token_lock;
|
||||
struct idr token;
|
||||
int token_count;
|
||||
u16 wed_token_count;
|
||||
u16 token_count;
|
||||
u16 token_size;
|
||||
|
||||
wait_queue_head_t tx_wait;
|
||||
/* spinclock used to protect wcid pktid linked list */
|
||||
|
@ -727,7 +751,7 @@ struct mt76_dev {
|
|||
u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
|
||||
u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
|
||||
|
||||
u32 vif_mask;
|
||||
u64 vif_mask;
|
||||
|
||||
struct mt76_wcid global_wcid;
|
||||
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
|
||||
|
@ -942,14 +966,14 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
|
|||
|
||||
struct mt76_queue *
|
||||
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
|
||||
int ring_base);
|
||||
int ring_base, u32 flags);
|
||||
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
|
||||
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
|
||||
int n_desc, int ring_base)
|
||||
int n_desc, int ring_base, u32 flags)
|
||||
{
|
||||
struct mt76_queue *q;
|
||||
|
||||
q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base);
|
||||
q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags);
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
|
@ -964,7 +988,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
|
|||
{
|
||||
struct mt76_queue *q;
|
||||
|
||||
q = mt76_init_queue(dev, qid, idx, n_desc, ring_base);
|
||||
q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0);
|
||||
if (IS_ERR(q))
|
||||
return PTR_ERR(q);
|
||||
|
||||
|
@ -1321,8 +1345,15 @@ int mt76s_rd_rp(struct mt76_dev *dev, u32 base,
|
|||
struct mt76_reg_pair *data, int len);
|
||||
|
||||
struct sk_buff *
|
||||
__mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len, gfp_t gfp);
|
||||
static inline struct sk_buff *
|
||||
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
|
||||
int data_len);
|
||||
int data_len)
|
||||
{
|
||||
return __mt76_mcu_msg_alloc(dev, data, data_len, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
|
||||
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
|
||||
unsigned long expires);
|
||||
|
@ -1380,8 +1411,7 @@ mt76_token_get(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
|
|||
int token;
|
||||
|
||||
spin_lock_bh(&dev->token_lock);
|
||||
token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size,
|
||||
GFP_ATOMIC);
|
||||
token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
|
||||
spin_unlock_bh(&dev->token_lock);
|
||||
|
||||
return token;
|
||||
|
|
|
@ -82,12 +82,12 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
|||
__skb_queue_head_init(&data.q);
|
||||
|
||||
q = dev->mphy.q_tx[MT_TXQ_BEACON];
|
||||
spin_lock_bh(&q->lock);
|
||||
spin_lock(&q->lock);
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7603_update_beacon_iter, dev);
|
||||
mt76_queue_kick(dev, q);
|
||||
spin_unlock_bh(&q->lock);
|
||||
spin_unlock(&q->lock);
|
||||
|
||||
/* Flush all previous CAB queue packets */
|
||||
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
|
||||
|
@ -117,7 +117,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
|||
mt76_skb_set_moredata(data.tail[i], false);
|
||||
}
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
spin_lock(&q->lock);
|
||||
while ((skb = __skb_dequeue(&data.q)) != NULL) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
|
@ -126,7 +126,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
|||
mt76_tx_queue_skb(dev, q, skb, &mvif->sta.wcid, NULL);
|
||||
}
|
||||
mt76_queue_kick(dev, q);
|
||||
spin_unlock_bh(&q->lock);
|
||||
spin_unlock(&q->lock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data.count); i++)
|
||||
mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i),
|
||||
|
|
|
@ -173,13 +173,13 @@ int mt7603_dma_init(struct mt7603_dev *dev)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
|
||||
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
|
||||
MT7603_TX_RING_SIZE, MT_TX_RING_BASE);
|
||||
MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
|
||||
MT7603_PSD_RING_SIZE, MT_TX_RING_BASE);
|
||||
MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -189,12 +189,12 @@ int mt7603_dma_init(struct mt7603_dev *dev)
|
|||
return ret;
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN,
|
||||
MT_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC,
|
||||
MT_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -223,8 +223,8 @@ int mt7603_dma_init(struct mt7603_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7603_poll_tx, NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7603_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -44,7 +44,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
mvif->idx = ffs(~dev->mt76.vif_mask) - 1;
|
||||
mvif->idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mvif->idx >= MT7603_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
|
@ -65,7 +65,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
}
|
||||
|
||||
idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
|
||||
dev->mt76.vif_mask |= BIT(mvif->idx);
|
||||
dev->mt76.vif_mask |= BIT_ULL(mvif->idx);
|
||||
INIT_LIST_HEAD(&mvif->sta.poll_list);
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
|
@ -75,7 +75,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
|
||||
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = &mvif->sta.wcid;
|
||||
mtxq->wcid = idx;
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
|
||||
out:
|
||||
|
@ -106,7 +106,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
spin_unlock_bh(&dev->sta_poll_lock);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||
|
|
|
@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
|
|||
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
|
||||
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
|
||||
MT7615_TX_RING_SIZE / 2,
|
||||
MT_TX_RING_BASE);
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT,
|
||||
MT7615_TX_MGMT_RING_SIZE,
|
||||
MT_TX_RING_BASE);
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
|
|||
return mt7622_init_tx_queues_multi(dev);
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, 0, 0, MT7615_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE);
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -284,8 +284,8 @@ int mt7615_dma_init(struct mt7615_dev *dev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7615_poll_tx, NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7615_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
mt76_poll(dev, MT_WPDMA_GLO_CFG,
|
||||
|
|
|
@ -194,7 +194,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
|||
is_zero_ether_addr(vif->addr))
|
||||
phy->monitor_vif = vif;
|
||||
|
||||
mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
|
||||
mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mvif->mt76.idx >= MT7615_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
|
@ -212,7 +212,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
|||
if (ext_phy)
|
||||
mvif->mt76.wmm_idx += 2;
|
||||
|
||||
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
|
||||
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
|
@ -234,7 +234,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
|||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = &mvif->sta.wcid;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
|
||||
ret = mt7615_mcu_add_dev_info(phy, vif, true);
|
||||
|
@ -268,7 +268,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
|
||||
dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t)
|
|||
return;
|
||||
|
||||
dev->reset_state = mcu_int;
|
||||
ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
wake_up(&dev->reset_wait);
|
||||
}
|
||||
|
||||
|
|
|
@ -2185,11 +2185,8 @@ int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,
|
|||
return -ENOMEM;
|
||||
|
||||
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
|
||||
for (i = 0; i < len; i++) {
|
||||
u8 *addr = (u8 *)skb_put(skb, sizeof(__be32));
|
||||
|
||||
memcpy(addr, &info->arp_addr_list[i], sizeof(__be32));
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
skb_put_data(skb, &info->arp_addr_list[i], sizeof(__be32));
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true);
|
||||
}
|
||||
|
|
|
@ -974,7 +974,6 @@ enum {
|
|||
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
|
||||
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
|
||||
MCU_EXT_CMD_SET_SER_TRIGGER = 0x81,
|
||||
MCU_EXT_CMD_SCS_CTRL = 0x82,
|
||||
MCU_EXT_CMD_TWT_AGRT_UPDATE = 0x94,
|
||||
MCU_EXT_CMD_FW_DBG_CTRL = 0x95,
|
||||
MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
|
||||
|
|
|
@ -191,13 +191,13 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
|
|||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i),
|
||||
MT76x02_TX_RING_SIZE,
|
||||
MT_TX_RING_BASE);
|
||||
MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
|
||||
MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE);
|
||||
MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -230,8 +230,8 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt76x02_poll_tx, NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt76x02_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -292,7 +292,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
|
|||
mt76_packet_id_init(&mvif->group_wcid);
|
||||
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = &mvif->group_wcid;
|
||||
rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
|
||||
mtxq->wcid = MT_VIF_WCID(idx);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -327,11 +328,11 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
idx += 8;
|
||||
|
||||
/* vif is already set or idx is 8 for AP/Mesh/... */
|
||||
if (dev->mt76.vif_mask & BIT(idx) ||
|
||||
if (dev->mt76.vif_mask & BIT_ULL(idx) ||
|
||||
(vif->type != NL80211_IFTYPE_STATION && idx > 7))
|
||||
return -EBUSY;
|
||||
|
||||
dev->mt76.vif_mask |= BIT(idx);
|
||||
dev->mt76.vif_mask |= BIT_ULL(idx);
|
||||
|
||||
mt76x02_vif_init(dev, vif, idx);
|
||||
return 0;
|
||||
|
@ -344,7 +345,8 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
|
|||
struct mt76x02_dev *dev = hw->priv;
|
||||
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->idx);
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
|
||||
rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
|
||||
|
|
|
@ -44,35 +44,113 @@ mt7915_implicit_txbf_get(void *data, u64 *val)
|
|||
DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
|
||||
mt7915_implicit_txbf_set, "%lld\n");
|
||||
|
||||
/* test knob of system layer 1/2 error recovery */
|
||||
static int mt7915_ser_trigger_set(void *data, u64 val)
|
||||
/* test knob of system error recovery */
|
||||
static ssize_t
|
||||
mt7915_fw_ser_set(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
enum {
|
||||
SER_SET_RECOVER_L1 = 1,
|
||||
SER_SET_RECOVER_L2,
|
||||
SER_ENABLE = 2,
|
||||
SER_RECOVER
|
||||
};
|
||||
struct mt7915_dev *dev = data;
|
||||
struct mt7915_phy *phy = file->private_data;
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
char buf[16];
|
||||
int ret = 0;
|
||||
u16 val;
|
||||
|
||||
if (count >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, user_buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
if (count && buf[count - 1] == '\n')
|
||||
buf[count - 1] = '\0';
|
||||
else
|
||||
buf[count] = '\0';
|
||||
|
||||
if (kstrtou16(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
switch (val) {
|
||||
case SER_QUERY:
|
||||
/* grab firmware SER stats */
|
||||
ret = mt7915_mcu_set_ser(dev, 0, 0, ext_phy);
|
||||
break;
|
||||
case SER_SET_RECOVER_L1:
|
||||
case SER_SET_RECOVER_L2:
|
||||
ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), 0);
|
||||
case SER_SET_RECOVER_L3_RX_ABORT:
|
||||
case SER_SET_RECOVER_L3_TX_ABORT:
|
||||
case SER_SET_RECOVER_L3_TX_DISABLE:
|
||||
case SER_SET_RECOVER_L3_BF:
|
||||
ret = mt7915_mcu_set_ser(dev, SER_ENABLE, BIT(val), ext_phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7915_mcu_set_ser(dev, SER_RECOVER, val, 0);
|
||||
ret = mt7915_mcu_set_ser(dev, SER_RECOVER, val, ext_phy);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
mt7915_fw_ser_get(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct mt7915_phy *phy = file->private_data;
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
char *buff;
|
||||
int desc = 0;
|
||||
ssize_t ret;
|
||||
static const size_t bufsz = 400;
|
||||
|
||||
buff = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_STATUS = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_SER_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR_1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PLE_ERR_AMSDU = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PSE_ERR = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PSE_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_PSE_ERR_1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_PSE1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR6_B0 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR6_B1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR7_B0 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
|
||||
desc += scnprintf(buff + desc, bufsz - desc,
|
||||
"::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
|
||||
mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
|
||||
kfree(buff);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_ser_trigger, NULL,
|
||||
mt7915_ser_trigger_set, "%lld\n");
|
||||
static const struct file_operations mt7915_fw_ser_ops = {
|
||||
.write = mt7915_fw_ser_set,
|
||||
.read = mt7915_fw_ser_get,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int
|
||||
mt7915_radar_trigger(void *data, u64 val)
|
||||
|
@ -95,7 +173,7 @@ mt7915_muru_debug_set(void *data, u64 val)
|
|||
struct mt7915_dev *dev = data;
|
||||
|
||||
dev->muru_debug = val;
|
||||
mt7915_mcu_muru_debug_set(dev, data);
|
||||
mt7915_mcu_muru_debug_set(dev, dev->muru_debug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -369,20 +447,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
|
|||
bool tx, rx, en;
|
||||
int ret;
|
||||
|
||||
dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
|
||||
dev->fw.debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
|
||||
|
||||
if (dev->fw_debug_bin)
|
||||
if (dev->fw.debug_bin)
|
||||
val = 16;
|
||||
else
|
||||
val = dev->fw_debug_wm;
|
||||
val = dev->fw.debug_wm;
|
||||
|
||||
tx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(1));
|
||||
rx = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(2));
|
||||
en = dev->fw_debug_wm || (dev->fw_debug_bin & BIT(0));
|
||||
tx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(1));
|
||||
rx = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(2));
|
||||
en = dev->fw.debug_wm || (dev->fw.debug_bin & BIT(0));
|
||||
|
||||
ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) {
|
||||
if (debug == DEBUG_RPT_RX)
|
||||
|
@ -392,16 +470,20 @@ mt7915_fw_debug_wm_set(void *data, u64 val)
|
|||
|
||||
ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* WM CPU info record control */
|
||||
mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
|
||||
mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw_debug_wm);
|
||||
mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw.debug_wm);
|
||||
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
|
||||
mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
|
||||
|
||||
return 0;
|
||||
out:
|
||||
if (ret)
|
||||
dev->fw.debug_wm = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -409,7 +491,7 @@ mt7915_fw_debug_wm_get(void *data, u64 *val)
|
|||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
|
||||
*val = dev->fw_debug_wm;
|
||||
*val = dev->fw.debug_wm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -423,14 +505,19 @@ mt7915_fw_debug_wa_set(void *data, u64 val)
|
|||
struct mt7915_dev *dev = data;
|
||||
int ret;
|
||||
|
||||
dev->fw_debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
|
||||
dev->fw.debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
|
||||
|
||||
ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw_debug_wa);
|
||||
ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw.debug_wa);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_PDMA_RX,
|
||||
!!dev->fw_debug_wa, 0);
|
||||
ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
|
||||
MCU_WA_PARAM_PDMA_RX, !!dev->fw.debug_wa, 0);
|
||||
out:
|
||||
if (ret)
|
||||
dev->fw.debug_wa = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -438,7 +525,7 @@ mt7915_fw_debug_wa_get(void *data, u64 *val)
|
|||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
|
||||
*val = dev->fw_debug_wa;
|
||||
*val = dev->fw.debug_wa;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -485,11 +572,11 @@ mt7915_fw_debug_bin_set(void *data, u64 val)
|
|||
if (!dev->relay_fwlog)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->fw_debug_bin = val;
|
||||
dev->fw.debug_bin = val;
|
||||
|
||||
relay_reset(dev->relay_fwlog);
|
||||
|
||||
return mt7915_fw_debug_wm_set(dev, dev->fw_debug_wm);
|
||||
return mt7915_fw_debug_wm_set(dev, dev->fw.debug_wm);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -497,7 +584,7 @@ mt7915_fw_debug_bin_get(void *data, u64 *val)
|
|||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
|
||||
*val = dev->fw_debug_bin;
|
||||
*val = dev->fw.debug_bin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -510,7 +597,13 @@ mt7915_fw_util_wm_show(struct seq_file *file, void *data)
|
|||
{
|
||||
struct mt7915_dev *dev = file->private;
|
||||
|
||||
if (dev->fw_debug_wm) {
|
||||
seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WM_MCU_PC));
|
||||
seq_printf(file, "Exception state: 0x%x\n",
|
||||
is_mt7915(&dev->mt76) ?
|
||||
(u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(15, 8)) :
|
||||
(u32)mt76_get_field(dev, MT_FW_EXCEPTION, GENMASK(7, 0)));
|
||||
|
||||
if (dev->fw.debug_wm) {
|
||||
seq_printf(file, "Busy: %u%% Peak busy: %u%%\n",
|
||||
mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT),
|
||||
mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT));
|
||||
|
@ -529,7 +622,9 @@ mt7915_fw_util_wa_show(struct seq_file *file, void *data)
|
|||
{
|
||||
struct mt7915_dev *dev = file->private;
|
||||
|
||||
if (dev->fw_debug_wa)
|
||||
seq_printf(file, "Program counter: 0x%x\n", mt76_rr(dev, MT_WA_MCU_PC));
|
||||
|
||||
if (dev->fw.debug_wa)
|
||||
return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY),
|
||||
MCU_WA_PARAM_CPU_UTIL, 0, 0);
|
||||
|
||||
|
@ -867,6 +962,36 @@ mt7915_twt_stats(struct seq_file *s, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* The index of RF registers use the generic regidx, combined with two parts:
|
||||
* WF selection [31:28] and offset [27:0].
|
||||
*/
|
||||
static int
|
||||
mt7915_rf_regval_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
u32 regval;
|
||||
int ret;
|
||||
|
||||
ret = mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, ®val, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = le32_to_cpu(regval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_rf_regval_set(void *data, u64 val)
|
||||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
|
||||
return mt7915_mcu_rf_regval(dev, dev->mt76.debugfs_reg, (u32 *)&val, true);
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7915_rf_regval_get,
|
||||
mt7915_rf_regval_set, "0x%08llx\n");
|
||||
|
||||
int mt7915_init_debugfs(struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
|
@ -884,6 +1009,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
|
|||
debugfs_create_file("xmit-queues", 0400, dir, phy,
|
||||
&mt7915_xmit_queues_fops);
|
||||
debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
|
||||
debugfs_create_file("fw_ser", 0600, dir, phy, &mt7915_fw_ser_ops);
|
||||
debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
|
||||
debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
|
||||
debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
|
||||
|
@ -897,7 +1023,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
|
|||
&mt7915_rate_txpower_fops);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
|
||||
mt7915_twt_stats);
|
||||
debugfs_create_file("ser_trigger", 0200, dir, dev, &fops_ser_trigger);
|
||||
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
|
||||
|
||||
if (!dev->dbdc_support || phy->band_idx) {
|
||||
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
|
||||
&dev->hw_pattern);
|
||||
|
|
|
@ -5,11 +5,19 @@
|
|||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
|
||||
static int
|
||||
mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int i, err;
|
||||
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base);
|
||||
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
|
||||
ring_base = MT_WED_TX_RING_BASE;
|
||||
idx -= MT_TXQ_ID(0);
|
||||
}
|
||||
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, ring_base,
|
||||
MT_WED_Q_TX(idx));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -318,14 +326,23 @@ static int mt7915_dma_enable(struct mt7915_dev *dev)
|
|||
if (dev->dbdc_support || dev->phy.band_idx)
|
||||
irq_mask |= MT_INT_BAND1_RX_DONE;
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
u32 wed_irq_mask = irq_mask;
|
||||
|
||||
wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
|
||||
mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask);
|
||||
mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask);
|
||||
}
|
||||
|
||||
mt7915_irq_enable(dev, irq_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7915_dma_init(struct mt7915_dev *dev)
|
||||
int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
u32 wa_rx_base, wa_rx_idx;
|
||||
u32 hif1_ofs = 0;
|
||||
int ret;
|
||||
|
||||
|
@ -338,6 +355,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
|
|||
|
||||
mt7915_dma_disable(dev, true);
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
|
||||
|
||||
mt76_wr(dev, MT_WFDMA_WED_RING_CONTROL,
|
||||
FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX0, 18) |
|
||||
FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_TX1, 19) |
|
||||
FIELD_PREP(MT_WFDMA_WED_RING_CONTROL_RX1, 1));
|
||||
} else {
|
||||
mt76_clear(dev, MT_WFDMA_HOST_CONFIG, MT_WFDMA_HOST_CONFIG_WED);
|
||||
}
|
||||
|
||||
/* init tx queue */
|
||||
ret = mt7915_init_tx_queues(&dev->phy,
|
||||
MT_TXQ_ID(dev->phy.band_idx),
|
||||
|
@ -346,6 +374,15 @@ int mt7915_dma_init(struct mt7915_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (phy2) {
|
||||
ret = mt7915_init_tx_queues(phy2,
|
||||
MT_TXQ_ID(phy2->band_idx),
|
||||
MT7915_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(1));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* command to WM */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM,
|
||||
MT_MCUQ_ID(MT_MCUQ_WM),
|
||||
|
@ -380,11 +417,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
|
|||
return ret;
|
||||
|
||||
/* event from WA */
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
wa_rx_base = MT_WED_RX_RING_BASE;
|
||||
wa_rx_idx = MT7915_RXQ_MCU_WA;
|
||||
dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
|
||||
} else {
|
||||
wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA);
|
||||
wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA);
|
||||
}
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
|
||||
MT_RXQ_ID(MT_RXQ_MCU_WA),
|
||||
MT7915_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
|
||||
wa_rx_idx, MT7915_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, wa_rx_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -434,8 +477,8 @@ int mt7915_dma_init(struct mt7915_dev *dev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7915_poll_tx, NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7915_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7915_dma_enable(dev);
|
||||
|
|
|
@ -152,6 +152,8 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
|
|||
phy->mt76->cap.has_2ghz = true;
|
||||
return;
|
||||
}
|
||||
} else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) {
|
||||
val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
|
|
|
@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);
|
||||
|
||||
if (!mdev->dev->of_node ||
|
||||
!of_property_read_bool(mdev->dev->of_node,
|
||||
|
@ -450,6 +452,9 @@ static void mt7915_mac_init(struct mt7915_dev *dev)
|
|||
|
||||
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, rx_len);
|
||||
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
|
||||
|
||||
/* enable hardware de-agg */
|
||||
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
|
||||
|
||||
|
@ -484,21 +489,18 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
|
|||
return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE);
|
||||
}
|
||||
|
||||
static int mt7915_register_ext_phy(struct mt7915_dev *dev)
|
||||
static struct mt7915_phy *
|
||||
mt7915_alloc_ext_phy(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt7915_phy *phy = mt7915_ext_phy(dev);
|
||||
struct mt7915_phy *phy;
|
||||
struct mt76_phy *mphy;
|
||||
int ret;
|
||||
|
||||
if (!dev->dbdc_support)
|
||||
return 0;
|
||||
|
||||
if (phy)
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
|
||||
if (!mphy)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
phy = mphy->priv;
|
||||
phy->dev = dev;
|
||||
|
@ -507,6 +509,15 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
|
|||
/* Bind main phy to band0 and ext_phy to band1 for dbdc case */
|
||||
phy->band_idx = 1;
|
||||
|
||||
return phy;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
int ret;
|
||||
|
||||
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
|
||||
|
||||
mt7915_eeprom_parse_hw_cap(dev, phy);
|
||||
|
@ -526,29 +537,22 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
|
|||
|
||||
/* init wiphy according to mphy and phy */
|
||||
mt7915_init_wiphy(mphy->hw);
|
||||
ret = mt7915_init_tx_queues(phy, MT_TXQ_ID(phy->band_idx),
|
||||
MT7915_TX_RING_SIZE,
|
||||
MT_TXQ_RING_BASE(1));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt76_register_phy(mphy, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
ret = mt7915_thermal_init(phy);
|
||||
if (ret)
|
||||
goto error;
|
||||
goto unreg;
|
||||
|
||||
ret = mt7915_init_debugfs(phy);
|
||||
if (ret)
|
||||
goto error;
|
||||
mt7915_init_debugfs(phy);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ieee80211_free_hw(mphy->hw);
|
||||
unreg:
|
||||
mt76_unregister_phy(mphy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -565,7 +569,7 @@ static void mt7915_init_work(struct work_struct *work)
|
|||
mt7915_txbf_init(dev);
|
||||
}
|
||||
|
||||
static void mt7915_wfsys_reset(struct mt7915_dev *dev)
|
||||
void mt7915_wfsys_reset(struct mt7915_dev *dev)
|
||||
{
|
||||
#define MT_MCU_DUMMY_RANDOM GENMASK(15, 0)
|
||||
#define MT_MCU_DUMMY_DEFAULT GENMASK(31, 16)
|
||||
|
@ -645,36 +649,25 @@ static bool mt7915_band_config(struct mt7915_dev *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mt7915_init_hardware(struct mt7915_dev *dev)
|
||||
static int
|
||||
mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
|
||||
{
|
||||
int ret, idx;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
|
||||
|
||||
INIT_WORK(&dev->init_work, mt7915_init_work);
|
||||
|
||||
dev->dbdc_support = mt7915_band_config(dev);
|
||||
|
||||
/* If MCU was already running, it is likely in a bad state */
|
||||
if (mt76_get_field(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE) >
|
||||
FW_STATE_FW_DOWNLOAD)
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
ret = mt7915_dma_init(dev);
|
||||
ret = mt7915_dma_init(dev, phy2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
|
||||
ret = mt7915_mcu_init(dev);
|
||||
if (ret) {
|
||||
/* Reset and try again */
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
ret = mt7915_mcu_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7915_eeprom_init(dev);
|
||||
if (ret < 0)
|
||||
|
@ -814,7 +807,7 @@ static void
|
|||
mt7915_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
|
@ -1048,9 +1041,22 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
|
|||
ieee80211_free_hw(mphy->hw);
|
||||
}
|
||||
|
||||
static void mt7915_stop_hardware(struct mt7915_dev *dev)
|
||||
{
|
||||
mt7915_mcu_exit(dev);
|
||||
mt7915_tx_token_put(dev);
|
||||
mt7915_dma_cleanup(dev);
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
|
||||
if (is_mt7986(&dev->mt76))
|
||||
mt7986_wmac_disable(dev);
|
||||
}
|
||||
|
||||
|
||||
int mt7915_register_device(struct mt7915_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt7915_phy *phy2;
|
||||
int ret;
|
||||
|
||||
dev->phy.dev = dev;
|
||||
|
@ -1066,9 +1072,15 @@ int mt7915_register_device(struct mt7915_dev *dev)
|
|||
init_waitqueue_head(&dev->reset_wait);
|
||||
INIT_WORK(&dev->reset_work, mt7915_mac_reset_work);
|
||||
|
||||
ret = mt7915_init_hardware(dev);
|
||||
dev->dbdc_support = mt7915_band_config(dev);
|
||||
|
||||
phy2 = mt7915_alloc_ext_phy(dev);
|
||||
if (IS_ERR(phy2))
|
||||
return PTR_ERR(phy2);
|
||||
|
||||
ret = mt7915_init_hardware(dev, phy2);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto free_phy2;
|
||||
|
||||
mt7915_init_wiphy(hw);
|
||||
|
||||
|
@ -1085,19 +1097,34 @@ int mt7915_register_device(struct mt7915_dev *dev)
|
|||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
return ret;
|
||||
goto stop_hw;
|
||||
|
||||
ret = mt7915_thermal_init(&dev->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto unreg_dev;
|
||||
|
||||
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
|
||||
|
||||
ret = mt7915_register_ext_phy(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (phy2) {
|
||||
ret = mt7915_register_ext_phy(dev, phy2);
|
||||
if (ret)
|
||||
goto unreg_thermal;
|
||||
}
|
||||
|
||||
return mt7915_init_debugfs(&dev->phy);
|
||||
mt7915_init_debugfs(&dev->phy);
|
||||
|
||||
return 0;
|
||||
|
||||
unreg_thermal:
|
||||
mt7915_unregister_thermal(&dev->phy);
|
||||
unreg_dev:
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
stop_hw:
|
||||
mt7915_stop_hardware(dev);
|
||||
free_phy2:
|
||||
if (phy2)
|
||||
ieee80211_free_hw(phy2->mt76->hw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mt7915_unregister_device(struct mt7915_dev *dev)
|
||||
|
@ -1105,13 +1132,7 @@ void mt7915_unregister_device(struct mt7915_dev *dev)
|
|||
mt7915_unregister_ext_phy(dev);
|
||||
mt7915_unregister_thermal(&dev->phy);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7915_mcu_exit(dev);
|
||||
mt7915_tx_token_put(dev);
|
||||
mt7915_dma_cleanup(dev);
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
|
||||
if (is_mt7986(&dev->mt76))
|
||||
mt7986_wmac_disable(dev);
|
||||
mt7915_stop_hardware(dev);
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ mt7915_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
|
|||
}
|
||||
|
||||
static void
|
||||
mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
||||
mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
|
||||
{
|
||||
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
|
||||
static const struct ieee80211_radiotap_he known = {
|
||||
|
@ -474,10 +474,10 @@ static int
|
|||
mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
|
||||
struct mt76_rx_status *status,
|
||||
struct ieee80211_supported_band *sband,
|
||||
__le32 *rxv)
|
||||
__le32 *rxv, u8 *mode)
|
||||
{
|
||||
u32 v0, v2;
|
||||
u8 stbc, gi, bw, dcm, mode, nss;
|
||||
u8 stbc, gi, bw, dcm, nss;
|
||||
int i, idx;
|
||||
bool cck = false;
|
||||
|
||||
|
@ -490,18 +490,18 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
|
|||
if (!is_mt7915(&dev->mt76)) {
|
||||
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
|
||||
gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v0);
|
||||
mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
*mode = FIELD_GET(MT_PRXV_TX_MODE, v0);
|
||||
dcm = FIELD_GET(MT_PRXV_DCM, v0);
|
||||
bw = FIELD_GET(MT_PRXV_FRAME_MODE, v0);
|
||||
} else {
|
||||
stbc = FIELD_GET(MT_CRXV_HT_STBC, v2);
|
||||
gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2);
|
||||
mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
|
||||
*mode = FIELD_GET(MT_CRXV_TX_MODE, v2);
|
||||
dcm = !!(idx & GENMASK(3, 0) & MT_PRXV_TX_DCM);
|
||||
bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
switch (*mode) {
|
||||
case MT_PHY_TYPE_CCK:
|
||||
cck = true;
|
||||
fallthrough;
|
||||
|
@ -521,7 +521,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
|
|||
status->encoding = RX_ENC_VHT;
|
||||
if (gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
if (i > 9)
|
||||
if (i > 11)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
|
@ -546,7 +546,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
|
|||
case IEEE80211_STA_RX_BW_20:
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
if (mode & MT_PHY_TYPE_HE_EXT_SU &&
|
||||
if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
|
||||
(idx & MT_PRXV_TX_ER_SU_106T)) {
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
status->he_ru =
|
||||
|
@ -566,7 +566,7 @@ mt7915_mac_fill_rx_rate(struct mt7915_dev *dev,
|
|||
}
|
||||
|
||||
status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;
|
||||
if (mode < MT_PHY_TYPE_HE_SU && gi)
|
||||
if (*mode < MT_PHY_TYPE_HE_SU && gi)
|
||||
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
|
||||
|
||||
return 0;
|
||||
|
@ -581,7 +581,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
struct ieee80211_supported_band *sband;
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
__le32 *rxv = NULL;
|
||||
u32 mode = 0;
|
||||
u32 rxd0 = le32_to_cpu(rxd[0]);
|
||||
u32 rxd1 = le32_to_cpu(rxd[1]);
|
||||
u32 rxd2 = le32_to_cpu(rxd[2]);
|
||||
|
@ -590,10 +589,10 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
|
||||
bool unicast, insert_ccmp_hdr = false;
|
||||
u8 remove_pad, amsdu_info;
|
||||
u8 mode = 0, qos_ctl = 0;
|
||||
bool hdr_trans;
|
||||
u16 hdr_gap;
|
||||
u16 seq_ctrl = 0;
|
||||
u8 qos_ctl = 0;
|
||||
__le16 fc = 0;
|
||||
int idx;
|
||||
|
||||
|
@ -766,7 +765,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) {
|
||||
ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv);
|
||||
ret = mt7915_mac_fill_rx_rate(dev, status, sband, rxv,
|
||||
&mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -837,10 +837,6 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
if (!status->wcid || !ieee80211_is_data_qos(fc))
|
||||
return 0;
|
||||
|
||||
/* drop no data frame */
|
||||
if (fc & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))
|
||||
return -EINVAL;
|
||||
|
||||
status->aggr = unicast &&
|
||||
!ieee80211_is_qos_nullfunc(fc);
|
||||
status->qos_ctl = qos_ctl;
|
||||
|
@ -864,8 +860,11 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
int i;
|
||||
|
||||
band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX);
|
||||
if (band_idx && !phy->band_idx)
|
||||
if (band_idx && !phy->band_idx) {
|
||||
phy = mt7915_ext_phy(dev);
|
||||
if (!phy)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rcpi = le32_to_cpu(rxv[6]);
|
||||
ib_rssi = le32_to_cpu(rxv[7]);
|
||||
|
@ -890,8 +889,8 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
|
|||
|
||||
phy->test.last_freq_offset = foe;
|
||||
phy->test.last_snr = snr;
|
||||
out:
|
||||
#endif
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
@ -1017,6 +1016,7 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
|
|||
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 fc_type, fc_stype;
|
||||
u16 ethertype;
|
||||
bool wmm = false;
|
||||
u32 val;
|
||||
|
||||
|
@ -1030,7 +1030,8 @@ mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
|
|||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
|
||||
if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN)
|
||||
ethertype = get_unaligned_be16(&skb->data[12]);
|
||||
if (ethertype >= ETH_P_802_3_MIN)
|
||||
val |= MT_TXD1_ETH_802_3;
|
||||
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
@ -1176,7 +1177,7 @@ out:
|
|||
|
||||
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, bool beacon)
|
||||
struct ieee80211_key_conf *key, u32 changed)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
|
@ -1187,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|||
bool mcast = false;
|
||||
u16 tx_count = 15;
|
||||
u32 val;
|
||||
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED));
|
||||
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY));
|
||||
|
||||
if (vif) {
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
|
@ -1199,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|||
if (ext_phy && dev->mt76.phy2)
|
||||
mphy = dev->mt76.phy2;
|
||||
|
||||
if (beacon) {
|
||||
if (inband_disc) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_ALTX0;
|
||||
} else if (beacon) {
|
||||
p_fmt = MT_TX_TYPE_FW;
|
||||
q_idx = MT_LMAC_BCN0;
|
||||
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
||||
|
@ -1307,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
return id;
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
|
||||
false);
|
||||
mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0);
|
||||
|
||||
txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
|
@ -1347,6 +1354,29 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
|
||||
{
|
||||
struct mt7915_txp *txp = ptr + MT_TXD_SIZE;
|
||||
__le32 *txwi = ptr;
|
||||
u32 val;
|
||||
|
||||
memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
|
||||
|
||||
val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
|
||||
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
|
||||
txwi[0] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD1_LONG_FORMAT |
|
||||
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
|
||||
txp->token = cpu_to_le16(token_id);
|
||||
txp->nbuf = 1;
|
||||
txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
|
||||
|
||||
return MT_TXD_SIZE + sizeof(*txp);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
{
|
||||
|
@ -1380,7 +1410,7 @@ mt7915_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
|||
|
||||
txp = mt7915_txwi_to_txp(dev, t);
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
|
||||
dma_unmap_single(dev->dma_dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
|
@ -1389,6 +1419,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
|
|||
struct ieee80211_sta *sta, struct list_head *free_list)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt7915_sta *msta;
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txwi;
|
||||
u16 wcid_idx;
|
||||
|
@ -1401,13 +1432,24 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
|
|||
if (sta) {
|
||||
wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
wcid_idx = wcid->idx;
|
||||
|
||||
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7915_tx_check_aggr(sta, txwi);
|
||||
} else {
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]);
|
||||
|
||||
if (wcid && wcid->sta) {
|
||||
msta = container_of(wcid, struct mt7915_sta, wcid);
|
||||
sta = container_of((void *)msta, struct ieee80211_sta,
|
||||
drv_priv);
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
if (list_empty(&msta->poll_list))
|
||||
list_add_tail(&msta->poll_list, &dev->sta_poll_list);
|
||||
spin_unlock_bh(&dev->sta_poll_lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7915_tx_check_aggr(sta, txwi);
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
|
||||
out:
|
||||
|
@ -1416,20 +1458,10 @@ out:
|
|||
}
|
||||
|
||||
static void
|
||||
mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
||||
mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt7915_tx_free *free = (struct mt7915_tx_free *)data;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_phy *mphy_ext = mdev->phy2;
|
||||
struct mt76_txwi_cache *txwi;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
LIST_HEAD(free_list);
|
||||
struct sk_buff *skb, *tmp;
|
||||
void *end = data + len;
|
||||
bool v3, wake = false;
|
||||
u16 total, count = 0;
|
||||
u32 txd = le32_to_cpu(free->txd);
|
||||
__le32 *cur_info;
|
||||
|
||||
/* clean DMA queues and unmap buffers first */
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
|
||||
|
@ -1438,6 +1470,42 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
|||
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_PSD], false);
|
||||
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mac_tx_free_done(struct mt7915_dev *dev,
|
||||
struct list_head *free_list, bool wake)
|
||||
{
|
||||
struct sk_buff *skb, *tmp;
|
||||
|
||||
mt7915_mac_sta_poll(dev);
|
||||
|
||||
if (wake)
|
||||
mt76_set_tx_blocked(&dev->mt76, false);
|
||||
|
||||
mt76_worker_schedule(&dev->mt76.tx_worker);
|
||||
|
||||
list_for_each_entry_safe(skb, tmp, free_list, list) {
|
||||
skb_list_del_init(skb);
|
||||
napi_consume_skb(skb, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
||||
{
|
||||
struct mt7915_tx_free *free = (struct mt7915_tx_free *)data;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_txwi_cache *txwi;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
LIST_HEAD(free_list);
|
||||
void *end = data + len;
|
||||
bool v3, wake = false;
|
||||
u16 total, count = 0;
|
||||
u32 txd = le32_to_cpu(free->txd);
|
||||
__le32 *cur_info;
|
||||
|
||||
mt7915_mac_tx_free_prepare(dev);
|
||||
|
||||
total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
|
||||
|
@ -1491,17 +1559,38 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
|||
}
|
||||
}
|
||||
|
||||
mt7915_mac_sta_poll(dev);
|
||||
mt7915_mac_tx_free_done(dev, &free_list, wake);
|
||||
}
|
||||
|
||||
if (wake)
|
||||
mt76_set_tx_blocked(&dev->mt76, false);
|
||||
static void
|
||||
mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len)
|
||||
{
|
||||
struct mt7915_tx_free *free = (struct mt7915_tx_free *)data;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
__le16 *info = (__le16 *)free->info;
|
||||
void *end = data + len;
|
||||
LIST_HEAD(free_list);
|
||||
bool wake = false;
|
||||
u8 i, count;
|
||||
|
||||
mt76_worker_schedule(&dev->mt76.tx_worker);
|
||||
mt7915_mac_tx_free_prepare(dev);
|
||||
|
||||
list_for_each_entry_safe(skb, tmp, &free_list, list) {
|
||||
skb_list_del_init(skb);
|
||||
napi_consume_skb(skb, 1);
|
||||
count = FIELD_GET(MT_TX_FREE_MSDU_CNT_V0, le16_to_cpu(free->ctrl));
|
||||
if (WARN_ON_ONCE((void *)&info[count] > end))
|
||||
return;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct mt76_txwi_cache *txwi;
|
||||
u16 msdu = le16_to_cpu(info[i]);
|
||||
|
||||
txwi = mt76_token_release(mdev, msdu, &wake);
|
||||
if (!txwi)
|
||||
continue;
|
||||
|
||||
mt7915_txwi_free(dev, txwi, NULL, &free_list);
|
||||
}
|
||||
|
||||
mt7915_mac_tx_free_done(dev, &free_list, wake);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1681,6 +1770,9 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
|
|||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7915_mac_tx_free(dev, data, len);
|
||||
return false;
|
||||
case PKT_TYPE_TXRX_NOTIFY_V0:
|
||||
mt7915_mac_tx_free_v0(dev, data, len);
|
||||
return false;
|
||||
case PKT_TYPE_TXS:
|
||||
for (rxd += 2; rxd + 8 <= end; rxd += 8)
|
||||
mt7915_mac_add_txs(dev, rxd);
|
||||
|
@ -1708,6 +1800,10 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
|||
mt7915_mac_tx_free(dev, skb->data, skb->len);
|
||||
napi_consume_skb(skb, 1);
|
||||
break;
|
||||
case PKT_TYPE_TXRX_NOTIFY_V0:
|
||||
mt7915_mac_tx_free_v0(dev, skb->data, skb->len);
|
||||
napi_consume_skb(skb, 1);
|
||||
break;
|
||||
case PKT_TYPE_RX_EVENT:
|
||||
mt7915_mcu_rx_event(dev, skb);
|
||||
break;
|
||||
|
@ -1918,7 +2014,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
|||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
|
||||
mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon,
|
||||
BSS_CHANGED_BEACON_ENABLED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2304,6 +2401,32 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
|||
}
|
||||
}
|
||||
|
||||
static void mt7915_mac_severe_check(struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
u32 trb;
|
||||
|
||||
if (!phy->omac_mask)
|
||||
return;
|
||||
|
||||
/* In rare cases, TRB pointers might be out of sync leads to RMAC
|
||||
* stopping Rx, so check status periodically to see if TRB hardware
|
||||
* requires minimal recovery.
|
||||
*/
|
||||
trb = mt76_rr(dev, MT_TRB_RXPSR0(phy->band_idx));
|
||||
|
||||
if ((FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, trb) !=
|
||||
FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, trb)) &&
|
||||
(FIELD_GET(MT_TRB_RXPSR0_RX_RMAC_PTR, phy->trb_ts) !=
|
||||
FIELD_GET(MT_TRB_RXPSR0_RX_WTBL_PTR, phy->trb_ts)) &&
|
||||
trb == phy->trb_ts)
|
||||
mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L3_RX_ABORT,
|
||||
ext_phy);
|
||||
|
||||
phy->trb_ts = trb;
|
||||
}
|
||||
|
||||
void mt7915_mac_sta_rc_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7915_dev *dev = container_of(work, struct mt7915_dev, rc_work);
|
||||
|
@ -2356,6 +2479,7 @@ void mt7915_mac_work(struct work_struct *work)
|
|||
mphy->mac_work_count = 0;
|
||||
|
||||
mt7915_mac_update_stats(phy);
|
||||
mt7915_mac_severe_check(phy);
|
||||
}
|
||||
|
||||
mutex_unlock(&mphy->dev->mutex);
|
||||
|
@ -2600,6 +2724,34 @@ static int mt7915_mac_check_twt_req(struct ieee80211_twt_setup *twt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7915_mac_twt_param_equal(struct mt7915_sta *msta,
|
||||
struct ieee80211_twt_params *twt_agrt)
|
||||
{
|
||||
u16 type = le16_to_cpu(twt_agrt->req_type);
|
||||
u8 exp;
|
||||
int i;
|
||||
|
||||
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
|
||||
for (i = 0; i < MT7915_MAX_STA_TWT_AGRT; i++) {
|
||||
struct mt7915_twt_flow *f;
|
||||
|
||||
if (!(msta->twt.flowid_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
f = &msta->twt.flow[i];
|
||||
if (f->duration == twt_agrt->min_twt_dur &&
|
||||
f->mantissa == twt_agrt->mantissa &&
|
||||
f->exp == exp &&
|
||||
f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
|
||||
f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
|
||||
f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_twt_setup *twt)
|
||||
|
@ -2625,6 +2777,12 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
|
|||
if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
|
||||
goto unlock;
|
||||
|
||||
if (twt_agrt->min_twt_dur < MT7915_MIN_TWT_DUR) {
|
||||
setup_cmd = TWT_SETUP_CMD_DICTATE;
|
||||
twt_agrt->min_twt_dur = MT7915_MIN_TWT_DUR;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
flowid = ffs(~msta->twt.flowid_mask) - 1;
|
||||
le16p_replace_bits(&twt_agrt->req_type, flowid,
|
||||
IEEE80211_TWT_REQTYPE_FLOWID);
|
||||
|
@ -2633,6 +2791,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
|
|||
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
|
||||
sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
|
||||
|
||||
if (mt7915_mac_twt_param_equal(msta, twt_agrt))
|
||||
goto unlock;
|
||||
|
||||
flow = &msta->twt.flow[flowid];
|
||||
memset(flow, 0, sizeof(*flow));
|
||||
INIT_LIST_HEAD(&flow->list);
|
||||
|
|
|
@ -24,6 +24,7 @@ enum rx_pkt_type {
|
|||
PKT_TYPE_TXRX_NOTIFY,
|
||||
PKT_TYPE_RX_EVENT,
|
||||
PKT_TYPE_RX_FW_MONITOR = 0x0c,
|
||||
PKT_TYPE_TXRX_NOTIFY_V0 = 0x18,
|
||||
};
|
||||
|
||||
/* RXD DW1 */
|
||||
|
@ -311,6 +312,7 @@ struct mt7915_tx_free {
|
|||
|
||||
#define MT_TX_FREE_VER GENMASK(18, 16)
|
||||
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
|
||||
#define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0)
|
||||
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
|
||||
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
|
||||
/* 0: success, others: dropped */
|
||||
|
|
|
@ -42,10 +42,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_scs(dev, 0, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7915_mac_enable_nf(dev, 0);
|
||||
}
|
||||
|
||||
|
@ -58,10 +54,6 @@ static int mt7915_start(struct ieee80211_hw *hw)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_scs(dev, 1, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt7915_mac_enable_nf(dev, 1);
|
||||
}
|
||||
|
||||
|
@ -174,14 +166,14 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
|
||||
mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
|
||||
mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0);
|
||||
mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0);
|
||||
mvif->bitrate_mask.control[i].he_gi = 0xff;
|
||||
mvif->bitrate_mask.control[i].he_ltf = 0xff;
|
||||
mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
|
||||
memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
|
||||
memset(mvif->bitrate_mask.control[i].ht_mcs, 0xff,
|
||||
sizeof(mvif->bitrate_mask.control[i].ht_mcs));
|
||||
memset(mvif->bitrate_mask.control[i].vht_mcs, GENMASK(15, 0),
|
||||
memset(mvif->bitrate_mask.control[i].vht_mcs, 0xff,
|
||||
sizeof(mvif->bitrate_mask.control[i].vht_mcs));
|
||||
memset(mvif->bitrate_mask.control[i].he_mcs, GENMASK(15, 0),
|
||||
memset(mvif->bitrate_mask.control[i].he_mcs, 0xff,
|
||||
sizeof(mvif->bitrate_mask.control[i].he_mcs));
|
||||
}
|
||||
}
|
||||
|
@ -204,8 +196,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
|||
is_zero_ether_addr(vif->addr))
|
||||
phy->monitor_vif = vif;
|
||||
|
||||
mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
|
||||
if (mvif->mt76.idx >= MT7915_MAX_INTERFACES) {
|
||||
mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mvif->mt76.idx >= (MT7915_MAX_INTERFACES << dev->dbdc_support)) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
|
@ -227,7 +219,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
idx = MT7915_WTBL_RESERVED - mvif->mt76.idx;
|
||||
|
@ -246,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
|||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = &mvif->sta.wcid;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_AP &&
|
||||
|
@ -290,7 +282,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
|
|||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
|
@ -630,8 +622,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
|
|||
mt7915_update_bss_color(hw, vif, &info->he_bss_color);
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
|
||||
BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY))
|
||||
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
@ -644,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
|
|||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mt7915_mcu_add_beacon(hw, vif, true);
|
||||
mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
|
@ -1381,6 +1375,39 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
static int
|
||||
mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct net_device_path_ctx *ctx,
|
||||
struct net_device_path *path)
|
||||
{
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
|
||||
if (!mtk_wed_device_active(wed))
|
||||
return -ENODEV;
|
||||
|
||||
if (msta->wcid.idx > 0xff)
|
||||
return -EIO;
|
||||
|
||||
path->type = DEV_PATH_MTK_WDMA;
|
||||
path->dev = ctx->dev;
|
||||
path->mtk_wdma.wdma_idx = wed->wdma_idx;
|
||||
path->mtk_wdma.bss = mvif->mt76.idx;
|
||||
path->mtk_wdma.wcid = msta->wcid.idx;
|
||||
path->mtk_wdma.queue = phy != &dev->phy;
|
||||
|
||||
ctx->dev = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct ieee80211_ops mt7915_ops = {
|
||||
.tx = mt7915_tx,
|
||||
.start = mt7915_start,
|
||||
|
@ -1428,4 +1455,7 @@ const struct ieee80211_ops mt7915_ops = {
|
|||
.sta_add_debugfs = mt7915_sta_add_debugfs,
|
||||
#endif
|
||||
.set_radar_background = mt7915_set_radar_background,
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
.net_fill_forward_path = mt7915_net_fill_forward_path,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -1854,7 +1854,8 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
|||
continue;
|
||||
|
||||
for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
|
||||
const u8 *data;
|
||||
const struct ieee80211_bssid_index *idx;
|
||||
const u8 *idx_ie;
|
||||
|
||||
if (sub_elem->id || sub_elem->datalen < 4)
|
||||
continue; /* not a valid BSS profile */
|
||||
|
@ -1862,14 +1863,19 @@ mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
|||
/* Find WLAN_EID_MULTI_BSSID_IDX
|
||||
* in the merged nontransmitted profile
|
||||
*/
|
||||
data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||
sub_elem->data,
|
||||
sub_elem->datalen);
|
||||
if (!data || data[1] < 1 || !data[2])
|
||||
idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||
sub_elem->data,
|
||||
sub_elem->datalen);
|
||||
if (!idx_ie || idx_ie[1] < sizeof(*idx))
|
||||
continue;
|
||||
|
||||
mbss->offset[data[2]] = cpu_to_le16(data - skb->data);
|
||||
mbss->bitmap |= cpu_to_le32(BIT(data[2]));
|
||||
idx = (void *)(idx_ie + 2);
|
||||
if (!idx->bssid_index || idx->bssid_index > 31)
|
||||
continue;
|
||||
|
||||
mbss->offset[idx->bssid_index] =
|
||||
cpu_to_le16(idx_ie - skb->data);
|
||||
mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1886,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
u8 *buf;
|
||||
int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;
|
||||
|
||||
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,
|
||||
len, &bcn->sub_ntlv, &bcn->len);
|
||||
|
||||
|
@ -1904,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
|||
|
||||
buf = (u8 *)tlv + sizeof(*cont);
|
||||
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
true);
|
||||
BSS_CHANGED_BEACON);
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
||||
|
@ -1986,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
}
|
||||
}
|
||||
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int en)
|
||||
static void
|
||||
mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct bss_info_bcn *bcn,
|
||||
u32 changed)
|
||||
{
|
||||
#define OFFLOAD_TX_MODE_SU BIT(0)
|
||||
#define OFFLOAD_TX_MODE_MU BIT(1)
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||
struct bss_info_inband_discovery *discov;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct tlv *tlv;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
u8 *buf, interval;
|
||||
int len;
|
||||
|
||||
if (changed & BSS_CHANGED_FILS_DISCOVERY &&
|
||||
vif->bss_conf.fils_discovery.max_interval) {
|
||||
interval = vif->bss_conf.fils_discovery.max_interval;
|
||||
skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
|
||||
} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
|
||||
vif->bss_conf.unsol_bcast_probe_resp_interval) {
|
||||
interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
|
||||
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->control.vif = vif;
|
||||
info->band = band;
|
||||
|
||||
if (ext_phy)
|
||||
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
|
||||
|
||||
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
|
||||
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
|
||||
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
|
||||
len, &bcn->sub_ntlv, &bcn->len);
|
||||
discov = (struct bss_info_inband_discovery *)tlv;
|
||||
discov->tx_mode = OFFLOAD_TX_MODE_SU;
|
||||
/* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
|
||||
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
|
||||
discov->tx_interval = interval;
|
||||
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
discov->enable = true;
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*discov);
|
||||
|
||||
mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
changed);
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int en, u32 changed)
|
||||
{
|
||||
#define MAX_BEACON_SIZE 512
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
|
@ -2038,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
|||
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
|
||||
changed & BSS_CHANGED_FILS_DISCOVERY)
|
||||
mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
|
||||
bcn, changed);
|
||||
|
||||
out:
|
||||
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
|
||||
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
|
||||
|
@ -2465,10 +2540,7 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
|
|||
/* force firmware operation mode into normal state,
|
||||
* which should be set before firmware download stage.
|
||||
*/
|
||||
if (is_mt7915(&dev->mt76))
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
else
|
||||
mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
|
||||
ret = mt7915_driver_own(dev, 0);
|
||||
if (ret)
|
||||
|
@ -2493,6 +2565,9 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
|
||||
mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
|
||||
|
||||
ret = mt7915_mcu_set_mwds(dev, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2583,22 +2658,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band,
|
|||
&req_mac, sizeof(req_mac), true);
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable)
|
||||
{
|
||||
struct {
|
||||
__le32 cmd;
|
||||
u8 band;
|
||||
u8 enable;
|
||||
} __packed req = {
|
||||
.cmd = cpu_to_le32(SCS_ENABLE),
|
||||
.band = band,
|
||||
.enable = enable + 1,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(SCS_CTRL), &req,
|
||||
sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *param)
|
||||
{
|
||||
struct mt7915_mcu_tx *req = (struct mt7915_mcu_tx *)param;
|
||||
|
@ -3671,3 +3730,32 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
|
|||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TWT_AGRT_UPDATE),
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
|
||||
{
|
||||
struct {
|
||||
__le32 idx;
|
||||
__le32 ofs;
|
||||
__le32 data;
|
||||
} __packed req = {
|
||||
.idx = cpu_to_le32(u32_get_bits(regidx, GENMASK(31, 28))),
|
||||
.ofs = cpu_to_le32(u32_get_bits(regidx, GENMASK(27, 0))),
|
||||
.data = set ? cpu_to_le32(*val) : 0,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
if (set)
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_REG_ACCESS),
|
||||
&req, sizeof(req), false);
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(RF_REG_ACCESS),
|
||||
&req, sizeof(req), true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = le32_to_cpu(*(__le32 *)(skb->data + 8));
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -304,16 +304,6 @@ enum mcu_mmps_mode {
|
|||
MCU_MMPS_DISABLE,
|
||||
};
|
||||
|
||||
enum {
|
||||
SCS_SEND_DATA,
|
||||
SCS_SET_MANUAL_PD_TH,
|
||||
SCS_CONFIG,
|
||||
SCS_ENABLE,
|
||||
SCS_SHOW_INFO,
|
||||
SCS_GET_GLO_ADDR,
|
||||
SCS_GET_GLO_ADDR_EVENT,
|
||||
};
|
||||
|
||||
struct bss_info_bmc_rate {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
@ -414,11 +404,23 @@ struct bss_info_bcn_cont {
|
|||
__le16 pkt_len;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct bss_info_inband_discovery {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 tx_type;
|
||||
u8 tx_mode;
|
||||
u8 tx_interval;
|
||||
u8 enable;
|
||||
__le16 rsv;
|
||||
__le16 prob_rsp_len;
|
||||
} __packed __aligned(4);
|
||||
|
||||
enum {
|
||||
BSS_INFO_BCN_CSA,
|
||||
BSS_INFO_BCN_BCC,
|
||||
BSS_INFO_BCN_MBSSID,
|
||||
BSS_INFO_BCN_CONTENT,
|
||||
BSS_INFO_BCN_DISCOV,
|
||||
BSS_INFO_BCN_MAX
|
||||
};
|
||||
|
||||
|
@ -473,6 +475,20 @@ enum {
|
|||
MURU_GET_TXC_TX_STATS = 151,
|
||||
};
|
||||
|
||||
enum {
|
||||
SER_QUERY,
|
||||
/* recovery */
|
||||
SER_SET_RECOVER_L1,
|
||||
SER_SET_RECOVER_L2,
|
||||
SER_SET_RECOVER_L3_RX_ABORT,
|
||||
SER_SET_RECOVER_L3_TX_ABORT,
|
||||
SER_SET_RECOVER_L3_TX_DISABLE,
|
||||
SER_SET_RECOVER_L3_BF,
|
||||
/* action */
|
||||
SER_ENABLE = 2,
|
||||
SER_RECOVER
|
||||
};
|
||||
|
||||
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_omac) + \
|
||||
sizeof(struct bss_info_basic) +\
|
||||
|
@ -486,6 +502,7 @@ enum {
|
|||
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_bcn_cntdwn) + \
|
||||
sizeof(struct bss_info_bcn_mbss) + \
|
||||
sizeof(struct bss_info_bcn_cont))
|
||||
sizeof(struct bss_info_bcn_cont) + \
|
||||
sizeof(struct bss_info_inband_discovery))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,8 @@ static const u32 mt7915_reg[] = {
|
|||
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
|
||||
[CBTOP1_PHY_END] = 0x77ffffff,
|
||||
[INFRA_MCU_ADDR_END] = 0x7c3fffff,
|
||||
[FW_EXCEPTION_ADDR] = 0x219848,
|
||||
[SWDEF_BASE_ADDR] = 0x41f200,
|
||||
};
|
||||
|
||||
static const u32 mt7916_reg[] = {
|
||||
|
@ -36,6 +38,8 @@ static const u32 mt7916_reg[] = {
|
|||
[WFDMA_EXT_CSR_ADDR] = 0xd7000,
|
||||
[CBTOP1_PHY_END] = 0x7fffffff,
|
||||
[INFRA_MCU_ADDR_END] = 0x7c085fff,
|
||||
[FW_EXCEPTION_ADDR] = 0x022050bc,
|
||||
[SWDEF_BASE_ADDR] = 0x411400,
|
||||
};
|
||||
|
||||
static const u32 mt7986_reg[] = {
|
||||
|
@ -50,6 +54,8 @@ static const u32 mt7986_reg[] = {
|
|||
[WFDMA_EXT_CSR_ADDR] = 0x27000,
|
||||
[CBTOP1_PHY_END] = 0x7fffffff,
|
||||
[INFRA_MCU_ADDR_END] = 0x7c085fff,
|
||||
[FW_EXCEPTION_ADDR] = 0x02204ffc,
|
||||
[SWDEF_BASE_ADDR] = 0x411400,
|
||||
};
|
||||
|
||||
static const u32 mt7915_offs[] = {
|
||||
|
@ -547,15 +553,21 @@ static void mt7915_rx_poll_complete(struct mt76_dev *mdev,
|
|||
static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct mt7915_dev *dev = from_tasklet(dev, t, irq_tasklet);
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
u32 intr, intr1, mask;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
mtk_wed_device_irq_set_mask(wed, 0);
|
||||
intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
|
||||
} else {
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
|
||||
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
|
||||
intr &= dev->mt76.mmio.irqmask;
|
||||
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
|
||||
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
|
||||
intr &= dev->mt76.mmio.irqmask;
|
||||
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
|
||||
}
|
||||
|
||||
if (dev->hif2) {
|
||||
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
|
||||
|
@ -601,7 +613,7 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
|||
mt76_wr(dev, MT_MCU_CMD, val);
|
||||
if (val & MT_MCU_CMD_ERROR_MASK) {
|
||||
dev->reset_state = val;
|
||||
ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
|
||||
queue_work(dev->mt76.wq, &dev->reset_work);
|
||||
wake_up(&dev->reset_wait);
|
||||
}
|
||||
}
|
||||
|
@ -610,10 +622,15 @@ static void mt7915_irq_tasklet(struct tasklet_struct *t)
|
|||
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct mt7915_dev *dev = dev_instance;
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
mtk_wed_device_irq_set_mask(wed, 0);
|
||||
} else {
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
|
||||
}
|
||||
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return IRQ_NONE;
|
||||
|
@ -665,8 +682,6 @@ struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
|||
|
||||
tasklet_setup(&dev->irq_tasklet, mt7915_irq_tasklet);
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
|
||||
return dev;
|
||||
|
||||
error:
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#define MT7915_MAX_TWT_AGRT 16
|
||||
#define MT7915_MAX_STA_TWT_AGRT 8
|
||||
#define MT7915_MIN_TWT_DUR 64
|
||||
#define MT7915_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 2)
|
||||
|
||||
struct mt7915_vif;
|
||||
|
@ -247,6 +248,8 @@ struct mt7915_phy {
|
|||
|
||||
u8 rdd_state;
|
||||
|
||||
u32 trb_ts;
|
||||
|
||||
u32 rx_ampdu_ts;
|
||||
u32 ampdu_ref;
|
||||
|
||||
|
@ -309,9 +312,6 @@ struct mt7915_dev {
|
|||
bool flash_mode;
|
||||
bool muru_debug;
|
||||
bool ibf;
|
||||
u8 fw_debug_wm;
|
||||
u8 fw_debug_wa;
|
||||
u8 fw_debug_bin;
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
struct rchan *relay_fwlog;
|
||||
|
@ -319,7 +319,13 @@ struct mt7915_dev {
|
|||
void *cal;
|
||||
|
||||
struct {
|
||||
u8 table_mask;
|
||||
u8 debug_wm;
|
||||
u8 debug_wa;
|
||||
u8 debug_bin;
|
||||
} fw;
|
||||
|
||||
struct {
|
||||
u16 table_mask;
|
||||
u8 n_agrt;
|
||||
} twt;
|
||||
|
||||
|
@ -429,8 +435,11 @@ static inline void mt7986_wmac_disable(struct mt7915_dev *dev)
|
|||
#endif
|
||||
struct mt7915_dev *mt7915_mmio_probe(struct device *pdev,
|
||||
void __iomem *mem_base, u32 device_id);
|
||||
void mt7915_wfsys_reset(struct mt7915_dev *dev);
|
||||
irqreturn_t mt7915_irq_handler(int irq, void *dev_instance);
|
||||
u64 __mt7915_get_tsf(struct ieee80211_hw *hw, struct mt7915_vif *mvif);
|
||||
u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
|
||||
|
||||
int mt7915_register_device(struct mt7915_dev *dev);
|
||||
void mt7915_unregister_device(struct mt7915_dev *dev);
|
||||
int mt7915_eeprom_init(struct mt7915_dev *dev);
|
||||
|
@ -440,7 +449,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
|||
struct ieee80211_channel *chan,
|
||||
u8 chain_idx);
|
||||
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
|
||||
int mt7915_dma_init(struct mt7915_dev *dev);
|
||||
int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
|
||||
void mt7915_dma_prefetch(struct mt7915_dev *dev);
|
||||
void mt7915_dma_cleanup(struct mt7915_dev *dev);
|
||||
int mt7915_mcu_init(struct mt7915_dev *dev);
|
||||
|
@ -463,7 +472,7 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
|
|||
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct cfg80211_he_bss_color *he_bss_color);
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int enable);
|
||||
int enable, u32 changed);
|
||||
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
|
@ -485,7 +494,6 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
|
|||
bool hdr_trans);
|
||||
int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
|
||||
u8 en);
|
||||
int mt7915_mcu_set_scs(struct mt7915_dev *dev, u8 band, bool enable);
|
||||
int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band);
|
||||
int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
|
||||
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
|
||||
|
@ -506,6 +514,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
|||
struct ieee80211_sta *sta, struct rate_info *rate);
|
||||
int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set);
|
||||
int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
|
||||
int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
|
||||
int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
|
||||
|
@ -550,7 +559,7 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
|
|||
void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy);
|
||||
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, bool beacon);
|
||||
struct ieee80211_key_conf *key, u32 changed);
|
||||
void mt7915_mac_set_timing(struct mt7915_phy *phy);
|
||||
int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
@ -572,7 +581,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|||
struct mt76_tx_info *tx_info);
|
||||
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
void mt7915_tx_token_put(struct mt7915_dev *dev);
|
||||
int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base);
|
||||
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb);
|
||||
bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#include "mac.h"
|
||||
#include "../trace.h"
|
||||
|
||||
static bool wed_enable = false;
|
||||
module_param(wed_enable, bool, 0644);
|
||||
|
||||
static LIST_HEAD(hif_list);
|
||||
static DEFINE_SPINLOCK(hif_lock);
|
||||
static u32 hif_idx;
|
||||
|
@ -92,12 +95,79 @@ static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
|
||||
{
|
||||
struct mt7915_dev *dev;
|
||||
int ret;
|
||||
|
||||
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
|
||||
|
||||
spin_lock_bh(&dev->mt76.token_lock);
|
||||
dev->mt76.token_size = wed->wlan.token_start;
|
||||
spin_unlock_bh(&dev->mt76.token_lock);
|
||||
|
||||
ret = wait_event_timeout(dev->mt76.tx_wait,
|
||||
!dev->mt76.wed_token_count, HZ);
|
||||
if (!ret)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
|
||||
{
|
||||
struct mt7915_dev *dev;
|
||||
|
||||
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
|
||||
|
||||
spin_lock_bh(&dev->mt76.token_lock);
|
||||
dev->mt76.token_size = MT7915_TOKEN_SIZE;
|
||||
spin_unlock_bh(&dev->mt76.token_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
|
||||
{
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
int ret;
|
||||
|
||||
if (!wed_enable)
|
||||
return 0;
|
||||
|
||||
wed->wlan.pci_dev = pdev;
|
||||
wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
|
||||
MT_WFDMA_EXT_CSR_BASE;
|
||||
wed->wlan.nbuf = 4096;
|
||||
wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
|
||||
wed->wlan.init_buf = mt7915_wed_init_buf;
|
||||
wed->wlan.offload_enable = mt7915_wed_offload_enable;
|
||||
wed->wlan.offload_disable = mt7915_wed_offload_disable;
|
||||
|
||||
if (mtk_wed_device_attach(wed) != 0)
|
||||
return 0;
|
||||
|
||||
*irq = wed->irq;
|
||||
dev->mt76.dma_dev = wed->dev;
|
||||
|
||||
ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mt7915_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct mt7915_hif *hif2 = NULL;
|
||||
struct mt7915_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
struct mt7915_hif *hif2;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
|
@ -126,19 +196,27 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
|
|||
return PTR_ERR(dev);
|
||||
|
||||
mdev = &dev->mt76;
|
||||
mt7915_wfsys_reset(dev);
|
||||
hif2 = mt7915_pci_init_hif2(pdev);
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
ret = mt7915_pci_wed_init(dev, pdev, &irq);
|
||||
if (ret < 0)
|
||||
goto free_device;
|
||||
goto free_wed_or_irq_vector;
|
||||
|
||||
if (!ret) {
|
||||
hif2 = mt7915_pci_init_hif2(pdev);
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
if (ret < 0)
|
||||
goto free_device;
|
||||
|
||||
irq = pdev->irq;
|
||||
}
|
||||
|
||||
irq = pdev->irq;
|
||||
ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
if (ret)
|
||||
goto free_irq_vector;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
goto free_wed_or_irq_vector;
|
||||
|
||||
/* master switch of PCIe tnterrupt enable */
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
|
@ -173,8 +251,11 @@ free_hif2:
|
|||
if (dev->hif2)
|
||||
put_device(dev->hif2->dev);
|
||||
devm_free_irq(mdev->dev, irq, dev);
|
||||
free_irq_vector:
|
||||
pci_free_irq_vectors(pdev);
|
||||
free_wed_or_irq_vector:
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed))
|
||||
mtk_wed_device_detach(&mdev->mmio.wed);
|
||||
else
|
||||
pci_free_irq_vectors(pdev);
|
||||
free_device:
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ enum reg_rev {
|
|||
WFDMA_EXT_CSR_ADDR,
|
||||
CBTOP1_PHY_END,
|
||||
INFRA_MCU_ADDR_END,
|
||||
FW_EXCEPTION_ADDR,
|
||||
SWDEF_BASE_ADDR,
|
||||
__MT_REG_MAX,
|
||||
};
|
||||
|
||||
|
@ -158,6 +160,9 @@ enum offs_rev {
|
|||
#define MT_MDP_DCR1 MT_MDP(0x004)
|
||||
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
|
||||
|
||||
#define MT_MDP_DCR2 MT_MDP(0x0e8)
|
||||
#define MT_MDP_DCR2_RX_TRANS_SHORT BIT(2)
|
||||
|
||||
#define MT_MDP_BNRCFR0(_band) MT_MDP(__OFFS(MDP_BNRCFR0) + \
|
||||
((_band) << 8))
|
||||
#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4)
|
||||
|
@ -172,6 +177,14 @@ enum offs_rev {
|
|||
#define MT_MDP_TO_HIF 0
|
||||
#define MT_MDP_TO_WM 1
|
||||
|
||||
/* TRB: band 0(0x820e1000), band 1(0x820f1000) */
|
||||
#define MT_WF_TRB_BASE(_band) ((_band) ? 0x820f1000 : 0x820e1000)
|
||||
#define MT_WF_TRB(_band, ofs) (MT_WF_TRB_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_TRB_RXPSR0(_band) MT_WF_TRB(_band, 0x03c)
|
||||
#define MT_TRB_RXPSR0_RX_WTBL_PTR GENMASK(25, 16)
|
||||
#define MT_TRB_RXPSR0_RX_RMAC_PTR GENMASK(9, 0)
|
||||
|
||||
/* TMAC: band 0(0x820e4000), band 1(0x820f4000) */
|
||||
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000)
|
||||
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
|
||||
|
@ -565,18 +578,31 @@ enum offs_rev {
|
|||
|
||||
/* WFDMA CSR */
|
||||
#define MT_WFDMA_EXT_CSR_BASE __REG(WFDMA_EXT_CSR_ADDR)
|
||||
#define MT_WFDMA_EXT_CSR_PHYS_BASE 0x18027000
|
||||
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
|
||||
#define MT_WFDMA_EXT_CSR_PHYS(ofs) (MT_WFDMA_EXT_CSR_PHYS_BASE + (ofs))
|
||||
|
||||
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
|
||||
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR_PHYS(0x30)
|
||||
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
|
||||
#define MT_WFDMA_HOST_CONFIG_WED BIT(1)
|
||||
|
||||
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
|
||||
#define MT_WFDMA_WED_RING_CONTROL MT_WFDMA_EXT_CSR_PHYS(0x34)
|
||||
#define MT_WFDMA_WED_RING_CONTROL_TX0 GENMASK(4, 0)
|
||||
#define MT_WFDMA_WED_RING_CONTROL_TX1 GENMASK(12, 8)
|
||||
#define MT_WFDMA_WED_RING_CONTROL_RX1 GENMASK(20, 16)
|
||||
|
||||
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR_PHYS(0x44)
|
||||
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
|
||||
|
||||
#define MT_PCIE_RECOG_ID 0xd7090
|
||||
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
|
||||
#define MT_PCIE_RECOG_ID_SEM BIT(31)
|
||||
|
||||
#define MT_INT_WED_MASK_CSR MT_WFDMA_EXT_CSR(0x204)
|
||||
|
||||
#define MT_WED_TX_RING_BASE MT_WFDMA_EXT_CSR(0x300)
|
||||
#define MT_WED_RX_RING_BASE MT_WFDMA_EXT_CSR(0x400)
|
||||
|
||||
/* WFDMA0 PCIE1 */
|
||||
#define MT_WFDMA0_PCIE1_BASE __REG(WFDMA0_PCIE1_ADDR)
|
||||
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
|
||||
|
@ -794,6 +820,7 @@ enum offs_rev {
|
|||
|
||||
/* ADIE */
|
||||
#define MT_ADIE_CHIP_ID 0x02c
|
||||
#define MT_ADIE_VERSION_MASK GENMASK(15, 0)
|
||||
#define MT_ADIE_CHIP_ID_MASK GENMASK(31, 16)
|
||||
#define MT_ADIE_IDX0 GENMASK(15, 0)
|
||||
#define MT_ADIE_IDX1 GENMASK(31, 16)
|
||||
|
@ -913,12 +940,27 @@ enum offs_rev {
|
|||
#define MT_ADIE_TYPE_MASK BIT(1)
|
||||
|
||||
/* FW MODE SYNC */
|
||||
#define MT_SWDEF_MODE 0x41f23c
|
||||
#define MT_SWDEF_MODE_MT7916 0x41143c
|
||||
#define MT_FW_EXCEPTION __REG(FW_EXCEPTION_ADDR)
|
||||
|
||||
#define MT_SWDEF_BASE __REG(SWDEF_BASE_ADDR)
|
||||
|
||||
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
|
||||
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
|
||||
#define MT_SWDEF_NORMAL_MODE 0
|
||||
#define MT_SWDEF_ICAP_MODE 1
|
||||
#define MT_SWDEF_SPECTRUM_MODE 2
|
||||
|
||||
#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
|
||||
#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
|
||||
#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
|
||||
#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C)
|
||||
#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
|
||||
#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
|
||||
#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
|
||||
#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C)
|
||||
#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x060)
|
||||
#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x064)
|
||||
|
||||
#define MT_DIC_CMD_REG_BASE 0x41f000
|
||||
#define MT_DIC_CMD_REG(ofs) (MT_DIC_CMD_REG_BASE + (ofs))
|
||||
#define MT_DIC_CMD_REG_CMD MT_DIC_CMD_REG(0x10)
|
||||
|
@ -965,10 +1007,6 @@ enum offs_rev {
|
|||
#define MT_TOP_MISC MT_TOP(0xf0)
|
||||
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_REV 0x70010204
|
||||
#define MT_WF_SUBSYS_RST 0x70002600
|
||||
|
||||
#define MT_TOP_WFSYS_WAKEUP MT_TOP(0x1a4)
|
||||
#define MT_TOP_WFSYS_WAKEUP_MASK BIT(0)
|
||||
|
||||
|
@ -1030,6 +1068,10 @@ enum offs_rev {
|
|||
#define MT_MCU_BUS_DBG_TIMEOUT_CK_EN_MASK BIT(3)
|
||||
#define MT_MCU_BUS_DBG_TIMEOUT_EN_MASK BIT(2)
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_REV 0x70010204
|
||||
#define MT_WF_SUBSYS_RST 0x70002600
|
||||
|
||||
/* PCIE MAC */
|
||||
#define MT_PCIE_MAC_BASE 0x74030000
|
||||
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
|
||||
|
@ -1038,6 +1080,9 @@ enum offs_rev {
|
|||
#define MT_PCIE1_MAC_INT_ENABLE 0x74020188
|
||||
#define MT_PCIE1_MAC_INT_ENABLE_MT7916 0x74090188
|
||||
|
||||
#define MT_WM_MCU_PC 0x7c060204
|
||||
#define MT_WA_MCU_PC 0x7c06020c
|
||||
|
||||
/* PP TOP */
|
||||
#define MT_WF_PP_TOP_BASE 0x820cc000
|
||||
#define MT_WF_PP_TOP(ofs) (MT_WF_PP_TOP_BASE + (ofs))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/iopoll.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "mt7915.h"
|
||||
|
||||
|
@ -210,6 +211,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
|
|||
if (IS_ERR_OR_NULL(state))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = pinctrl_select_state(pinctrl, state);
|
||||
|
@ -468,17 +471,32 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie)
|
|||
|
||||
static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie)
|
||||
{
|
||||
u32 id, version, rg_xo_01, rg_xo_03;
|
||||
int ret;
|
||||
|
||||
ret = mt76_wmac_spi_read(dev, adie, MT_ADIE_CHIP_ID, &id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
version = FIELD_GET(MT_ADIE_VERSION_MASK, id);
|
||||
|
||||
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_TOP_THADC, 0x4a563b00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, 0x1d59080f);
|
||||
if (version == 0x8a00 || version == 0x8a10 || version == 0x8b00) {
|
||||
rg_xo_01 = 0x1d59080f;
|
||||
rg_xo_03 = 0x34c00fe0;
|
||||
} else {
|
||||
rg_xo_01 = 0x1959f80f;
|
||||
rg_xo_03 = 0x34d00fe0;
|
||||
}
|
||||
|
||||
ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_01, rg_xo_01);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, 0x34c00fe0);
|
||||
return mt76_wmac_spi_write(dev, adie, MT_ADIE_RG_XO_03, rg_xo_03);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1115,6 +1133,19 @@ static int mt7986_wmac_init(struct mt7915_dev *dev)
|
|||
{
|
||||
struct device *pdev = dev->mt76.dev;
|
||||
struct platform_device *pfdev = to_platform_device(pdev);
|
||||
struct clk *mcu_clk, *ap_conn_clk;
|
||||
|
||||
mcu_clk = devm_clk_get(pdev, "mcu");
|
||||
if (IS_ERR(mcu_clk))
|
||||
dev_err(pdev, "mcu clock not found\n");
|
||||
else if (clk_prepare_enable(mcu_clk))
|
||||
dev_err(pdev, "mcu clock configuration failed\n");
|
||||
|
||||
ap_conn_clk = devm_clk_get(pdev, "ap2conn");
|
||||
if (IS_ERR(ap_conn_clk))
|
||||
dev_err(pdev, "ap2conn clock not found\n");
|
||||
else if (clk_prepare_enable(ap_conn_clk))
|
||||
dev_err(pdev, "ap2conn clock configuration failed\n");
|
||||
|
||||
dev->dcm = devm_platform_ioremap_resource(pfdev, 1);
|
||||
if (IS_ERR(dev->dcm))
|
||||
|
@ -1128,7 +1159,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev)
|
|||
if (IS_ERR(dev->rstc))
|
||||
return PTR_ERR(dev->rstc);
|
||||
|
||||
return mt7986_wmac_enable(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7986_wmac_probe(struct platform_device *pdev)
|
||||
|
@ -1161,12 +1192,12 @@ static int mt7986_wmac_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto free_device;
|
||||
|
||||
mt76_wr(dev, MT_INT_MASK_CSR, 0);
|
||||
|
||||
ret = mt7986_wmac_init(dev);
|
||||
if (ret)
|
||||
goto free_irq;
|
||||
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
ret = mt7915_register_device(dev);
|
||||
if (ret)
|
||||
goto free_irq;
|
||||
|
|
|
@ -9,7 +9,7 @@ static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
|||
{
|
||||
int i, err;
|
||||
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE);
|
||||
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -296,8 +296,8 @@ int mt7921_dma_init(struct mt7921_dev *dev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7921_poll_tx, NAPI_POLL_WEIGHT);
|
||||
netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi,
|
||||
mt7921_poll_tx);
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
|
||||
return mt7921_dma_enable(dev);
|
||||
|
|
|
@ -11,6 +11,10 @@ static const struct ieee80211_iface_limit if_limits[] = {
|
|||
{
|
||||
.max = MT7921_MAX_INTERFACES,
|
||||
.types = BIT(NL80211_IFTYPE_STATION)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -64,7 +68,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy->iface_combinations = if_comb;
|
||||
wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
|
||||
WIPHY_FLAG_4ADDR_STATION);
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
|
||||
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
|
||||
wiphy->max_scan_ssids = 4;
|
||||
|
@ -80,6 +85,10 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
|||
wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
|
||||
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
|
||||
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
|
@ -255,6 +264,10 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
|||
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
|
||||
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
|
||||
INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
INIT_WORK(&dev->ipv6_ns_work, mt7921_set_ipv6_ns_work);
|
||||
skb_queue_head_init(&dev->ipv6_ns_list);
|
||||
#endif
|
||||
skb_queue_head_init(&dev->phy.scan_event_list);
|
||||
skb_queue_head_init(&dev->coredump.msg_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
|
|
|
@ -696,7 +696,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
|
|||
status->nss =
|
||||
FIELD_GET(MT_PRXV_NSTS, v0) + 1;
|
||||
status->encoding = RX_ENC_VHT;
|
||||
if (i > 9)
|
||||
if (i > 11)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_MU:
|
||||
|
@ -814,6 +814,7 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi,
|
|||
{
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
u8 fc_type, fc_stype;
|
||||
u16 ethertype;
|
||||
bool wmm = false;
|
||||
u32 val;
|
||||
|
||||
|
@ -827,7 +828,8 @@ mt7921_mac_write_txwi_8023(struct mt7921_dev *dev, __le32 *txwi,
|
|||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
|
||||
FIELD_PREP(MT_TXD1_TID, tid);
|
||||
|
||||
if (be16_to_cpu(skb->protocol) >= ETH_P_802_3_MIN)
|
||||
ethertype = get_unaligned_be16(&skb->data[12]);
|
||||
if (ethertype >= ETH_P_802_3_MIN)
|
||||
val |= MT_TXD1_ETH_802_3;
|
||||
|
||||
txwi[1] |= cpu_to_le32(val);
|
||||
|
@ -1361,12 +1363,21 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
|
|||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mvif->phy->dev;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_disconnect(vif, true);
|
||||
|
||||
mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
|
||||
mt7921_mcu_set_tx(dev, vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid,
|
||||
true);
|
||||
mt7921_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* system error recovery */
|
||||
|
@ -1715,3 +1726,29 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
|
|||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data);
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
void mt7921_set_ipv6_ns_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
|
||||
ipv6_ns_work);
|
||||
struct sk_buff *skb;
|
||||
int ret = 0;
|
||||
|
||||
do {
|
||||
skb = skb_dequeue(&dev->ipv6_ns_list);
|
||||
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_UNI_CMD(OFFLOAD), true);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
} while (!ret);
|
||||
|
||||
if (ret)
|
||||
skb_queue_purge(&dev->ipv6_ns_list);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/ipv6.h>
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
|
||||
|
@ -12,7 +13,7 @@ static void
|
|||
mt7921_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
{
|
||||
u8 i, ppet_bits, ppet_size, ru_bit_mask = 0x7; /* HE80 */
|
||||
u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
static const u8 ppet16_ppet8_ru3_ru0[] = {0x1c, 0xc7, 0x71};
|
||||
|
||||
he_ppet[0] = FIELD_PREP(IEEE80211_PPE_THRES_NSS_MASK, nss - 1) |
|
||||
FIELD_PREP(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK,
|
||||
|
@ -53,6 +54,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
|||
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_AP:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
|
@ -86,6 +88,23 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band,
|
|||
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
|
||||
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
he_cap_elem->mac_cap_info[2] |=
|
||||
IEEE80211_HE_MAC_CAP2_BSR;
|
||||
he_cap_elem->mac_cap_info[4] |=
|
||||
IEEE80211_HE_MAC_CAP4_BQR;
|
||||
he_cap_elem->mac_cap_info[5] |=
|
||||
IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
he_cap_elem->mac_cap_info[1] |=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
|
||||
|
@ -294,7 +313,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
|
||||
mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
|
@ -310,7 +329,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
|
||||
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
|
||||
|
||||
idx = MT7921_WTBL_RESERVED - mvif->mt76.idx;
|
||||
|
@ -330,7 +349,7 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
|
|||
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
|
||||
if (vif->txq) {
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
mtxq->wcid = &mvif->sta.wcid;
|
||||
mtxq->wcid = idx;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -354,7 +373,7 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
|
||||
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
|
@ -489,8 +508,8 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
|||
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
mt7921_mcu_set_sniffer(dev, vif, monitor);
|
||||
pm->enable = !monitor;
|
||||
pm->ds_enable = !monitor;
|
||||
pm->enable = pm->enable_user && !monitor;
|
||||
pm->ds_enable = pm->ds_enable_user && !monitor;
|
||||
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
|
||||
|
||||
|
@ -566,7 +585,6 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
|||
u64 multicast)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
|
||||
MT_WF_RFCR1_DROP_BF_POLL |
|
||||
MT_WF_RFCR1_DROP_BA |
|
||||
|
@ -576,23 +594,23 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
|||
|
||||
#define MT76_FILTER(_flag, _hw) do { \
|
||||
flags |= *total_flags & FIF_##_flag; \
|
||||
phy->rxfilter &= ~(_hw); \
|
||||
phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
|
||||
dev->mt76.rxfilter &= ~(_hw); \
|
||||
dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \
|
||||
} while (0)
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON |
|
||||
MT_WF_RFCR_DROP_FRAME_REPORT |
|
||||
MT_WF_RFCR_DROP_PROBEREQ |
|
||||
MT_WF_RFCR_DROP_MCAST_FILTERED |
|
||||
MT_WF_RFCR_DROP_MCAST |
|
||||
MT_WF_RFCR_DROP_BCAST |
|
||||
MT_WF_RFCR_DROP_DUPLICATE |
|
||||
MT_WF_RFCR_DROP_A2_BSSID |
|
||||
MT_WF_RFCR_DROP_UNWANTED_CTL |
|
||||
MT_WF_RFCR_DROP_STBC_MULTI);
|
||||
dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON |
|
||||
MT_WF_RFCR_DROP_FRAME_REPORT |
|
||||
MT_WF_RFCR_DROP_PROBEREQ |
|
||||
MT_WF_RFCR_DROP_MCAST_FILTERED |
|
||||
MT_WF_RFCR_DROP_MCAST |
|
||||
MT_WF_RFCR_DROP_BCAST |
|
||||
MT_WF_RFCR_DROP_DUPLICATE |
|
||||
MT_WF_RFCR_DROP_A2_BSSID |
|
||||
MT_WF_RFCR_DROP_UNWANTED_CTL |
|
||||
MT_WF_RFCR_DROP_STBC_MULTI);
|
||||
|
||||
MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
|
||||
MT_WF_RFCR_DROP_A3_MAC |
|
||||
|
@ -606,7 +624,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
|||
MT_WF_RFCR_DROP_NDPA);
|
||||
|
||||
*total_flags = flags;
|
||||
mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
|
||||
mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter);
|
||||
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags);
|
||||
|
@ -635,6 +653,20 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
|
||||
true);
|
||||
mt7921_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_NONE);
|
||||
}
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7921_mcu_uni_add_beacon_offload(dev, hw, vif,
|
||||
info->enable_beacon);
|
||||
|
||||
/* ensure that enable txcmd_mode after bss_info */
|
||||
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7921_mcu_set_tx(dev, vif);
|
||||
|
@ -1301,7 +1333,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw,
|
|||
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76_connac_mcu_set_suspend_iter,
|
||||
mt7921_mcu_set_suspend_iter,
|
||||
&dev->mphy);
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
|
@ -1376,6 +1408,67 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
|
|||
MCU_UNI_CMD(STA_REC_UPDATE));
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct inet6_dev *idev)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mvif->phy->dev;
|
||||
struct inet6_ifaddr *ifa;
|
||||
struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
|
||||
struct sk_buff *skb;
|
||||
u8 i, idx = 0;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct mt76_connac_arpns_tlv arpns;
|
||||
} req_hdr = {
|
||||
.hdr = {
|
||||
.bss_idx = mvif->mt76.idx,
|
||||
},
|
||||
.arpns = {
|
||||
.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),
|
||||
.mode = 2, /* update */
|
||||
.option = 1, /* update only */
|
||||
},
|
||||
};
|
||||
|
||||
read_lock_bh(&idev->lock);
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
if (ifa->flags & IFA_F_TENTATIVE)
|
||||
continue;
|
||||
ns_addrs[idx] = ifa->addr;
|
||||
if (++idx >= IEEE80211_BSS_ARP_ADDR_LIST_LEN)
|
||||
break;
|
||||
}
|
||||
read_unlock_bh(&idev->lock);
|
||||
|
||||
if (!idx)
|
||||
return;
|
||||
|
||||
skb = __mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) +
|
||||
idx * sizeof(struct in6_addr), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
req_hdr.arpns.ips_num = idx;
|
||||
req_hdr.arpns.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)
|
||||
+ idx * sizeof(struct in6_addr));
|
||||
skb_put_data(skb, &req_hdr, sizeof(req_hdr));
|
||||
|
||||
for (i = 0; i < idx; i++)
|
||||
skb_put_data(skb, &ns_addrs[i].in6_u, sizeof(struct in6_addr));
|
||||
|
||||
skb_queue_tail(&dev->ipv6_ns_list, skb);
|
||||
|
||||
ieee80211_queue_work(dev->mt76.hw, &dev->ipv6_ns_work);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mt7921_set_sar_specs(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar)
|
||||
{
|
||||
|
@ -1395,6 +1488,18 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_channel_switch_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
.tx = mt7921_tx,
|
||||
.start = mt7921_start,
|
||||
|
@ -1409,10 +1514,14 @@ const struct ieee80211_ops mt7921_ops = {
|
|||
.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
|
||||
.set_key = mt7921_set_key,
|
||||
.sta_set_decap_offload = mt7921_sta_set_decap_offload,
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
.ipv6_addr_change = mt7921_ipv6_addr_change,
|
||||
#endif /* CONFIG_IPV6 */
|
||||
.ampdu_action = mt7921_ampdu_action,
|
||||
.set_rts_threshold = mt7921_set_rts_threshold,
|
||||
.wake_tx_queue = mt76_wake_tx_queue,
|
||||
.release_buffered_frames = mt76_release_buffered_frames,
|
||||
.channel_switch_beacon = mt7921_channel_switch_beacon,
|
||||
.get_txpower = mt76_get_txpower,
|
||||
.get_stats = mt7921_get_stats,
|
||||
.get_et_sset_count = mt7921_get_et_sset_count,
|
||||
|
|
|
@ -224,6 +224,49 @@ exit:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mcu_fill_message);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int
|
||||
mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev,
|
||||
struct ieee80211_vif *vif, bool suspend)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct mt76_connac_arpns_tlv arpns;
|
||||
} req = {
|
||||
.hdr = {
|
||||
.bss_idx = mvif->mt76.idx,
|
||||
},
|
||||
.arpns = {
|
||||
.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ND),
|
||||
.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),
|
||||
.mode = suspend,
|
||||
},
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(dev, MCU_UNI_CMD_OFFLOAD, &req, sizeof(req),
|
||||
true);
|
||||
}
|
||||
|
||||
void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_IPV6)) {
|
||||
struct mt76_phy *phy = priv;
|
||||
|
||||
mt7921_mcu_set_ipv6_ns_filter(phy->dev, vif,
|
||||
!test_bit(MT76_STATE_RUNNING,
|
||||
&phy->state));
|
||||
}
|
||||
|
||||
mt76_connac_mcu_set_suspend_iter(priv, mac, vif);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static void
|
||||
mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -248,7 +291,8 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac,
|
|||
if (mvif->idx != event->bss_idx)
|
||||
return;
|
||||
|
||||
if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))
|
||||
if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER) ||
|
||||
vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
ieee80211_connection_loss(vif);
|
||||
|
@ -1166,3 +1210,79 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
|||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),
|
||||
true);
|
||||
}
|
||||
|
||||
int
|
||||
mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||
struct ieee80211_mutable_offsets offs;
|
||||
struct {
|
||||
struct req_hdr {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct bcn_content_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
__le16 tim_ie_pos;
|
||||
__le16 csa_ie_pos;
|
||||
__le16 bcc_ie_pos;
|
||||
/* 0: disable beacon offload
|
||||
* 1: enable beacon offload
|
||||
* 2: update probe respond offload
|
||||
*/
|
||||
u8 enable;
|
||||
/* 0: legacy format (TXD + payload)
|
||||
* 1: only cap field IE
|
||||
*/
|
||||
u8 type;
|
||||
__le16 pkt_len;
|
||||
u8 pkt[512];
|
||||
} __packed beacon_tlv;
|
||||
} req = {
|
||||
.hdr = {
|
||||
.bss_idx = mvif->mt76.idx,
|
||||
},
|
||||
.beacon_tlv = {
|
||||
.tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT),
|
||||
.len = cpu_to_le16(sizeof(struct bcn_content_tlv)),
|
||||
.enable = enable,
|
||||
},
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!enable)
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
if (skb->len > 512 - MT_TXD_SIZE) {
|
||||
dev_err(dev->mt76.dev, "beacon size limit exceed\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mt7921_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb,
|
||||
wcid, NULL, 0, true);
|
||||
memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len);
|
||||
req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset);
|
||||
|
||||
if (offs.cntdwn_counter_offs[0]) {
|
||||
u16 csa_offs;
|
||||
|
||||
csa_offs = MT_TXD_SIZE + offs.cntdwn_counter_offs[0] - 4;
|
||||
req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs);
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
out:
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(BSS_INFO_UPDATE),
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,6 @@ struct mt7921_phy {
|
|||
|
||||
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
|
||||
|
||||
u32 rxfilter;
|
||||
u64 omac_mask;
|
||||
|
||||
u16 noise;
|
||||
|
@ -212,6 +211,10 @@ struct mt7921_dev {
|
|||
struct mt76_connac_pm pm;
|
||||
struct mt76_connac_coredump coredump;
|
||||
const struct mt7921_hif_ops *hif_ops;
|
||||
|
||||
struct work_struct ipv6_ns_work;
|
||||
/* IPv6 addresses for WoWLAN */
|
||||
struct sk_buff_head ipv6_ns_list;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -450,6 +453,10 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev);
|
|||
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data);
|
||||
void mt7921_set_runtime_pm(struct mt7921_dev *dev);
|
||||
void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif);
|
||||
void mt7921_set_ipv6_ns_work(struct work_struct *work);
|
||||
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
|
||||
|
@ -467,7 +474,11 @@ bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
|||
|
||||
int mt7921u_mcu_power_on(struct mt7921_dev *dev);
|
||||
int mt7921u_wfsys_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev);
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev, bool resume);
|
||||
int mt7921u_init_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_mac_reset(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
#endif
|
||||
|
|
|
@ -119,7 +119,6 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev)
|
|||
mt7921_mcu_exit(dev);
|
||||
|
||||
tasklet_disable(&dev->irq_tasklet);
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
||||
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
|
||||
|
@ -302,8 +301,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
dev->bus_ops = dev->mt76.bus;
|
||||
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
|
||||
GFP_KERNEL);
|
||||
if (!bus_ops)
|
||||
return -ENOMEM;
|
||||
if (!bus_ops) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
bus_ops->rr = mt7921_rr;
|
||||
bus_ops->wr = mt7921_wr;
|
||||
|
@ -312,7 +313,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
ret = __mt7921e_mcu_drv_pmctrl(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_free_dev;
|
||||
|
||||
mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
|
||||
|
@ -354,6 +355,7 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
mt7921e_unregister_device(dev);
|
||||
devm_free_irq(&pdev->dev, pdev->irq, dev);
|
||||
mt76_free_device(&dev->mt76);
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -516,4 +516,9 @@
|
|||
#define MT_TOP_MISC2_FW_PWR_ON BIT(0)
|
||||
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
|
||||
|
||||
#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs))
|
||||
#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028)
|
||||
#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6)
|
||||
#define MT_WF_SW_SER_DONE_SUSPEND BIT(7)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -246,7 +246,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt7921u_dma_init(dev);
|
||||
ret = mt7921u_dma_init(dev, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -288,6 +288,61 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf)
|
|||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
|
||||
{
|
||||
struct mt7921_dev *dev = usb_get_intfdata(intf);
|
||||
int err;
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
set_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7921u_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct mt7921_dev *dev = usb_get_intfdata(intf);
|
||||
bool reinit = true;
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
|
||||
|
||||
if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
|
||||
reinit = false;
|
||||
break;
|
||||
}
|
||||
if (val & MT_WF_SW_SER_DONE_SUSPEND) {
|
||||
mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
if (reinit || mt7921_dma_need_reinit(dev)) {
|
||||
err = mt7921u_dma_init(dev, true);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
|
||||
|
||||
err = mt76u_resume_rx(&dev->mt76);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
|
||||
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7921_ROM_PATCH);
|
||||
|
@ -297,6 +352,11 @@ static struct usb_driver mt7921u_driver = {
|
|||
.id_table = mt7921u_device_table,
|
||||
.probe = mt7921u_probe,
|
||||
.disconnect = mt7921u_disconnect,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mt7921u_suspend,
|
||||
.resume = mt7921u_resume,
|
||||
.reset_resume = mt7921u_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
.soft_unbind = 1,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
|
|
@ -121,7 +121,7 @@ static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
|
|||
mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
|
||||
}
|
||||
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev)
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev, bool resume)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -136,6 +136,9 @@ int mt7921u_dma_init(struct mt7921_dev *dev)
|
|||
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
|
||||
|
||||
if (resume)
|
||||
return 0;
|
||||
|
||||
err = mt7921u_dma_rx_evt_ep4(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -221,7 +224,7 @@ int mt7921u_mac_reset(struct mt7921_dev *dev)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921u_dma_init(dev);
|
||||
err = mt7921u_dma_init(dev, false);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -66,9 +66,8 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
|
|||
wcid = rcu_dereference(dev->wcid[cb->wcid]);
|
||||
if (wcid) {
|
||||
status.sta = wcid_to_sta(wcid);
|
||||
|
||||
if (status.sta)
|
||||
status.rate = &wcid->rate;
|
||||
status.rates = NULL;
|
||||
status.n_rates = 0;
|
||||
}
|
||||
|
||||
hw = mt76_tx_status_get_hw(dev, skb);
|
||||
|
@ -120,7 +119,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|||
|
||||
memset(cb, 0, sizeof(*cb));
|
||||
|
||||
if (!wcid)
|
||||
if (!wcid || !rcu_access_pointer(dev->wcid[wcid->idx]))
|
||||
return MT_PACKET_ID_NO_ACK;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
|
@ -436,12 +435,11 @@ mt76_txq_stopped(struct mt76_queue *q)
|
|||
|
||||
static int
|
||||
mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
||||
struct mt76_txq *mtxq)
|
||||
struct mt76_txq *mtxq, struct mt76_wcid *wcid)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
|
||||
enum mt76_txq_id qid = mt76_txq_get_qid(txq);
|
||||
struct mt76_wcid *wcid = mtxq->wcid;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb;
|
||||
int n_frames = 1;
|
||||
|
@ -463,7 +461,9 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
|||
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
|
||||
info->control.rates, 1);
|
||||
|
||||
spin_lock(&q->lock);
|
||||
idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
|
||||
spin_unlock(&q->lock);
|
||||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
|
@ -483,14 +483,18 @@ mt76_txq_send_burst(struct mt76_phy *phy, struct mt76_queue *q,
|
|||
ieee80211_get_tx_rates(txq->vif, txq->sta, skb,
|
||||
info->control.rates, 1);
|
||||
|
||||
spin_lock(&q->lock);
|
||||
idx = __mt76_tx_queue_skb(phy, qid, skb, wcid, txq->sta, &stop);
|
||||
spin_unlock(&q->lock);
|
||||
if (idx < 0)
|
||||
break;
|
||||
|
||||
n_frames++;
|
||||
} while (1);
|
||||
|
||||
spin_lock(&q->lock);
|
||||
dev->queue_ops->kick(dev, q);
|
||||
spin_unlock(&q->lock);
|
||||
|
||||
return n_frames;
|
||||
}
|
||||
|
@ -521,12 +525,10 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
|||
break;
|
||||
|
||||
mtxq = (struct mt76_txq *)txq->drv_priv;
|
||||
wcid = mtxq->wcid;
|
||||
if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags))
|
||||
wcid = rcu_dereference(dev->wcid[mtxq->wcid]);
|
||||
if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
|
||||
continue;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
if (mtxq->send_bar && mtxq->aggr) {
|
||||
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
|
||||
struct ieee80211_sta *sta = txq->sta;
|
||||
|
@ -535,15 +537,11 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
|||
u8 tid = txq->tid;
|
||||
|
||||
mtxq->send_bar = false;
|
||||
spin_unlock_bh(&q->lock);
|
||||
ieee80211_send_bar(vif, sta->addr, tid, agg_ssn);
|
||||
spin_lock_bh(&q->lock);
|
||||
}
|
||||
|
||||
if (!mt76_txq_stopped(q))
|
||||
n_frames = mt76_txq_send_burst(phy, q, mtxq);
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
n_frames = mt76_txq_send_burst(phy, q, mtxq, wcid);
|
||||
|
||||
ieee80211_return_txq(phy->hw, txq, false);
|
||||
|
||||
|
@ -563,6 +561,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
|
|||
if (qid >= 4)
|
||||
return;
|
||||
|
||||
local_bh_disable();
|
||||
rcu_read_lock();
|
||||
|
||||
do {
|
||||
|
@ -572,6 +571,7 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
|
|||
} while (len > 0);
|
||||
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_txq_schedule);
|
||||
|
||||
|
@ -721,12 +721,17 @@ int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi)
|
|||
|
||||
spin_lock_bh(&dev->token_lock);
|
||||
|
||||
token = idr_alloc(&dev->token, *ptxwi, 0, dev->drv->token_size,
|
||||
GFP_ATOMIC);
|
||||
token = idr_alloc(&dev->token, *ptxwi, 0, dev->token_size, GFP_ATOMIC);
|
||||
if (token >= 0)
|
||||
dev->token_count++;
|
||||
|
||||
if (dev->token_count >= dev->drv->token_size - MT76_TOKEN_FREE_THR)
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
token >= dev->mmio.wed.wlan.token_start)
|
||||
dev->wed_token_count++;
|
||||
#endif
|
||||
|
||||
if (dev->token_count >= dev->token_size - MT76_TOKEN_FREE_THR)
|
||||
__mt76_set_tx_blocked(dev, true);
|
||||
|
||||
spin_unlock_bh(&dev->token_lock);
|
||||
|
@ -743,10 +748,18 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
|
|||
spin_lock_bh(&dev->token_lock);
|
||||
|
||||
txwi = idr_remove(&dev->token, token);
|
||||
if (txwi)
|
||||
if (txwi) {
|
||||
dev->token_count--;
|
||||
|
||||
if (dev->token_count < dev->drv->token_size - MT76_TOKEN_FREE_THR &&
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
if (mtk_wed_device_active(&dev->mmio.wed) &&
|
||||
token >= dev->mmio.wed.wlan.token_start &&
|
||||
--dev->wed_token_count == 0)
|
||||
wake_up(&dev->tx_wait);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
|
||||
dev->phy.q_tx[0]->blocked)
|
||||
*wake = true;
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ struct wilc_remain_ch {
|
|||
u32 duration;
|
||||
void (*expired)(void *priv, u64 cookie);
|
||||
void *arg;
|
||||
u32 cookie;
|
||||
u64 cookie;
|
||||
};
|
||||
|
||||
struct wilc;
|
||||
|
|
|
@ -233,7 +233,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
|||
wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
|
||||
wl->monitor_dev->needs_free_netdev = true;
|
||||
|
||||
if (cfg80211_register_netdevice(wl->monitor_dev)) {
|
||||
if (register_netdevice(wl->monitor_dev)) {
|
||||
netdev_err(real_dev, "register_netdevice failed\n");
|
||||
free_netdev(wl->monitor_dev);
|
||||
return NULL;
|
||||
|
@ -251,7 +251,7 @@ void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
|
|||
return;
|
||||
|
||||
if (rtnl_locked)
|
||||
cfg80211_unregister_netdevice(wl->monitor_dev);
|
||||
unregister_netdevice(wl->monitor_dev);
|
||||
else
|
||||
unregister_netdev(wl->monitor_dev);
|
||||
wl->monitor_dev = NULL;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "wlan_cfg.h"
|
||||
|
||||
#define WILC_MULTICAST_TABLE_SIZE 8
|
||||
#define WILC_MAX_FW_VERSION_STR_SIZE 50
|
||||
|
||||
/* latest API version supported */
|
||||
#define WILC1000_API_VER 1
|
||||
|
@ -522,7 +523,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
|
|||
|
||||
if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
|
||||
int size;
|
||||
char firmware_ver[20];
|
||||
char firmware_ver[WILC_MAX_FW_VERSION_STR_SIZE];
|
||||
|
||||
size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,
|
||||
firmware_ver,
|
||||
|
|
|
@ -598,7 +598,7 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume)
|
|||
cmd.read_write = 1;
|
||||
cmd.function = 0;
|
||||
cmd.raw = 1;
|
||||
cmd.address = SDIO_FBR_BASE(func->num);
|
||||
cmd.address = SDIO_FBR_BASE(1);
|
||||
cmd.data = SDIO_FBR_ENABLE_CSA;
|
||||
ret = wilc_sdio_cmd52(wilc, &cmd);
|
||||
if (ret) {
|
||||
|
|
|
@ -875,14 +875,15 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count)
|
|||
char *bssid;
|
||||
u8 mgmt_ptk = 0;
|
||||
|
||||
if (vmm_table[i] == 0 || vmm_entries_ac[i] >= NQUEUES)
|
||||
break;
|
||||
|
||||
tqe = wilc_wlan_txq_remove_from_head(wilc, vmm_entries_ac[i]);
|
||||
ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
|
||||
if (!tqe)
|
||||
break;
|
||||
|
||||
ac_pkt_num_to_chip[vmm_entries_ac[i]]++;
|
||||
vif = tqe->vif;
|
||||
if (vmm_table[i] == 0)
|
||||
break;
|
||||
|
||||
le32_to_cpus(&vmm_table[i]);
|
||||
vmm_sz = FIELD_GET(WILC_VMM_BUFFER_SIZE, vmm_table[i]);
|
||||
|
|
|
@ -1146,8 +1146,8 @@ static int qtnf_pcie_pearl_probe(struct qtnf_bus *bus, unsigned int tx_bd_size,
|
|||
}
|
||||
|
||||
tasklet_setup(&ps->base.reclaim_tq, qtnf_pearl_reclaim_tasklet_fn);
|
||||
netif_napi_add(&bus->mux_dev, &bus->mux_napi,
|
||||
qtnf_pcie_pearl_rx_poll, 10);
|
||||
netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
|
||||
qtnf_pcie_pearl_rx_poll, 10);
|
||||
|
||||
ipc_int.fn = qtnf_pcie_pearl_ipc_gen_ep_int;
|
||||
ipc_int.arg = ps;
|
||||
|
|
|
@ -1159,8 +1159,8 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
|
|||
}
|
||||
|
||||
tasklet_setup(&ts->base.reclaim_tq, qtnf_reclaim_tasklet_fn);
|
||||
netif_napi_add(&bus->mux_dev, &bus->mux_napi,
|
||||
qtnf_topaz_rx_poll, 10);
|
||||
netif_napi_add_weight(&bus->mux_dev, &bus->mux_napi,
|
||||
qtnf_topaz_rx_poll, 10);
|
||||
|
||||
ipc_int.fn = qtnf_topaz_ipc_gen_ep_int;
|
||||
ipc_int.arg = ts;
|
||||
|
|
|
@ -1014,7 +1014,7 @@ int rtl_usb_probe(struct usb_interface *intf,
|
|||
hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) +
|
||||
sizeof(struct rtl_usb_priv), &rtl_ops);
|
||||
if (!hw) {
|
||||
WARN_ONCE(true, "rtl_usb: ieee80211 alloc failed\n");
|
||||
pr_warn("rtl_usb: ieee80211 alloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
rtlpriv = hw->priv;
|
||||
|
|
|
@ -1786,7 +1786,7 @@ void rtw_fw_adaptivity(struct rtw_dev *rtwdev)
|
|||
|
||||
SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY);
|
||||
SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode);
|
||||
SET_ADAPTIVITY_OPTION(h2c_pkt, 2);
|
||||
SET_ADAPTIVITY_OPTION(h2c_pkt, 1);
|
||||
SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]);
|
||||
SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini);
|
||||
SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density);
|
||||
|
|
|
@ -19,8 +19,11 @@ config RTW89_PCI
|
|||
config RTW89_8852A
|
||||
tristate
|
||||
|
||||
config RTW89_8852C
|
||||
tristate
|
||||
|
||||
config RTW89_8852AE
|
||||
tristate "Realtek 8852AE PCI wireless network adapter"
|
||||
tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter"
|
||||
depends on PCI
|
||||
select RTW89_CORE
|
||||
select RTW89_PCI
|
||||
|
@ -28,7 +31,18 @@ config RTW89_8852AE
|
|||
help
|
||||
Select this option will enable support for 8852AE chipset
|
||||
|
||||
802.11ax PCIe wireless network adapter
|
||||
802.11ax PCIe wireless network (Wi-Fi 6) adapter
|
||||
|
||||
config RTW89_8852CE
|
||||
tristate "Realtek 8852CE PCI wireless network (Wi-Fi 6E) adapter"
|
||||
depends on PCI
|
||||
select RTW89_CORE
|
||||
select RTW89_PCI
|
||||
select RTW89_8852C
|
||||
help
|
||||
Select this option will enable support for 8852CE chipset
|
||||
|
||||
802.11ax PCIe wireless network (Wi-Fi 6E) adapter
|
||||
|
||||
config RTW89_DEBUG
|
||||
bool
|
||||
|
|
|
@ -23,6 +23,15 @@ rtw89_8852a-objs := rtw8852a.o \
|
|||
obj-$(CONFIG_RTW89_8852AE) += rtw89_8852ae.o
|
||||
rtw89_8852ae-objs := rtw8852ae.o
|
||||
|
||||
obj-$(CONFIG_RTW89_8852C) += rtw89_8852c.o
|
||||
rtw89_8852c-objs := rtw8852c.o \
|
||||
rtw8852c_table.o \
|
||||
rtw8852c_rfk.o \
|
||||
rtw8852c_rfk_table.o
|
||||
|
||||
obj-$(CONFIG_RTW89_8852CE) += rtw89_8852ce.o
|
||||
rtw89_8852ce-objs := rtw8852ce.o
|
||||
|
||||
rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
|
||||
|
||||
obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
|
||||
|
|
|
@ -1608,10 +1608,13 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
|
|||
|
||||
if (rtwdev->scanning &&
|
||||
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
|
||||
rx_status->freq =
|
||||
ieee80211_channel_to_frequency(hal->current_channel,
|
||||
hal->current_band_type);
|
||||
rx_status->band = rtwdev->hal.current_band_type;
|
||||
u8 chan = hal->current_channel;
|
||||
u8 band = hal->current_band_type;
|
||||
enum nl80211_band nl_band;
|
||||
|
||||
nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
rx_status->freq = ieee80211_channel_to_frequency(chan, nl_band);
|
||||
rx_status->band = nl_band;
|
||||
}
|
||||
|
||||
if (desc_info->icv_err || desc_info->crc32_err)
|
||||
|
|
|
@ -3480,6 +3480,20 @@ static inline u8 rtw89_hw_to_rate_info_bw(enum rtw89_bandwidth hw_bw)
|
|||
return RATE_INFO_BW_20;
|
||||
}
|
||||
|
||||
static inline
|
||||
enum nl80211_band rtw89_hw_to_nl80211_band(enum rtw89_band hw_band)
|
||||
{
|
||||
switch (hw_band) {
|
||||
default:
|
||||
case RTW89_BAND_2G:
|
||||
return NL80211_BAND_2GHZ;
|
||||
case RTW89_BAND_5G:
|
||||
return NL80211_BAND_5GHZ;
|
||||
case RTW89_BAND_6G:
|
||||
return NL80211_BAND_6GHZ;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
enum rtw89_bandwidth nl_to_rtw89_bandwidth(enum nl80211_chan_width width)
|
||||
{
|
||||
|
|
|
@ -635,6 +635,11 @@ static int rtw89_debug_priv_mac_reg_dump_get(struct seq_file *m, void *v)
|
|||
start = 0x000;
|
||||
end = 0x014;
|
||||
break;
|
||||
case RTW89_DBG_SEL_MAC_30:
|
||||
seq_puts(m, "Debug selected MAC page 0x30\n");
|
||||
start = 0x030;
|
||||
end = 0x033;
|
||||
break;
|
||||
case RTW89_DBG_SEL_MAC_40:
|
||||
seq_puts(m, "Debug selected MAC page 0x40\n");
|
||||
start = 0x040;
|
||||
|
|
|
@ -28,6 +28,7 @@ enum rtw89_debug_mask {
|
|||
|
||||
enum rtw89_debug_mac_reg_sel {
|
||||
RTW89_DBG_SEL_MAC_00,
|
||||
RTW89_DBG_SEL_MAC_30,
|
||||
RTW89_DBG_SEL_MAC_40,
|
||||
RTW89_DBG_SEL_MAC_80,
|
||||
RTW89_DBG_SEL_MAC_C0,
|
||||
|
|
|
@ -2068,7 +2068,7 @@ static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
|
|||
struct rtw89_pktofld_info *info, *tmp;
|
||||
u8 idx;
|
||||
|
||||
for (idx = RTW89_BAND_2G; idx < NUM_NL80211_BANDS; idx++) {
|
||||
for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) {
|
||||
if (!(rtwdev->chip->support_bands & BIT(idx)))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ const u32 rtw89_mac_mem_base_addrs[RTW89_MAC_MEM_NUM] = {
|
|||
[RTW89_MAC_MEM_TXDATA_FIFO_0] = TXDATA_FIFO_0_BASE_ADDR,
|
||||
[RTW89_MAC_MEM_TXDATA_FIFO_1] = TXDATA_FIFO_1_BASE_ADDR,
|
||||
[RTW89_MAC_MEM_CPU_LOCAL] = CPU_LOCAL_BASE_ADDR,
|
||||
[RTW89_MAC_MEM_BSSID_CAM] = BSSID_CAM_BASE_ADDR,
|
||||
};
|
||||
|
||||
static void rtw89_mac_mem_write(struct rtw89_dev *rtwdev, u32 offset,
|
||||
|
@ -1050,6 +1051,7 @@ static int rtw89_mac_check_cpwm_state(struct rtw89_dev *rtwdev,
|
|||
void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
|
||||
{
|
||||
enum rtw89_rpwm_req_pwr_state state;
|
||||
unsigned long delay = enter ? 10 : 150;
|
||||
int ret;
|
||||
|
||||
if (enter)
|
||||
|
@ -1059,7 +1061,7 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
|
|||
|
||||
rtw89_mac_send_rpwm(rtwdev, state, false);
|
||||
ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
|
||||
1000, 15000, false, rtwdev, state);
|
||||
delay, 15000, false, rtwdev, state);
|
||||
if (ret)
|
||||
rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
|
||||
enter ? "entering" : "leaving");
|
||||
|
@ -1889,11 +1891,12 @@ static int cca_ctrl_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
|||
B_AX_CTN_CHK_BASIC_NAV | B_AX_CTN_CHK_BTCCA |
|
||||
B_AX_CTN_CHK_EDCCA | B_AX_CTN_CHK_CCA_S80 |
|
||||
B_AX_CTN_CHK_CCA_S40 | B_AX_CTN_CHK_CCA_S20 |
|
||||
B_AX_CTN_CHK_CCA_P20 | B_AX_SIFS_CHK_EDCCA);
|
||||
B_AX_CTN_CHK_CCA_P20);
|
||||
val &= ~(B_AX_TB_CHK_TX_NAV | B_AX_TB_CHK_CCA_S80 |
|
||||
B_AX_TB_CHK_CCA_S40 | B_AX_TB_CHK_CCA_S20 |
|
||||
B_AX_SIFS_CHK_CCA_S80 | B_AX_SIFS_CHK_CCA_S40 |
|
||||
B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV);
|
||||
B_AX_SIFS_CHK_CCA_S20 | B_AX_CTN_CHK_TXNAV |
|
||||
B_AX_SIFS_CHK_EDCCA);
|
||||
|
||||
rtw89_write32(rtwdev, reg, val);
|
||||
|
||||
|
@ -2004,6 +2007,7 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
|||
#define TRXCFG_RMAC_DATA_TO 15
|
||||
#define RX_MAX_LEN_UNIT 512
|
||||
#define PLD_RLS_MAX_PG 127
|
||||
#define RX_SPEC_MAX_LEN (11454 + RX_MAX_LEN_UNIT)
|
||||
int ret;
|
||||
u32 reg, rx_max_len, rx_qta;
|
||||
u16 val;
|
||||
|
@ -2034,11 +2038,10 @@ static int rmac_init(struct rtw89_dev *rtwdev, u8 mac_idx)
|
|||
rx_qta = rtwdev->mac.dle_info.c0_rx_qta;
|
||||
else
|
||||
rx_qta = rtwdev->mac.dle_info.c1_rx_qta;
|
||||
rx_qta = rx_qta > PLD_RLS_MAX_PG ? PLD_RLS_MAX_PG : rx_qta;
|
||||
rx_max_len = (rx_qta - 1) * rtwdev->mac.dle_info.ple_pg_size /
|
||||
RX_MAX_LEN_UNIT;
|
||||
rx_max_len = rx_max_len > B_AX_RX_MPDU_MAX_LEN_SIZE ?
|
||||
B_AX_RX_MPDU_MAX_LEN_SIZE : rx_max_len;
|
||||
rx_qta = min_t(u32, rx_qta, PLD_RLS_MAX_PG);
|
||||
rx_max_len = rx_qta * rtwdev->mac.dle_info.ple_pg_size;
|
||||
rx_max_len = min_t(u32, rx_max_len, RX_SPEC_MAX_LEN);
|
||||
rx_max_len /= RX_MAX_LEN_UNIT;
|
||||
rtw89_write32_mask(rtwdev, reg, B_AX_RX_MPDU_MAX_LEN_MASK, rx_max_len);
|
||||
|
||||
if (rtwdev->chip->chip_id == RTL8852A &&
|
||||
|
@ -4239,6 +4242,10 @@ static int rtw89_mac_init_bfee(struct rtw89_dev *rtwdev, u8 mac_idx)
|
|||
u32_encode_bits(CSI_INIT_RATE_VHT, B_AX_BFMEE_VHT_CSI_RATE_MASK) |
|
||||
u32_encode_bits(CSI_INIT_RATE_HE, B_AX_BFMEE_HE_CSI_RATE_MASK));
|
||||
|
||||
reg = rtw89_mac_reg_by_idx(R_AX_CSIRPT_OPTION, mac_idx);
|
||||
rtw89_write32_set(rtwdev, reg,
|
||||
B_AX_CSIPRT_VHTSU_AID_EN | B_AX_CSIPRT_HESU_AID_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ enum rtw89_mac_mem_sel {
|
|||
RTW89_MAC_MEM_TXDATA_FIFO_0,
|
||||
RTW89_MAC_MEM_TXDATA_FIFO_1,
|
||||
RTW89_MAC_MEM_CPU_LOCAL,
|
||||
RTW89_MAC_MEM_BSSID_CAM,
|
||||
|
||||
/* keep last */
|
||||
RTW89_MAC_MEM_NUM,
|
||||
|
|
|
@ -630,7 +630,7 @@ static void rtw89_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta
|
|||
|
||||
rtwsta->use_cfg_mask = true;
|
||||
rtwsta->mask = *br_data->mask;
|
||||
rtw89_phy_ra_updata_sta(br_data->rtwdev, sta);
|
||||
rtw89_phy_ra_updata_sta(br_data->rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
|
||||
}
|
||||
|
||||
static void rtw89_ra_mask_info_update(struct rtw89_dev *rtwdev,
|
||||
|
@ -759,6 +759,15 @@ static void rtw89_ops_cancel_hw_scan(struct ieee80211_hw *hw,
|
|||
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 rtw89_dev *rtwdev = hw->priv;
|
||||
|
||||
rtw89_phy_ra_updata_sta(rtwdev, sta, changed);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops rtw89_ops = {
|
||||
.tx = rtw89_ops_tx,
|
||||
.wake_tx_queue = rtw89_ops_wake_tx_queue,
|
||||
|
@ -788,5 +797,6 @@ const struct ieee80211_ops rtw89_ops = {
|
|||
.hw_scan = rtw89_ops_hw_scan,
|
||||
.cancel_hw_scan = rtw89_ops_cancel_hw_scan,
|
||||
.set_sar_specs = rtw89_ops_set_sar_specs,
|
||||
.sta_rc_update = rtw89_ops_sta_rc_update,
|
||||
};
|
||||
EXPORT_SYMBOL(rtw89_ops);
|
||||
|
|
|
@ -682,9 +682,6 @@ EXPORT_SYMBOL(rtw89_pci_enable_intr_v1);
|
|||
void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci)
|
||||
{
|
||||
rtw89_write32(rtwdev, R_AX_PCIE_HIMR00_V1, 0);
|
||||
rtw89_write32(rtwdev, R_AX_HIMR0, 0);
|
||||
rtw89_write32(rtwdev, R_AX_HAXI_HIMR00, 0);
|
||||
rtw89_write32(rtwdev, R_AX_HIMR1, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(rtw89_pci_disable_intr_v1);
|
||||
|
||||
|
|
|
@ -357,13 +357,19 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
|
|||
ra->csi_mode = csi_mode;
|
||||
}
|
||||
|
||||
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
|
||||
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
|
||||
u32 changed)
|
||||
{
|
||||
struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
|
||||
struct rtw89_ra_info *ra = &rtwsta->ra;
|
||||
|
||||
rtw89_phy_ra_sta_update(rtwdev, sta, false);
|
||||
ra->upd_mask = 1;
|
||||
|
||||
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
|
||||
ra->upd_mask = 1;
|
||||
if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))
|
||||
ra->upd_bw_nss_mask = 1;
|
||||
|
||||
rtw89_debug(rtwdev, RTW89_DBG_RA,
|
||||
"ra updat: macid = %d, bw = %d, nss = %d, gi = %d %d",
|
||||
ra->macid,
|
||||
|
@ -423,27 +429,28 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
|
|||
RTW89_HW_RATE_MCS16,
|
||||
RTW89_HW_RATE_MCS24};
|
||||
u8 band = rtwdev->hal.current_band_type;
|
||||
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
|
||||
u8 tx_nss = rtwdev->hal.tx_nss;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < tx_nss; i++)
|
||||
if (!__check_rate_pattern(&next_pattern, hw_rate_he[i],
|
||||
RA_MASK_HE_RATES, RTW89_RA_MODE_HE,
|
||||
mask->control[band].he_mcs[i],
|
||||
mask->control[nl_band].he_mcs[i],
|
||||
0, true))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < tx_nss; i++)
|
||||
if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i],
|
||||
RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT,
|
||||
mask->control[band].vht_mcs[i],
|
||||
mask->control[nl_band].vht_mcs[i],
|
||||
0, true))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < tx_nss; i++)
|
||||
if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i],
|
||||
RA_MASK_HT_RATES, RTW89_RA_MODE_HT,
|
||||
mask->control[band].ht_mcs[i],
|
||||
mask->control[nl_band].ht_mcs[i],
|
||||
0, true))
|
||||
goto out;
|
||||
|
||||
|
@ -451,18 +458,18 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
|
|||
* require at least one basic rate for ieee80211_set_bitrate_mask,
|
||||
* so the decision just depends on if all bitrates are set or not.
|
||||
*/
|
||||
sband = rtwdev->hw->wiphy->bands[band];
|
||||
sband = rtwdev->hw->wiphy->bands[nl_band];
|
||||
if (band == RTW89_BAND_2G) {
|
||||
if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_CCK1,
|
||||
RA_MASK_CCK_RATES | RA_MASK_OFDM_RATES,
|
||||
RTW89_RA_MODE_CCK | RTW89_RA_MODE_OFDM,
|
||||
mask->control[band].legacy,
|
||||
mask->control[nl_band].legacy,
|
||||
BIT(sband->n_bitrates) - 1, false))
|
||||
goto out;
|
||||
} else {
|
||||
if (!__check_rate_pattern(&next_pattern, RTW89_HW_RATE_OFDM6,
|
||||
RA_MASK_OFDM_RATES, RTW89_RA_MODE_OFDM,
|
||||
mask->control[band].legacy,
|
||||
mask->control[nl_band].legacy,
|
||||
BIT(sband->n_bitrates) - 1, false))
|
||||
goto out;
|
||||
}
|
||||
|
@ -487,7 +494,7 @@ static void rtw89_phy_ra_updata_sta_iter(void *data, struct ieee80211_sta *sta)
|
|||
{
|
||||
struct rtw89_dev *rtwdev = (struct rtw89_dev *)data;
|
||||
|
||||
rtw89_phy_ra_updata_sta(rtwdev, sta);
|
||||
rtw89_phy_ra_updata_sta(rtwdev, sta, IEEE80211_RC_SUPP_RATES_CHANGED);
|
||||
}
|
||||
|
||||
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev)
|
||||
|
@ -2456,6 +2463,11 @@ void rtw89_phy_cfo_parse(struct rtw89_dev *rtwdev, s16 cfo_val,
|
|||
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
|
||||
u8 macid = phy_ppdu->mac_id;
|
||||
|
||||
if (macid >= CFO_TRACK_MAX_USER) {
|
||||
rtw89_warn(rtwdev, "mac_id %d is out of range\n", macid);
|
||||
return;
|
||||
}
|
||||
|
||||
cfo->cfo_tail[macid] += cfo_val;
|
||||
cfo->cfo_cnt[macid]++;
|
||||
cfo->packet_count++;
|
||||
|
|
|
@ -471,7 +471,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
|
|||
u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
|
||||
void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
|
||||
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
|
||||
void rtw89_phy_ra_updata_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
|
||||
u32 changed);
|
||||
void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
|
||||
struct ieee80211_vif *vif,
|
||||
const struct cfg80211_bitrate_mask *mask);
|
||||
|
|
|
@ -2605,7 +2605,6 @@
|
|||
B_AX_TMAC_HWSIGB_GEN | \
|
||||
B_AX_TMAC_RXTB | \
|
||||
B_AX_TMAC_MIMO_CTRL | \
|
||||
B_AX_RMAC_CSI | \
|
||||
B_AX_RMAC_FTM)
|
||||
|
||||
#define R_AX_WMAC_TX_TF_INFO_0 0xCCD0
|
||||
|
@ -2842,6 +2841,11 @@
|
|||
#define R_AX_RX_SR_CTRL_C1 0xEE4A
|
||||
#define B_AX_SR_EN BIT(0)
|
||||
|
||||
#define R_AX_CSIRPT_OPTION 0xCE64
|
||||
#define R_AX_CSIRPT_OPTION_C1 0xEE64
|
||||
#define B_AX_CSIPRT_HESU_AID_EN BIT(25)
|
||||
#define B_AX_CSIPRT_VHTSU_AID_EN BIT(24)
|
||||
|
||||
#define R_AX_RX_STATE_MONITOR 0xCEF0
|
||||
#define R_AX_RX_STATE_MONITOR_C1 0xEEF0
|
||||
#define B_AX_RX_STATE_MONITOR_MASK GENMASK(31, 0)
|
||||
|
@ -3662,7 +3666,7 @@
|
|||
#define R_DCFO 0x4264
|
||||
#define B_DCFO GENMASK(1, 0)
|
||||
#define R_SEG0CSI 0x42AC
|
||||
#define B_SEG0CSI_IDX GENMASK(10, 0)
|
||||
#define B_SEG0CSI_IDX GENMASK(11, 0)
|
||||
#define R_SEG0CSI_EN 0x42C4
|
||||
#define B_SEG0CSI_EN BIT(23)
|
||||
#define R_BSS_CLR_MAP 0x43ac
|
||||
|
@ -3818,6 +3822,8 @@
|
|||
#define B_CHBW_MOD_SBW GENMASK(13, 12)
|
||||
#define B_CHBW_MOD_PRICH GENMASK(11, 8)
|
||||
#define B_ANT_RX_SEG0 GENMASK(3, 0)
|
||||
#define R_PD_BOOST_EN 0x49E8
|
||||
#define B_PD_BOOST_EN BIT(7)
|
||||
#define R_P1_BACKOFF_IBADC_V1 0x49F0
|
||||
#define B_P1_BACKOFF_IBADC_V1 GENMASK(31, 26)
|
||||
#define R_BK_FC0_INV_V1 0x4A1C
|
||||
|
@ -3836,6 +3842,12 @@
|
|||
#define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0)
|
||||
#define R_PATH0_FRC_FIR_TYPE_V1 0x4C00
|
||||
#define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
|
||||
#define R_PATH0_NOTCH 0x4C14
|
||||
#define B_PATH0_NOTCH_EN BIT(12)
|
||||
#define B_PATH0_NOTCH_VAL GENMASK(11, 0)
|
||||
#define R_PATH0_NOTCH2 0x4C20
|
||||
#define B_PATH0_NOTCH2_EN BIT(12)
|
||||
#define B_PATH0_NOTCH2_VAL GENMASK(11, 0)
|
||||
#define R_PATH0_5MDET 0x4C4C
|
||||
#define B_PATH0_5MDET_EN BIT(12)
|
||||
#define B_PATH0_5MDET_SB2 BIT(8)
|
||||
|
@ -3843,6 +3855,12 @@
|
|||
#define B_PATH0_5MDET_TH GENMASK(5, 0)
|
||||
#define R_PATH1_FRC_FIR_TYPE_V1 0x4CC4
|
||||
#define B_PATH1_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0)
|
||||
#define R_PATH1_NOTCH 0x4CD8
|
||||
#define B_PATH1_NOTCH_EN BIT(12)
|
||||
#define B_PATH1_NOTCH_VAL GENMASK(11, 0)
|
||||
#define R_PATH1_NOTCH2 0x4CE4
|
||||
#define B_PATH1_NOTCH2_EN BIT(12)
|
||||
#define B_PATH1_NOTCH2_VAL GENMASK(11, 0)
|
||||
#define R_PATH1_5MDET 0x4D10
|
||||
#define B_PATH1_5MDET_EN BIT(12)
|
||||
#define B_PATH1_5MDET_SB2 BIT(8)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue