Merge tag 'mt76-next-2025-03-19' of https://github.com/nbd168/wireless

Felix Fietkau says:
====================
mt76 patches for 6.15

- preparation for mt7996 mlo support
- fixes
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg
2025-03-19 19:37:46 +01:00
32 changed files with 2056 additions and 944 deletions

View File

@@ -293,6 +293,7 @@ struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
kfree(mlink);
return ERR_PTR(ret);
}
rcu_assign_pointer(mvif->offchannel_link, mlink);
return mlink;
}
@@ -301,10 +302,12 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct mt76_vif_link *mlink)
{
struct mt76_dev *dev = phy->dev;
struct mt76_vif_data *mvif = mlink->mvif;
if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
return;
rcu_assign_pointer(mvif->offchannel_link, NULL);
dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
kfree(mlink);
}

View File

@@ -95,6 +95,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
#ifdef CONFIG_NL80211_TESTMODE
dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
if (!dev->test_mtd.name) {
ret = -ENOMEM;
goto out_put_node;
}
dev->test_mtd.offset = offset;
#endif

View File

@@ -816,8 +816,8 @@ void mt76_free_device(struct mt76_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76_free_device);
static struct mt76_phy *
mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
struct mt76_chanctx *ctx;
@@ -831,6 +831,7 @@ mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ctx = (struct mt76_chanctx *)mlink->ctx->drv_priv;
return ctx->phy;
}
EXPORT_SYMBOL_GPL(mt76_vif_phy);
static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
{
@@ -1697,6 +1698,17 @@ void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
}
EXPORT_SYMBOL_GPL(mt76_wcid_add_poll);
s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower)
{
int n_chains = hweight16(phy->chainmask);
txpower = mt76_get_sar_power(phy, phy->chandef.chan, txpower * 2);
txpower -= mt76_tx_power_nss_delta(n_chains);
return txpower;
}
EXPORT_SYMBOL_GPL(mt76_get_power_bound);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, int *dbm)
{

View File

@@ -351,6 +351,7 @@ struct mt76_wcid {
u8 hw_key_idx;
u8 hw_key_idx2;
u8 offchannel:1;
u8 sta:1;
u8 sta_disabled:1;
u8 amsdu:1;
@@ -491,6 +492,7 @@ struct mt76_hw_cap {
#define MT_DRV_RX_DMA_HDR BIT(3)
#define MT_DRV_HW_MGMT_TXQ BIT(4)
#define MT_DRV_AMSDU_OFFLOAD BIT(5)
#define MT_DRV_IGNORE_TXS_FAILED BIT(6)
struct mt76_driver_ops {
u32 drv_flags;
@@ -769,6 +771,7 @@ struct mt76_testmode_data {
struct mt76_vif_link {
u8 idx;
u8 link_idx;
u8 omac_idx;
u8 band_idx;
u8 wmm_idx;
@@ -786,6 +789,7 @@ struct mt76_vif_link {
struct mt76_vif_data {
struct mt76_vif_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
struct mt76_vif_link __rcu *offchannel_link;
struct mt76_phy *roc_phy;
u16 valid_links;
@@ -1224,6 +1228,8 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
u8 band_idx);
int mt76_register_phy(struct mt76_phy *phy, bool vht,
struct ieee80211_rate *rates, int n_rates);
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
struct dentry *mt76_register_debugfs_fops(struct mt76_phy *phy,
const struct file_operations *ops);
@@ -1482,6 +1488,8 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx);
s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
unsigned int link_id, int *dbm);
int mt76_init_sar_power(struct ieee80211_hw *hw,

View File

@@ -314,6 +314,9 @@ enum tx_frag_idx {
#define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
#define MT_TXFREE_INFO_STAT GENMASK(29, 28)
#define MT_TXS_HDR_SIZE 4 /* Unit: DW */
#define MT_TXS_SIZE 12 /* Unit: DW */
#define MT_TXS0_BW GENMASK(31, 29)
#define MT_TXS0_TID GENMASK(28, 26)
#define MT_TXS0_AMPDU BIT(25)

View File

@@ -391,7 +391,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);
if (vif->type == NL80211_IFTYPE_STATION &&
!is_zero_ether_addr(link_conf->bssid)) {
link_conf && !is_zero_ether_addr(link_conf->bssid)) {
memcpy(basic->peer_addr, link_conf->bssid, ETH_ALEN);
basic->aid = cpu_to_le16(vif->cfg.aid);
} else {
@@ -1168,7 +1168,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
.len = cpu_to_le16(sizeof(struct req_tlv)),
.active = enable,
.link_idx = mvif->idx,
.link_idx = mvif->link_idx,
},
};
struct {
@@ -1191,7 +1191,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
.bmc_tx_wlan_idx = cpu_to_le16(wcid->idx),
.sta_idx = cpu_to_le16(wcid->idx),
.conn_state = 1,
.link_idx = mvif->idx,
.link_idx = mvif->link_idx,
},
};
int err, idx, cmd, len;

View File

@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
MT_DRV_SW_RX_AIRTIME,
MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x0_set_channel,

View File

@@ -214,7 +214,8 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
const struct usb_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.drv_flags = MT_DRV_SW_RX_AIRTIME,
.drv_flags = MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x0_set_channel,

View File

@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct mt76_driver_ops drv_ops = {
.txwi_size = sizeof(struct mt76x02_txwi),
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
MT_DRV_SW_RX_AIRTIME,
MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x2e_set_channel,

View File

@@ -22,6 +22,7 @@ static const struct usb_device_id mt76x2u_device_table[] = {
{ USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
{ USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */
{ USB_DEVICE(0x045e, 0x02fe) }, /* XBox One Wireless Adapter */
{ USB_DEVICE(0x2357, 0x0137) }, /* TP-Link TL-WDN6200 */
{ },
};
@@ -29,7 +30,8 @@ static int mt76x2u_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
.drv_flags = MT_DRV_SW_RX_AIRTIME,
.drv_flags = MT_DRV_SW_RX_AIRTIME |
MT_DRV_IGNORE_TXS_FAILED,
.survey_flags = SURVEY_INFO_TIME_TX,
.update_survey = mt76x02_update_channel,
.set_channel = mt76x2u_set_channel,

View File

@@ -303,9 +303,9 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.dl_vht_3mu_cnt,
phy->mib.dl_vht_4mu_cnt);
sub_total_cnt = phy->mib.dl_vht_2mu_cnt +
phy->mib.dl_vht_3mu_cnt +
phy->mib.dl_vht_4mu_cnt;
sub_total_cnt = (u64)phy->mib.dl_vht_2mu_cnt +
phy->mib.dl_vht_3mu_cnt +
phy->mib.dl_vht_4mu_cnt;
seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld",
sub_total_cnt);
@@ -353,26 +353,27 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.dl_he_9to16ru_cnt,
phy->mib.dl_he_gtr16ru_cnt);
sub_total_cnt = phy->mib.dl_he_2mu_cnt +
phy->mib.dl_he_3mu_cnt +
phy->mib.dl_he_4mu_cnt;
sub_total_cnt = (u64)phy->mib.dl_he_2mu_cnt +
phy->mib.dl_he_3mu_cnt +
phy->mib.dl_he_4mu_cnt;
total_ppdu_cnt = sub_total_cnt;
seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld",
sub_total_cnt);
sub_total_cnt = phy->mib.dl_he_2ru_cnt +
phy->mib.dl_he_3ru_cnt +
phy->mib.dl_he_4ru_cnt +
phy->mib.dl_he_5to8ru_cnt +
phy->mib.dl_he_9to16ru_cnt +
phy->mib.dl_he_gtr16ru_cnt;
sub_total_cnt = (u64)phy->mib.dl_he_2ru_cnt +
phy->mib.dl_he_3ru_cnt +
phy->mib.dl_he_4ru_cnt +
phy->mib.dl_he_5to8ru_cnt +
phy->mib.dl_he_9to16ru_cnt +
phy->mib.dl_he_gtr16ru_cnt;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld",
sub_total_cnt);
total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt;
total_ppdu_cnt += (u64)phy->mib.dl_he_su_cnt +
phy->mib.dl_he_ext_su_cnt;
seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt);
@@ -404,20 +405,20 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
phy->mib.ul_hetrig_9to16ru_cnt,
phy->mib.ul_hetrig_gtr16ru_cnt);
sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt +
phy->mib.ul_hetrig_3mu_cnt +
phy->mib.ul_hetrig_4mu_cnt;
sub_total_cnt = (u64)phy->mib.ul_hetrig_2mu_cnt +
phy->mib.ul_hetrig_3mu_cnt +
phy->mib.ul_hetrig_4mu_cnt;
total_ppdu_cnt = sub_total_cnt;
seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld",
sub_total_cnt);
sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt +
phy->mib.ul_hetrig_3ru_cnt +
phy->mib.ul_hetrig_4ru_cnt +
phy->mib.ul_hetrig_5to8ru_cnt +
phy->mib.ul_hetrig_9to16ru_cnt +
phy->mib.ul_hetrig_gtr16ru_cnt;
sub_total_cnt = (u64)phy->mib.ul_hetrig_2ru_cnt +
phy->mib.ul_hetrig_3ru_cnt +
phy->mib.ul_hetrig_4ru_cnt +
phy->mib.ul_hetrig_5to8ru_cnt +
phy->mib.ul_hetrig_9to16ru_cnt +
phy->mib.ul_hetrig_gtr16ru_cnt;
total_ppdu_cnt += sub_total_cnt;
seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld",
@@ -1084,13 +1085,13 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
return -EINVAL;
if (pwr160)
pwr160 = mt7915_get_power_bound(phy, pwr160);
pwr160 = mt76_get_power_bound(mphy, pwr160);
if (pwr80)
pwr80 = mt7915_get_power_bound(phy, pwr80);
pwr80 = mt76_get_power_bound(mphy, pwr80);
if (pwr40)
pwr40 = mt7915_get_power_bound(phy, pwr40);
pwr40 = mt76_get_power_bound(mphy, pwr40);
if (pwr20)
pwr20 = mt7915_get_power_bound(phy, pwr20);
pwr20 = mt76_get_power_bound(mphy, pwr20);
if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0)
return -EINVAL;

View File

@@ -3323,7 +3323,7 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
if (ret)
return ret;
txpower = mt7915_get_power_bound(phy, txpower);
txpower = mt76_get_power_bound(mphy, txpower);
if (txpower > mphy->txpower_cur || txpower < 0)
return -EINVAL;
@@ -3373,7 +3373,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
int i, idx;
int tx_power;
tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
tx_power = mt76_get_power_bound(mphy, hw->conf.power_level);
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
&limits_array, tx_power);
mphy->txpower_cur = tx_power;

View File

@@ -515,16 +515,4 @@ enum {
sizeof(struct bss_info_bmc_rate) +\
sizeof(struct bss_info_ext_bss))
static inline s8
mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
{
struct mt76_phy *mphy = phy->mt76;
int n_chains = hweight16(mphy->chainmask);
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
txpower -= mt76_tx_power_nss_delta(n_chains);
return txpower;
}
#endif

View File

@@ -811,6 +811,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->deflink.wcid.phy_idx = mvif->bss_conf.mt76.band_idx;
msta->deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET;
msta->deflink.last_txs = jiffies;
msta->deflink.sta = msta;
ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
if (ret)

View File

@@ -58,15 +58,110 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
return PTR_ERR_OR_ZERO(hwmon);
}
void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2)
{
struct mt792x_phy *phy = &dev->phy;
struct mt7925_clc_rule_v2 *rule;
struct mt7925_clc *clc;
bool old = dev->has_eht, new = true;
u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2);
u8 *pos;
if (mtcl_conf != MT792X_ACPI_MTCL_INVALID &&
(((mtcl_conf >> 4) & 0x3) == 0)) {
new = false;
goto out;
}
if (!phy->clc[MT792x_CLC_BE_CTRL])
goto out;
clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL];
pos = clc->data;
while (1) {
rule = (struct mt7925_clc_rule_v2 *)pos;
if (rule->alpha2[0] == alpha2[0] &&
rule->alpha2[1] == alpha2[1]) {
new = false;
break;
}
/* Check the last one */
if (rule->flag && BIT(0))
break;
pos += sizeof(*rule);
}
out:
if (old == new)
return;
dev->has_eht = new;
mt7925_set_stream_he_eht_caps(phy);
}
static void
mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
{
#define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
#define MT7925_UNII_59G_IS_VALID 0x1
#define MT7925_UNII_6G_IS_VALID 0x1e
struct ieee80211_supported_band *sband;
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_channel *ch;
u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, mdev->alpha2);
int i;
if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) {
if ((mtcl_conf & 0x3) == 0)
dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID;
if (((mtcl_conf >> 2) & 0x3) == 0)
dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID;
}
sband = wiphy->bands[NL80211_BAND_5GHZ];
if (!sband)
return;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
/* UNII-4 */
if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq))
ch->flags |= IEEE80211_CHAN_DISABLED;
}
sband = wiphy->bands[NL80211_BAND_6GHZ];
if (!sband)
return;
for (i = 0; i < sband->n_channels; i++) {
ch = &sband->channels[i];
/* UNII-5/6/7/8 */
if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) ||
IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) ||
IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) ||
IS_UNII_INVALID(4, 6875, 7125, ch->center_freq))
ch->flags |= IEEE80211_CHAN_DISABLED;
}
}
void mt7925_regd_update(struct mt792x_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
if (!dev->regd_change)
return;
mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env);
mt7925_regd_channel_update(wiphy, dev);
mt7925_mcu_set_channel_domain(hw->priv);
mt7925_set_tx_sar_pwr(hw, NULL);
dev->regd_change = false;
@@ -244,6 +339,7 @@ int mt7925_register_device(struct mt792x_dev *dev)
dev->mt76.tx_worker.fn = mt792x_tx_worker;
INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work);
INIT_DELAYED_WORK(&dev->mlo_pm_work, mt7925_mlo_pm_work);
INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work);
spin_lock_init(&dev->pm.wake.lock);
mutex_init(&dev->pm.mutex);

View File

@@ -251,12 +251,12 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
},
};
if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EVT_EN))
if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EN))
return 0;
ext_capab[0].eml_capabilities = phy->eml_cap;
ext_capab[0].mld_capa_and_ops =
u16_encode_bits(1, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
wiphy->iftype_ext_capab = ext_capab;
@@ -360,10 +360,15 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
struct mt76_txq *mtxq;
int idx, ret = 0;
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mconf->mt76.idx = MT792x_MAX_INTERFACES;
} else {
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
}
}
mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?
@@ -371,6 +376,7 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
mconf->mt76.band_idx = 0xff;
mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?
0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
mconf->mt76.link_idx = hweight16(mvif->valid_links);
if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4;
@@ -421,6 +427,7 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mvif->bss_conf.vif = mvif;
mvif->sta.vif = mvif;
mvif->deflink_id = IEEE80211_LINK_UNSPECIFIED;
mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;
ret = mt7925_mac_link_bss_add(dev, &vif->bss_conf, &mvif->sta.deflink);
if (ret < 0)
@@ -1149,7 +1156,12 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
struct mt792x_bss_conf *mconf;
mconf = mt792x_link_conf_to_mconf(link_conf);
mt792x_mac_link_bss_remove(dev, mconf, mlink);
if (ieee80211_vif_is_mld(vif))
mt792x_mac_link_bss_remove(dev, mconf, mlink);
else
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,
link_sta, false);
}
spin_lock_bh(&mdev->sta_poll_lock);
@@ -1169,6 +1181,31 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
struct mt76_wcid *wcid;
unsigned int link_id;
/* clean up bss before starec */
for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_link_sta *link_sta;
struct ieee80211_bss_conf *link_conf;
struct mt792x_bss_conf *mconf;
struct mt792x_link_sta *mlink;
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
if (!link_sta)
continue;
mlink = mt792x_sta_to_link(msta, link_id);
if (!mlink)
continue;
link_conf = mt792x_vif_to_bss_conf(vif, link_id);
if (!link_conf)
continue;
mconf = mt792x_link_conf_to_mconf(link_conf);
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,
link_sta, false);
}
for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_link_sta *link_sta;
struct mt792x_link_sta *mlink;
@@ -1206,51 +1243,22 @@ void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
struct {
struct {
u8 omac_idx;
u8 band_idx;
__le16 pad;
} __packed hdr;
struct req_tlv {
__le16 tag;
__le16 len;
u8 active;
u8 link_idx; /* hw link idx */
u8 omac_addr[ETH_ALEN];
} __packed tlv;
} dev_req = {
.hdr = {
.omac_idx = 0,
.band_idx = 0,
},
.tlv = {
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
.len = cpu_to_le16(sizeof(struct req_tlv)),
.active = true,
},
};
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
unsigned long rem;
rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0);
mt7925_mac_sta_remove_links(dev, vif, sta, rem);
if (ieee80211_vif_is_mld(vif)) {
mt7925_mcu_set_dbdc(&dev->mphy, false);
/* recovery omac address for the legacy interface */
memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN);
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE),
&dev_req, sizeof(dev_req), true);
}
if (ieee80211_vif_is_mld(vif))
mt7925_mcu_del_dev(mdev, vif);
if (vif->type == NL80211_IFTYPE_STATION) {
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
mvif->wep_sta = NULL;
ewma_rssi_init(&mvif->bss_conf.rssi);
}
mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;
}
EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove);
@@ -1289,22 +1297,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_RX_START:
mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,
params->buf_size);
mt7925_mcu_uni_rx_ba(dev, vif, params, true);
mt7925_mcu_uni_rx_ba(dev, params, true);
break;
case IEEE80211_AMPDU_RX_STOP:
mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);
mt7925_mcu_uni_rx_ba(dev, vif, params, false);
mt7925_mcu_uni_rx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
mtxq->aggr = true;
mtxq->send_bar = false;
mt7925_mcu_uni_tx_ba(dev, vif, params, true);
mt7925_mcu_uni_tx_ba(dev, params, true);
break;
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
mt7925_mcu_uni_tx_ba(dev, params, false);
break;
case IEEE80211_AMPDU_TX_START:
set_bit(tid, &msta->deflink.wcid.ampdu_state);
@@ -1313,7 +1321,7 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_CONT:
mtxq->aggr = false;
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
mt7925_mcu_uni_tx_ba(dev, params, false);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
}
@@ -1322,6 +1330,38 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return ret;
}
static void
mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt792x_dev *dev = priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
unsigned long valid = ieee80211_vif_is_mld(vif) ?
mvif->valid_links : BIT(0);
struct ieee80211_bss_conf *bss_conf;
int i;
if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS)
return;
mt792x_mutex_acquire(dev);
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
bss_conf = mt792x_vif_to_bss_conf(vif, i);
mt7925_mcu_uni_bss_ps(dev, bss_conf);
}
mt792x_mutex_release(dev);
}
void mt7925_mlo_pm_work(struct work_struct *work)
{
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
mlo_pm_work.work);
struct ieee80211_hw *hw = mt76_hw(dev);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7925_mlo_pm_iter, dev);
}
static bool is_valid_alpha2(const char *alpha2)
{
if (!alpha2)
@@ -1378,6 +1418,8 @@ void mt7925_scan_work(struct work_struct *work)
if (!is_valid_alpha2(evt->alpha2))
break;
mt7925_regd_be_ctrl(phy->dev, evt->alpha2);
if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
break;
@@ -1871,6 +1913,9 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
mt7925_mcu_sta_update(dev, NULL, vif, true,
MT76_STA_INFO_STATE_ASSOC);
mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
if (ieee80211_vif_is_mld(vif))
mvif->mlo_pm_state = MT792x_MLO_LINK_ASSOC;
}
if (changed & BSS_CHANGED_ARP_FILTER) {
@@ -1881,9 +1926,19 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_PS) {
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
bss_conf = mt792x_vif_to_bss_conf(vif, i);
if (hweight16(mvif->valid_links) < 2) {
/* legacy */
bss_conf = &vif->bss_conf;
mt7925_mcu_uni_bss_ps(dev, bss_conf);
} else {
if (mvif->mlo_pm_state == MT792x_MLO_LINK_ASSOC) {
mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS_PENDING;
} else if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS) {
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
bss_conf = mt792x_vif_to_bss_conf(vif, i);
mt7925_mcu_uni_bss_ps(dev, bss_conf);
}
}
}
}
@@ -1934,11 +1989,12 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
mt7925_mcu_set_tx(dev, info);
if (changed & BSS_CHANGED_BSSID) {
if (ieee80211_vif_is_mld(vif) &&
hweight16(mvif->valid_links) == 2)
/* Indicate the secondary setup done */
mt7925_mcu_uni_bss_bcnft(dev, info, true);
if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS_PENDING) {
/* Indicate the secondary setup done */
mt7925_mcu_uni_bss_bcnft(dev, info, true);
ieee80211_queue_delayed_work(hw, &dev->mlo_pm_work, 5 * HZ);
mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;
}
mt792x_mutex_release(dev);
@@ -2022,8 +2078,6 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto free;
if (mconf != &mvif->bss_conf) {
mt7925_mcu_set_bss_pm(dev, link_conf, true);
err = mt7925_set_mlo_roc(phy, &mvif->bss_conf,
vif->active_links);
if (err < 0)

View File

@@ -348,14 +348,10 @@ mt7925_mcu_handle_hif_ctrl_basic(struct mt792x_dev *dev, struct tlv *tlv)
basic = (struct mt7925_mcu_hif_ctrl_basic_tlv *)tlv;
if (basic->hifsuspend) {
if (basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE &&
basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)
/* success */
dev->hif_idle = true;
else
/* busy */
/* invalid */
dev->hif_idle = false;
dev->hif_idle = true;
if (!(basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE &&
basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE))
dev_info(dev->mt76.dev, "Hif traffic not idle.\n");
} else {
dev->hif_resumed = true;
}
@@ -576,10 +572,10 @@ void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
static int
mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
struct mt76_wcid *wcid,
struct ieee80211_ampdu_params *params,
bool enable, bool tx)
{
struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
struct sta_rec_ba_uni *ba;
struct sk_buff *skb;
struct tlv *tlv;
@@ -607,60 +603,76 @@ mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
/** starec & wtbl **/
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params,
bool enable)
{
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_link_sta *mlink;
struct mt792x_bss_conf *mconf;
unsigned long usable_links = ieee80211_vif_usable_links(vif);
struct mt76_wcid *wcid;
u8 link_id, ret;
struct mt792x_vif *mvif = msta->vif;
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
mconf = mt792x_vif_to_link(mvif, link_id);
mlink = mt792x_sta_to_link(msta, link_id);
wcid = &mlink->wcid;
if (enable && !params->amsdu)
msta->deflink.wcid.amsdu = false;
if (enable && !params->amsdu)
mlink->wcid.amsdu = false;
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
enable, true);
if (ret < 0)
break;
}
return ret;
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
enable, true);
}
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params,
bool enable)
{
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_link_sta *mlink;
struct mt792x_bss_conf *mconf;
unsigned long usable_links = ieee80211_vif_usable_links(vif);
struct mt76_wcid *wcid;
u8 link_id, ret;
struct mt792x_vif *mvif = msta->vif;
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
mconf = mt792x_vif_to_link(mvif, link_id);
mlink = mt792x_sta_to_link(msta, link_id);
wcid = &mlink->wcid;
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
enable, false);
}
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
enable, false);
if (ret < 0)
break;
}
static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)
{
struct {
u8 rsv[4];
return ret;
__le16 tag;
__le16 len;
__le32 addr;
__le32 valid;
u8 data[MT7925_EEPROM_BLOCK_SIZE];
} __packed req = {
.tag = cpu_to_le16(1),
.len = cpu_to_le16(sizeof(req) - 4),
.addr = cpu_to_le32(round_down(offset,
MT7925_EEPROM_BLOCK_SIZE)),
};
struct evt {
u8 rsv[4];
__le16 tag;
__le16 len;
__le32 ver;
__le32 addr;
__le32 valid;
__le32 size;
__le32 magic_num;
__le32 type;
__le32 rsv1[4];
u8 data[32];
} __packed *res;
struct sk_buff *skb;
int ret;
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
&req, sizeof(req), true, &skb);
if (ret)
return ret;
res = (struct evt *)skb->data;
*val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE];
dev_kfree_skb(skb);
return 0;
}
static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
@@ -671,13 +683,21 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
struct mt76_dev *mdev = &dev->mt76;
struct mt792x_phy *phy = &dev->phy;
const struct firmware *fw;
u8 *clc_base = NULL, hw_encap = 0;
int ret, i, len, offset = 0;
u8 *clc_base = NULL;
dev->phy.clc_chan_conf = 0xff;
if (mt7925_disable_clc ||
mt76_is_usb(&dev->mt76))
return 0;
if (mt76_is_mmio(&dev->mt76)) {
ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap);
if (ret)
return ret;
hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP);
}
ret = request_firmware(&fw, fw_name, mdev->dev);
if (ret)
return ret;
@@ -722,6 +742,12 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
if (phy->clc[clc->idx])
continue;
/* header content sanity */
if ((clc->idx == MT792x_CLC_BE_CTRL &&
u8_get_bits(clc->t2.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) ||
u8_get_bits(clc->t0.type, MT_EE_HW_TYPE_ENCAP) != hw_encap)
continue;
phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,
le32_to_cpu(clc->len),
GFP_KERNEL);
@@ -828,7 +854,6 @@ mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data)
mdev->phy.chainmask = mdev->phy.antenna_mask;
mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
dev->has_eht = cap->eht;
}
static void
@@ -1850,49 +1875,6 @@ mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,
}
}
static int
mt7925_mcu_sta_cmd(struct mt76_phy *phy,
struct mt76_sta_cmd_info *info)
{
struct mt76_vif_link *mvif = (struct mt76_vif_link *)info->vif->drv_priv;
struct mt76_dev *dev = phy->dev;
struct sk_buff *skb;
int conn_state;
skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid,
MT7925_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
CONN_STATE_DISCONNECT;
if (info->link_sta)
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
info->link_sta,
conn_state, info->newly);
if (info->link_sta && info->enable) {
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);
mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta);
mt7925_mcu_sta_he_tlv(skb, info->link_sta);
mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif,
info->link_sta);
mt7925_mcu_sta_state_v2_tlv(phy, skb, info->link_sta,
info->vif, info->rcpi,
info->state);
mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);
}
if (info->enable)
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
}
static void
mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)
{
@@ -1905,8 +1887,8 @@ mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)
}
static int
mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
struct mt76_sta_cmd_info *info)
mt7925_mcu_sta_cmd(struct mt76_phy *phy,
struct mt76_sta_cmd_info *info)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
struct mt76_dev *dev = phy->dev;
@@ -1920,12 +1902,10 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
if (IS_ERR(skb))
return PTR_ERR(skb);
if (info->enable)
if (info->enable && info->link_sta) {
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
info->link_sta,
info->enable, info->newly);
if (info->enable && info->link_sta) {
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
@@ -1976,25 +1956,15 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
};
struct mt792x_sta *msta;
struct mt792x_link_sta *mlink;
int err;
if (link_sta) {
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
}
info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
if (link_sta)
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
else
info.newly = state == MT76_STA_INFO_STATE_ASSOC ? false : true;
if (ieee80211_vif_is_mld(vif))
err = mt7925_mcu_mlo_sta_cmd(&dev->mphy, &info);
else
err = mt7925_mcu_sta_cmd(&dev->mphy, &info);
return err;
return mt7925_mcu_sta_cmd(&dev->mphy, &info);
}
int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
@@ -2559,6 +2529,7 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif = link_conf->vif;
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
struct mt792x_phy *phy = mvif->phy;
struct bss_mld_tlv *mld;
struct tlv *tlv;
bool is_mld;
@@ -2574,8 +2545,13 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
mld->group_mld_id = is_mld ? mvif->bss_conf.mt76.idx : 0xff;
mld->own_mld_id = mconf->mt76.idx + 32;
mld->remap_idx = 0xff;
mld->eml_enable = !!(link_conf->vif->cfg.eml_cap &
IEEE80211_EML_CAP_EMLSR_SUPP);
if (phy->chip_cap & MT792x_CHIP_CAP_MLO_EML_EN) {
mld->eml_enable = !!(link_conf->vif->cfg.eml_cap &
IEEE80211_EML_CAP_EMLSR_SUPP);
} else {
mld->eml_enable = 0;
}
memcpy(mld->mac_addr, vif->addr, ETH_ALEN);
}
@@ -2668,6 +2644,62 @@ int mt7925_mcu_set_timing(struct mt792x_phy *phy,
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
}
void mt7925_mcu_del_dev(struct mt76_dev *mdev,
struct ieee80211_vif *vif)
{
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
struct {
struct {
u8 omac_idx;
u8 band_idx;
__le16 pad;
} __packed hdr;
struct req_tlv {
__le16 tag;
__le16 len;
u8 active;
u8 link_idx; /* hw link idx */
u8 omac_addr[ETH_ALEN];
} __packed tlv;
} dev_req = {
.tlv = {
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
.len = cpu_to_le16(sizeof(struct req_tlv)),
.active = true,
},
};
struct {
struct {
u8 bss_idx;
u8 pad[3];
} __packed hdr;
struct mt76_connac_bss_basic_tlv basic;
} basic_req = {
.basic = {
.tag = cpu_to_le16(UNI_BSS_INFO_BASIC),
.len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)),
.active = true,
.conn_state = 1,
},
};
dev_req.hdr.omac_idx = mvif->omac_idx;
dev_req.hdr.band_idx = mvif->band_idx;
basic_req.hdr.bss_idx = mvif->idx;
basic_req.basic.omac_idx = mvif->omac_idx;
basic_req.basic.band_idx = mvif->band_idx;
basic_req.basic.link_idx = mvif->link_idx;
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE),
&basic_req, sizeof(basic_req), true);
/* recovery omac address for the legacy interface */
memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN);
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE),
&dev_req, sizeof(dev_req), true);
}
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
struct ieee80211_chanctx_conf *ctx,
struct ieee80211_bss_conf *link_conf,
@@ -3155,16 +3187,17 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
.idx = idx,
.env = env_cap,
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
};
int ret, valid_cnt = 0;
u8 i, *pos;
u8 *pos, *last_pos;
if (!clc)
return 0;
pos = clc->data + sizeof(*seg) * clc->nr_seg;
for (i = 0; i < clc->nr_country; i++) {
req.ver = clc->ver;
pos = clc->data + sizeof(*seg) * clc->t0.nr_seg;
last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4));
while (pos < last_pos) {
struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos;
pos += sizeof(*rule);
@@ -3179,6 +3212,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
memcpy(req.type, rule->type, 2);
req.size = cpu_to_le16(seg->len);
dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;
skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,
le16_to_cpu(req.size) + sizeof(req),
sizeof(req), GFP_KERNEL);
@@ -3194,8 +3228,10 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
valid_cnt++;
}
if (!valid_cnt)
if (!valid_cnt) {
dev->phy.clc_chan_conf = 0xff;
return -ENOENT;
}
return 0;
}
@@ -3208,6 +3244,9 @@ int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
/* submit all clc config */
for (i = 0; i < ARRAY_SIZE(phy->clc); i++) {
if (i == MT792x_CLC_BE_CTRL)
continue;
ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap,
phy->clc[i], i);
@@ -3266,6 +3305,9 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
else
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
if (cmd == MCU_UNI_CMD(HIF_CTRL))
uni_txd->option &= ~MCU_CMD_ACK;
goto exit;
}

View File

@@ -566,8 +566,8 @@ struct mt7925_wow_pattern_tlv {
u8 offset;
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
u8 rsv[7];
} __packed;
u8 rsv[4];
};
struct roc_acquire_tlv {
__le16 tag;
@@ -627,6 +627,8 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
struct ieee80211_vif *vif,
bool enable);
void mt7925_mcu_del_dev(struct mt76_dev *mdev,
struct ieee80211_vif *vif);
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
struct ieee80211_chanctx_conf *ctx,
struct ieee80211_bss_conf *link_conf,

View File

@@ -137,11 +137,18 @@ enum {
MT7925_CLC_MAX_NUM,
};
struct mt7925_clc_rule_v2 {
u32 flag;
u8 alpha2[2];
u8 rsv[10];
} __packed;
struct mt7925_clc_rule {
u8 alpha2[2];
u8 type[2];
u8 seg_idx;
u8 rsv[3];
u8 flag; /* UNII4~8 ctrl flag */
u8 rsv[2];
} __packed;
struct mt7925_clc_segment {
@@ -152,14 +159,26 @@ struct mt7925_clc_segment {
u8 rsv2[4];
} __packed;
struct mt7925_clc {
__le32 len;
u8 idx;
u8 ver;
struct mt7925_clc_type0 {
u8 nr_country;
u8 type;
u8 nr_seg;
u8 rsv[7];
} __packed;
struct mt7925_clc_type2 {
u8 type;
u8 rsv[9];
} __packed;
struct mt7925_clc {
__le32 len;
u8 idx;
u8 ver;
union {
struct mt7925_clc_type0 t0;
struct mt7925_clc_type2 t2;
};
u8 data[];
} __packed;
@@ -167,9 +186,12 @@ enum mt7925_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_HW_TYPE = 0xa71,
__MT_EE_MAX = 0x9ff
};
#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0)
enum {
TXPWR_USER,
TXPWR_EEPROM,
@@ -235,6 +257,7 @@ int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd);
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2);
void mt7925_regd_update(struct mt792x_dev *dev);
int mt7925_mac_init(struct mt792x_dev *dev);
int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -263,13 +286,12 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
bool enable);
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params,
bool enable);
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params,
bool enable);
void mt7925_mlo_pm_work(struct work_struct *work);
void mt7925_scan_work(struct work_struct *work);
void mt7925_roc_work(struct work_struct *work);
int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,

View File

@@ -27,8 +27,9 @@
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
#define MT792x_CHIP_CAP_MLO_EVT_EN BIT(2)
#define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3)
#define MT792x_CHIP_CAP_MLO_EN BIT(8)
#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 11
@@ -70,6 +71,7 @@ struct mt792x_fw_features {
enum {
MT792x_CLC_POWER,
MT792x_CLC_POWER_EXT,
MT792x_CLC_BE_CTRL,
MT792x_CLC_MAX_NUM,
};
@@ -81,6 +83,13 @@ enum mt792x_reg_power_type {
MT_AP_VLP,
};
enum mt792x_mlo_pm_state {
MT792x_MLO_LINK_DISASSOC,
MT792x_MLO_LINK_ASSOC,
MT792x_MLO_CHANGED_PS_PENDING,
MT792x_MLO_CHANGED_PS,
};
DECLARE_EWMA(avg_signal, 10, 8)
struct mt792x_link_sta {
@@ -134,6 +143,7 @@ struct mt792x_vif {
struct mt792x_phy *phy;
u16 valid_links;
u8 deflink_id;
enum mt792x_mlo_pm_state mlo_pm_state;
struct work_struct csa_work;
struct timer_list csa_timer;
@@ -239,6 +249,7 @@ struct mt792x_dev {
const struct mt792x_irq_map *irq_map;
struct work_struct ipv6_ns_work;
struct delayed_work mlo_pm_work;
/* IPv6 addresses for WoWLAN */
struct sk_buff_head ipv6_ns_list;
@@ -497,7 +508,7 @@ int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev);
int mt792x_init_acpi_sar(struct mt792x_dev *dev);
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default);
u8 mt792x_acpi_get_flags(struct mt792x_phy *phy);
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2);
u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2);
#else
static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev)
{
@@ -515,9 +526,9 @@ static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
return 0;
}
static inline u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
static inline u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
{
return 0xf;
return MT792X_ACPI_MTCL_INVALID;
}
#endif

View File

@@ -4,6 +4,28 @@
#include <linux/acpi.h>
#include "mt792x.h"
static const char * const cc_list_all[] = {
"00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
"CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
"MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
"TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
};
static const char * const cc_list_eu[] = {
"AD", "AT", "BE", "BG", "CY", "CZ", "HR", "DK",
"EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE",
"IT", "LV", "LI", "LT", "LU", "MC", "MT", "NL",
"NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE",
"CH",
};
static const char * const cc_list_be[] = {
"AR", "BR", "BY", "CL", "IQ", "MX", "OM", "RU",
"RW", "VN", "KR", "UA", "", "", "", "",
"EU", "AT", "CN", "CA", "TW", "NZ", "PH", "UK",
"US",
};
static int
mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
{
@@ -66,13 +88,22 @@ mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
}
/* MTCL : Country List Table for 6G band */
/* MTCL : Country List Table for 6G band and 11BE */
static int
mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
{
int ret;
int len, ret;
*version = ((ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL)) < 0)
? 1 : 2;
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, &len);
if (ret)
return ret;
if (len == sizeof(struct mt792x_asar_cl))
*version = ((struct mt792x_asar_cl *)*table)->version;
else if (len == sizeof(struct mt792x_asar_cl_v3))
*version = ((struct mt792x_asar_cl_v3 *)*table)->version;
else
return -EINVAL;
return ret;
}
@@ -351,10 +382,24 @@ u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
static u8
static u32
mt792x_acpi_get_mtcl_map_v3(int row, int column, struct mt792x_asar_cl_v3 *cl)
{
u32 config = 0;
u8 mode_be = 0;
mode_be = (cl->mode_be > 0x02) ? 0 : cl->mode_be;
if (cl->version > 2 && cl->clbe[row] & BIT(column))
config |= (mode_be & 0x3) << 4;
return config;
}
static u32
mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
{
u8 config = 0;
u32 config = 0;
u8 mode_6g, mode_5g9;
mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g;
@@ -368,30 +413,44 @@ mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
return config;
}
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
static u32
mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy *phy, char *alpha2)
{
static const char * const cc_list_all[] = {
"00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
"CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
"MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
"TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
};
static const char * const cc_list_eu[] = {
"AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE",
"FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT",
"LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL",
"PT", "RO", "SK", "SI", "ES", "SE", "CH",
};
struct mt792x_acpi_sar *sar = phy->acpisar;
struct mt792x_asar_cl *cl;
struct mt792x_asar_cl_v3 *cl = sar->countrylist_v3;
int col, row, i;
if (!sar)
return 0xf;
if (sar->ver != 3)
goto out;
cl = sar->countrylist;
if (!cl)
return 0xc;
return MT792X_ACPI_MTCL_INVALID;
for (i = 0; i < ARRAY_SIZE(cc_list_be); i++) {
col = 7 - i % 8;
row = i / 8;
if (!memcmp(cc_list_be[i], alpha2, 2))
return mt792x_acpi_get_mtcl_map_v3(row, col, cl);
}
for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++) {
if (!memcmp(cc_list_eu[i], alpha2, 2))
return mt792x_acpi_get_mtcl_map_v3(3, 7, cl);
}
out:
/* Depends on driver */
return 0x20;
}
static u32
mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy *phy, char *alpha2)
{
struct mt792x_acpi_sar *sar = phy->acpisar;
struct mt792x_asar_cl *cl = sar->countrylist;
int col, row, i;
if (!cl)
return MT792X_ACPI_MTCL_INVALID;
for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) {
col = 7 - i % 8;
@@ -406,4 +465,22 @@ u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
return mt792x_acpi_get_mtcl_map(0, 7, cl);
}
u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
{
struct mt792x_acpi_sar *sar = phy->acpisar;
u32 config = 0;
if (!sar)
return MT792X_ACPI_MTCL_INVALID;
config = mt792x_acpi_parse_mtcl_tbl_v3(phy, alpha2);
if (config == MT792X_ACPI_MTCL_INVALID)
return MT792X_ACPI_MTCL_INVALID;
config |= mt792x_acpi_parse_mtcl_tbl(phy, alpha2);
return config;
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf);

View File

@@ -15,6 +15,8 @@
#define MT792x_ACPI_MTGS "MTGS"
#define MT792x_ACPI_MTFG "MTFG"
#define MT792X_ACPI_MTCL_INVALID 0xffffffff
struct mt792x_asar_dyn_limit {
u8 idx;
u8 frp[5];
@@ -72,6 +74,17 @@ struct mt792x_asar_geo_v2 {
DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl);
} __packed;
struct mt792x_asar_cl_v3 {
u8 names[4];
u8 version;
u8 mode_6g;
u8 cl6g[6];
u8 mode_5g9;
u8 cl5g9[6];
u8 mode_be;
u8 clbe[6];
} __packed;
struct mt792x_asar_cl {
u8 names[4];
u8 version;
@@ -100,7 +113,10 @@ struct mt792x_acpi_sar {
struct mt792x_asar_geo *geo;
struct mt792x_asar_geo_v2 *geo_v2;
};
struct mt792x_asar_cl *countrylist;
union {
struct mt792x_asar_cl *countrylist;
struct mt792x_asar_cl_v3 *countrylist_v3;
};
struct mt792x_asar_fg *fg;
};

View File

@@ -665,7 +665,8 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
ieee80211_hw_set(hw, CONNECTION_MONITOR);
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
if (is_mt7921(&dev->mt76))
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
if (dev->pm.enable)
ieee80211_hw_set(hw, CONNECTION_MONITOR);

View File

@@ -616,28 +616,51 @@ static void
mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
{
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
struct mt7996_vif *mvif = msta->vif;
struct mt7996_dev *dev = mvif->deflink.phy->dev;
struct ieee80211_link_sta *link_sta;
struct seq_file *s = data;
u8 ac;
struct ieee80211_vif *vif;
unsigned int link_id;
for (ac = 0; ac < 4; ac++) {
u32 qlen, ctrl, val;
u32 idx = msta->wcid.idx >> 5;
u8 offs = msta->wcid.idx & GENMASK(4, 0);
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
ctrl = BIT(31) | BIT(11) | (ac << 24);
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
rcu_read_lock();
if (val & BIT(offs))
for_each_sta_active_link(vif, sta, link_sta, link_id) {
struct mt7996_sta_link *msta_link;
struct mt76_vif_link *mlink;
u8 ac;
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (!mlink)
continue;
mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx);
qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
GENMASK(11, 0));
seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
sta->addr, msta->wcid.idx,
msta->vif->deflink.mt76.wmm_idx, ac, qlen);
msta_link = rcu_dereference(msta->link[link_id]);
if (!msta_link)
continue;
for (ac = 0; ac < 4; ac++) {
u32 idx = msta_link->wcid.idx >> 5, qlen, ctrl, val;
u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
ctrl = BIT(31) | BIT(11) | (ac << 24);
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
if (val & BIT(offs))
continue;
mt76_wr(dev,
MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
GENMASK(11, 0));
seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
sta->addr, msta_link->wcid.idx,
mlink->wmm_idx, ac, qlen);
}
}
rcu_read_unlock();
}
static int
@@ -930,6 +953,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
struct ieee80211_sta *sta = file->private_data;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
struct mt7996_sta_link *msta_link = &msta->deflink;
struct ra_rate phy = {};
char buf[100];
int ret;
@@ -964,7 +988,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
goto out;
}
phy.wlan_idx = cpu_to_le16(msta->wcid.idx);
phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
phy.gi = cpu_to_le16(gi);
phy.ltf = cpu_to_le16(ltf);
phy.ldpc = phy.ldpc ? 7 : 0;

View File

@@ -53,26 +53,48 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = {
};
static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
u16 idx, bool unicast)
u16 idx, u8 band_idx)
{
struct mt7996_sta *sta;
struct mt7996_sta_link *msta_link;
struct mt7996_sta *msta;
struct mt7996_vif *mvif;
struct mt76_wcid *wcid;
int i;
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
return NULL;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
if (unicast || !wcid)
if (!wcid)
return NULL;
if (!mt7996_band_valid(dev, band_idx))
return NULL;
if (wcid->phy_idx == band_idx)
return wcid;
if (!wcid->sta)
msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
msta = msta_link->sta;
if (!msta || !msta->vif)
return NULL;
sta = container_of(wcid, struct mt7996_sta, wcid);
if (!sta->vif)
return NULL;
mvif = msta->vif;
for (i = 0; i < ARRAY_SIZE(mvif->mt76.link); i++) {
struct mt76_vif_link *mlink;
return &sta->vif->deflink.sta.wcid;
mlink = rcu_dereference(mvif->mt76.link[i]);
if (!mlink)
continue;
if (mlink->band_idx != band_idx)
continue;
msta_link = rcu_dereference(msta->link[i]);
break;
}
return &msta_link->wcid;
}
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
@@ -100,10 +122,13 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
[IEEE80211_AC_VI] = 4,
[IEEE80211_AC_VO] = 6
};
struct mt7996_sta_link *msta_link;
struct mt76_vif_link *mlink;
struct ieee80211_sta *sta;
struct mt7996_sta *msta;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
struct mt76_wcid *wcid;
int i;
spin_lock_bh(&dev->mt76.sta_poll_lock);
@@ -123,25 +148,28 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
spin_unlock_bh(&dev->mt76.sta_poll_lock);
break;
}
msta = list_first_entry(&sta_poll_list,
struct mt7996_sta, wcid.poll_list);
list_del_init(&msta->wcid.poll_list);
msta_link = list_first_entry(&sta_poll_list,
struct mt7996_sta_link,
wcid.poll_list);
msta = msta_link->sta;
wcid = &msta_link->wcid;
list_del_init(&wcid->poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
idx = msta->wcid.idx;
idx = wcid->idx;
/* refresh peer's airtime reporting */
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
u32 tx_last = msta->airtime_ac[i];
u32 rx_last = msta->airtime_ac[i + 4];
u32 tx_last = msta_link->airtime_ac[i];
u32 rx_last = msta_link->airtime_ac[i + 4];
msta->airtime_ac[i] = mt76_rr(dev, addr);
msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
msta_link->airtime_ac[i] = mt76_rr(dev, addr);
msta_link->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
tx_time[i] = msta->airtime_ac[i] - tx_last;
rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
tx_time[i] = msta_link->airtime_ac[i] - tx_last;
rx_time[i] = msta_link->airtime_ac[i + 4] - rx_last;
if ((tx_last | rx_last) & BIT(30))
clear = true;
@@ -152,10 +180,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
if (clear) {
mt7996_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
memset(msta_link->airtime_ac, 0,
sizeof(msta_link->airtime_ac));
}
if (!msta->wcid.sta)
if (!wcid->sta)
continue;
sta = container_of((void *)msta, struct ieee80211_sta,
@@ -181,28 +210,23 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
rssi[2] = to_rssi(GENMASK(23, 16), val);
rssi[3] = to_rssi(GENMASK(31, 14), val);
msta->ack_signal =
mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
mlink = rcu_dereference(msta->vif->mt76.link[wcid->link_id]);
if (mlink) {
struct mt76_phy *mphy = mt76_vif_link_phy(mlink);
ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
if (mphy)
msta_link->ack_signal =
mt76_rx_signal(mphy->antenna_mask,
rssi);
}
ewma_avg_signal_add(&msta_link->avg_ack_signal,
-msta_link->ack_signal);
}
rcu_read_unlock();
}
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
u32 addr;
addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->deflink.sta.wcid.idx, 5);
if (enable)
mt76_set(dev, addr, BIT(5));
else
mt76_clear(dev, addr, BIT(5));
}
/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
@@ -474,11 +498,15 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
status->wcid = mt7996_rx_get_wcid(dev, idx, band_idx);
if (status->wcid) {
msta = container_of(status->wcid, struct mt7996_sta, wcid);
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
struct mt7996_sta_link *msta_link;
msta_link = container_of(status->wcid, struct mt7996_sta_link,
wcid);
msta = msta_link->sta;
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
}
status->freq = mphy->chandef.chan->center_freq;
@@ -717,9 +745,8 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
u32 val;
if (wcid->sta) {
struct ieee80211_sta *sta;
struct ieee80211_sta *sta = wcid_to_sta(wcid);
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
wmm = sta->wme;
}
@@ -746,7 +773,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
static void
mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct ieee80211_key_conf *key)
struct sk_buff *skb,
struct ieee80211_key_conf *key,
struct mt76_wcid *wcid)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -754,6 +783,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
bool multicast = is_multicast_ether_addr(hdr->addr1);
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
u16 seqno = le16_to_cpu(sc);
u8 fc_type, fc_stype;
u32 val;
@@ -773,8 +803,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
val |= MT_TXD1_FIXED_RATE;
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) {
val |= MT_TXD1_BIP;
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
}
@@ -804,9 +833,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
}
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
u16 seqno = le16_to_cpu(sc);
if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
val = MT_TXD3_SN_VALID |
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
txwi[3] |= cpu_to_le32(val);
}
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
if (ieee80211_is_back_req(hdr->frame_control)) {
struct ieee80211_bar *bar;
@@ -819,6 +852,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
txwi[3] |= cpu_to_le32(val);
txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
}
if (ieee80211_vif_is_mld(info->control.vif) &&
(multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
ieee80211_vif_is_mld(info->control.vif)) {
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
}
if (!wcid->sta && ieee80211_is_mgmt(fc))
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
}
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
@@ -832,7 +878,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
struct mt76_vif_link *mvif;
struct mt76_vif_link *mlink = NULL;
struct mt7996_vif *mvif;
unsigned int link_id;
u16 tx_count = 15;
u32 val;
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
@@ -840,11 +888,20 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
if (mvif) {
omac_idx = mvif->omac_idx;
wmm_idx = mvif->wmm_idx;
band_idx = mvif->band_idx;
if (wcid != &dev->mt76.global_wcid)
link_id = wcid->link_id;
else
link_id = u32_get_bits(info->control.flags,
IEEE80211_TX_CTRL_MLO_LINK);
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
if (mvif)
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (mlink) {
omac_idx = mlink->omac_idx;
wmm_idx = mlink->wmm_idx;
band_idx = mlink->band_idx;
}
if (inband_disc) {
@@ -891,7 +948,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
val |= MT_TXD5_TX_STATUS_HOST;
txwi[5] = cpu_to_le32(val);
val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
val = MT_TXD6_DAS;
if (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
val |= MT_TXD6_DIS_MAT;
if (is_mt7996(&dev->mt76))
val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control))
@@ -903,23 +963,25 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
if (is_8023)
mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
else
mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
mt7996_mac_write_txwi_80211(dev, txwi, skb, key, wcid);
if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
bool mcast = ieee80211_is_data(hdr->frame_control) &&
is_multicast_ether_addr(hdr->addr1);
u8 idx = MT7996_BASIC_RATES_TBL;
if (mvif) {
if (mcast && mvif->mcast_rates_idx)
idx = mvif->mcast_rates_idx;
else if (beacon && mvif->beacon_rates_idx)
idx = mvif->beacon_rates_idx;
if (mlink) {
if (mcast && mlink->mcast_rates_idx)
idx = mlink->mcast_rates_idx;
else if (beacon && mlink->beacon_rates_idx)
idx = mlink->beacon_rates_idx;
else
idx = mvif->basic_rates_idx;
idx = mlink->basic_rates_idx;
}
val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
if (mcast)
val |= MT_TXD6_DIS_MAT;
txwi[6] |= cpu_to_le32(val);
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
@@ -984,8 +1046,14 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (vif) {
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_vif_link *mlink = NULL;
txp->fw.bss_idx = mvif->deflink.mt76.idx;
if (wcid->offchannel)
mlink = rcu_dereference(mvif->mt76.offchannel_link);
if (!mlink)
mlink = &mvif->deflink.mt76;
txp->fw.bss_idx = mlink->idx;
}
txp->fw.token = cpu_to_le16(id);
@@ -1027,9 +1095,10 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
static void
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
{
struct mt7996_sta *msta;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
struct mt7996_sta_link *msta_link;
struct mt7996_sta *msta;
u16 fc, tid;
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
@@ -1058,7 +1127,9 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
return;
msta = (struct mt7996_sta *)sta->drv_priv;
if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
msta_link = &msta->deflink;
if (!test_and_set_bit(tid, &msta_link->wcid.ampdu_state))
ieee80211_start_tx_ba_session(sta, tid, 0);
}
@@ -1136,7 +1207,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
*/
info = le32_to_cpu(*cur_info);
if (info & MT_TXFREE_INFO_PAIR) {
struct mt7996_sta *msta;
struct mt7996_sta_link *msta_link;
u16 idx;
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
@@ -1145,8 +1216,9 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
if (!sta)
continue;
msta = container_of(wcid, struct mt7996_sta, wcid);
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
msta_link = container_of(wcid, struct mt7996_sta_link,
wcid);
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
continue;
} else if (info & MT_TXFREE_INFO_HEADER) {
u32 tx_retries = 0, tx_failed = 0;
@@ -1230,7 +1302,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_sta *sta;
u8 tid;
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
sta = wcid_to_sta(wcid);
tid = FIELD_GET(MT_TXS0_TID, txs);
ieee80211_refresh_tx_agg_session_timer(sta, tid);
}
@@ -1344,7 +1416,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
{
struct mt7996_sta *msta = NULL;
struct mt7996_sta_link *msta_link;
struct mt76_wcid *wcid;
__le32 *txs_data = data;
u16 wcidx;
@@ -1365,14 +1437,13 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
if (!wcid)
goto out;
msta = container_of(wcid, struct mt7996_sta, wcid);
mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
if (!wcid->sta)
goto out;
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
out:
rcu_read_unlock();
@@ -1399,7 +1470,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
mt7996_mac_tx_free(dev, data, len);
return false;
case PKT_TYPE_TXS:
for (rxd += 4; rxd + 8 <= end; rxd += 8)
for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
mt7996_mac_add_txs(dev, rxd);
return false;
case PKT_TYPE_RX_FW_MONITOR:
@@ -1442,7 +1513,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
mt7996_mcu_rx_event(dev, skb);
break;
case PKT_TYPE_TXS:
for (rxd += 4; rxd + 8 <= end; rxd += 8)
for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
mt7996_mac_add_txs(dev, rxd);
dev_kfree_skb(skb);
break;
@@ -2239,38 +2310,69 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
void mt7996_mac_sta_rc_work(struct work_struct *work)
{
struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct mt7996_sta_link *msta_link;
struct mt7996_vif_link *link;
struct mt76_vif_link *mlink;
struct ieee80211_sta *sta;
struct ieee80211_vif *vif;
struct mt7996_sta *msta;
u32 changed;
struct mt7996_vif *mvif;
LIST_HEAD(list);
u32 changed;
u8 link_id;
rcu_read_lock();
spin_lock_bh(&dev->mt76.sta_poll_lock);
list_splice_init(&dev->sta_rc_list, &list);
while (!list_empty(&list)) {
msta = list_first_entry(&list, struct mt7996_sta, rc_list);
list_del_init(&msta->rc_list);
changed = msta->changed;
msta->changed = 0;
msta_link = list_first_entry(&list, struct mt7996_sta_link,
rc_list);
list_del_init(&msta_link->rc_list);
changed = msta_link->changed;
msta_link->changed = 0;
spin_unlock_bh(&dev->mt76.sta_poll_lock);
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
sta = wcid_to_sta(&msta_link->wcid);
link_id = msta_link->wcid.link_id;
msta = msta_link->sta;
mvif = msta->vif;
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
mlink = rcu_dereference(mvif->mt76.link[link_id]);
if (!mlink)
continue;
link_sta = rcu_dereference(sta->link[link_id]);
if (!link_sta)
continue;
link_conf = rcu_dereference(vif->link_conf[link_id]);
if (!link_conf)
continue;
link = (struct mt7996_vif_link *)mlink;
if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
IEEE80211_RC_NSS_CHANGED |
IEEE80211_RC_BW_CHANGED))
mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
mt7996_mcu_add_rate_ctrl(dev, vif, link_conf,
link_sta, link, msta_link,
true);
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
mt7996_mcu_set_fixed_field(dev, link_sta, link,
msta_link, NULL,
RATE_PARAM_MMPS_UPDATE);
spin_lock_bh(&dev->mt76.sta_poll_lock);
}
spin_unlock_bh(&dev->mt76.sta_poll_lock);
rcu_read_unlock();
}
void mt7996_mac_work(struct work_struct *work)
@@ -2538,7 +2640,7 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
}
static bool
mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
mt7996_mac_twt_param_equal(struct mt7996_sta_link *msta_link,
struct ieee80211_twt_params *twt_agrt)
{
u16 type = le16_to_cpu(twt_agrt->req_type);
@@ -2549,10 +2651,10 @@ mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
struct mt7996_twt_flow *f;
if (!(msta->twt.flowid_mask & BIT(i)))
if (!(msta_link->twt.flowid_mask & BIT(i)))
continue;
f = &msta->twt.flow[i];
f = &msta_link->twt.flow[i];
if (f->duration == twt_agrt->min_twt_dur &&
f->mantissa == twt_agrt->mantissa &&
f->exp == exp &&
@@ -2572,6 +2674,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
struct mt7996_sta_link *msta_link = &msta->deflink;
u16 req_type = le16_to_cpu(twt_agrt->req_type);
enum ieee80211_twt_setup_cmd sta_setup_cmd;
struct mt7996_dev *dev = mt7996_hw_dev(hw);
@@ -2586,7 +2689,8 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT)
goto unlock;
if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
if (hweight8(msta_link->twt.flowid_mask) ==
ARRAY_SIZE(msta_link->twt.flow))
goto unlock;
if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
@@ -2595,10 +2699,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
goto unlock;
}
if (mt7996_mac_twt_param_equal(msta, twt_agrt))
if (mt7996_mac_twt_param_equal(msta_link, twt_agrt))
goto unlock;
flowid = ffs(~msta->twt.flowid_mask) - 1;
flowid = ffs(~msta_link->twt.flowid_mask) - 1;
twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
twt_agrt->req_type |= le16_encode_bits(flowid,
IEEE80211_TWT_REQTYPE_FLOWID);
@@ -2607,10 +2711,10 @@ void mt7996_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);
flow = &msta->twt.flow[flowid];
flow = &msta_link->twt.flow[flowid];
memset(flow, 0, sizeof(*flow));
INIT_LIST_HEAD(&flow->list);
flow->wcid = msta->wcid.idx;
flow->wcid = msta_link->wcid.idx;
flow->table_id = table_id;
flow->id = flowid;
flow->duration = twt_agrt->min_twt_dur;
@@ -2628,7 +2732,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
flow->sched = true;
flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow);
curr_tsf = __mt7996_get_tsf(hw, msta->vif);
curr_tsf = __mt7996_get_tsf(hw, &msta->vif->deflink);
div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
flow_tsf = curr_tsf + interval - rem;
twt_agrt->twt = cpu_to_le64(flow_tsf);
@@ -2637,12 +2741,13 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
}
flow->tsf = le64_to_cpu(twt_agrt->twt);
if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow,
MCU_TWT_AGRT_ADD))
goto unlock;
setup_cmd = TWT_SETUP_CMD_ACCEPT;
dev->twt.table_mask |= BIT(table_id);
msta->twt.flowid_mask |= BIT(flowid);
msta_link->twt.flowid_mask |= BIT(flowid);
dev->twt.n_agrt++;
unlock:
@@ -2655,26 +2760,26 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
}
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
struct mt7996_sta *msta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
u8 flowid)
{
struct mt7996_twt_flow *flow;
lockdep_assert_held(&dev->mt76.mutex);
if (flowid >= ARRAY_SIZE(msta->twt.flow))
if (flowid >= ARRAY_SIZE(msta_link->twt.flow))
return;
if (!(msta->twt.flowid_mask & BIT(flowid)))
if (!(msta_link->twt.flowid_mask & BIT(flowid)))
return;
flow = &msta->twt.flow[flowid];
if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow,
MCU_TWT_AGRT_DELETE))
flow = &msta_link->twt.flow[flowid];
if (mt7996_mcu_twt_agrt_update(dev, link, flow, MCU_TWT_AGRT_DELETE))
return;
list_del_init(&flow->list);
msta->twt.flowid_mask &= ~BIT(flowid);
msta_link->twt.flowid_mask &= ~BIT(flowid);
dev->twt.table_mask &= ~BIT(flow->table_id);
dev->twt.n_agrt--;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -625,6 +625,35 @@ struct sta_rec_hdr_trans {
u8 mesh;
} __packed;
struct sta_rec_mld_setup {
__le16 tag;
__le16 len;
u8 mld_addr[ETH_ALEN];
__le16 primary_id;
__le16 seconed_id;
__le16 setup_wcid;
u8 link_num;
u8 info;
u8 __rsv[2];
u8 link_info[];
} __packed;
struct sta_rec_eht_mld {
__le16 tag;
__le16 len;
u8 nsep;
u8 __rsv1[2];
u8 str_cap[__MT_MAX_BAND];
__le16 eml_cap;
u8 __rsv2[4];
} __packed;
struct mld_setup_link {
__le16 wcid;
u8 bss_idx;
u8 __rsv;
} __packed;
struct hdr_trans_en {
__le16 tag;
__le16 len;
@@ -798,6 +827,9 @@ enum {
sizeof(struct sta_rec_eht) + \
sizeof(struct sta_rec_hdrt) + \
sizeof(struct sta_rec_hdr_trans) + \
sizeof(struct sta_rec_mld_setup) + \
sizeof(struct mld_setup_link) * 3 + \
sizeof(struct sta_rec_eht_mld) + \
sizeof(struct tlv))
#define MT7996_MAX_BEACON_SIZE 1338
@@ -809,18 +841,6 @@ enum {
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
MT7996_BEACON_UPDATE_SIZE)
static inline s8
mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
{
struct mt76_phy *mphy = phy->mt76;
int n_chains = hweight16(mphy->chainmask);
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
txpower -= mt76_tx_power_nss_delta(n_chains);
return txpower;
}
enum {
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
@@ -908,7 +928,8 @@ enum {
UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
UNI_CMD_SER_SET_RECOVER_L3_BF,
UNI_CMD_SER_SET_RECOVER_L4_MDP,
UNI_CMD_SER_SET_RECOVER_FULL,
UNI_CMD_SER_SET_RECOVER_FROM_ETH,
UNI_CMD_SER_SET_RECOVER_FULL = 8,
UNI_CMD_SER_SET_SYSTEM_ASSERT,
/* action */
UNI_CMD_SER_ENABLE = 1,

View File

@@ -281,7 +281,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
return -EBUSY;
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH,
mphy->band_idx);
if (ret)
goto out;
@@ -618,9 +618,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
.rx_skb = mt7996_queue_rx_skb,
.rx_check = mt7996_rx_check,
.rx_poll_complete = mt7996_rx_poll_complete,
.sta_add = mt7996_mac_sta_add,
.sta_event = mt7996_mac_sta_event,
.sta_remove = mt7996_mac_sta_remove,
.update_survey = mt7996_update_channel,
.set_channel = mt7996_set_channel,
.vif_link_add = mt7996_vif_link_add,

View File

@@ -185,10 +185,10 @@ struct mt7996_twt_flow {
DECLARE_EWMA(avg_signal, 10, 8)
struct mt7996_sta {
struct mt7996_sta_link {
struct mt76_wcid wcid; /* must be first */
struct mt7996_vif *vif;
struct mt7996_sta *sta;
struct list_head rc_list;
u32 airtime_ac[8];
@@ -204,12 +204,22 @@ struct mt7996_sta {
u8 flowid_mask;
struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
} twt;
struct rcu_head rcu_head;
};
struct mt7996_sta {
struct mt7996_sta_link deflink; /* must be first */
struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
u8 deflink_id;
struct mt7996_vif *vif;
};
struct mt7996_vif_link {
struct mt76_vif_link mt76; /* must be first */
struct mt7996_sta sta;
struct mt7996_sta_link msta_link;
struct mt7996_phy *phy;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
@@ -525,7 +535,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
void __iomem *mem_base, u32 device_id);
void mt7996_wfsys_reset(struct mt7996_dev *dev);
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
int mt7996_register_device(struct mt7996_dev *dev);
void mt7996_unregister_device(struct mt7996_dev *dev);
int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
@@ -553,7 +563,7 @@ int mt7996_run(struct mt7996_phy *phy);
int mt7996_mcu_init(struct mt7996_dev *dev);
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
struct mt7996_vif *mvif,
struct mt7996_vif_link *link,
struct mt7996_twt_flow *flow,
int cmd);
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
@@ -561,35 +571,52 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct mt76_vif_link *mlink, bool enable);
int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt76_vif_link *mlink, int enable);
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct mt76_vif_link *mlink,
struct ieee80211_sta *sta, int conn_state, bool newly);
struct mt76_vif_link *mlink,
struct mt7996_sta_link *msta_link, int enable);
int mt7996_mcu_add_sta(struct mt7996_dev *dev,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
int conn_state, bool newly);
int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link);
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
struct ieee80211_ampdu_params *params,
bool add);
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link, bool enable);
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
struct ieee80211_ampdu_params *params,
bool add);
struct mt7996_vif_link *link, bool enable);
int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
struct mt76_vif_link *mlink,
struct cfg80211_he_bss_color *he_bss_color);
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
struct ieee80211_vif *vif, u32 changed);
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct mt7996_vif_link *link, u32 changed);
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
struct mt7996_vif_link *link,
struct ieee80211_he_obss_pd *he_obss_pd);
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool changed);
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link, bool changed);
int mt7996_set_channel(struct mt76_phy *mphy);
int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
void *data, u16 version);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *data, u32 field);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev,
struct ieee80211_link_sta *link_sta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
void *data, u32 field);
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
@@ -683,26 +710,19 @@ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
void mt7996_mac_reset_counters(struct mt7996_phy *phy);
void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable);
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
enum mt76_txq_id qid, u32 changed);
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, enum mt76_sta_event ev);
void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7996_mac_work(struct work_struct *work);
void mt7996_mac_reset_work(struct work_struct *work);
void mt7996_mac_dump_work(struct work_struct *work);
void mt7996_mac_sta_rc_work(struct work_struct *work);
void mt7996_mac_update_stats(struct mt7996_phy *phy);
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
struct mt7996_sta *msta,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
u8 flowid);
void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
@@ -727,11 +747,14 @@ bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link,
struct ieee80211_key_conf *key);
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link);
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
#ifdef CONFIG_MAC80211_DEBUGFS
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

View File

@@ -52,11 +52,6 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
ether_addr_copy(hdr->addr3, req->bssid);
}
info = IEEE80211_SKB_CB(skb);
if (req->no_cck)
info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
if (req->ie_len)
skb_put_data(skb, req->ie, req->ie_len);
@@ -64,10 +59,20 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
rcu_read_lock();
if (ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL))
mt76_tx(phy, NULL, mvif->wcid, skb);
else
if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) {
ieee80211_free_txskb(phy->hw, skb);
goto out;
}
info = IEEE80211_SKB_CB(skb);
if (req->no_cck)
info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
mt76_tx(phy, NULL, mvif->wcid, skb);
out:
rcu_read_unlock();
}

View File

@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
return;
/* Tx status can be unreliable. if it fails, mark the frame as ACKed */
if (flags & MT_TX_CB_TXS_FAILED) {
if (flags & MT_TX_CB_TXS_FAILED &&
(dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) {
info->status.rates[0].count = 0;
info->status.rates[0].idx = -1;
info->flags |= IEEE80211_TX_STAT_ACK;