mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-14 01:49:20 -04:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user