mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
wifi: mt76: mt7925: introduce CSA support in non-MLO mode
Add CSA (Channel Switch Announcement) related implementation in collaboration with mac80211 to deal with dynamic channel switching. Signed-off-by: Leon Yen <[email protected]> Signed-off-by: Ming Yen Hsieh <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
+139
@@ -245,6 +245,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
{
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
static const u8 ext_capa_sta[] = {
|
||||
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
|
||||
[2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
|
||||
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
|
||||
};
|
||||
@@ -438,6 +439,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
|
||||
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
||||
INIT_WORK(&mvif->csa_work, mt7925_csa_work);
|
||||
timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0);
|
||||
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
@@ -1749,6 +1753,10 @@ static int
|
||||
mt7925_add_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
dev->new_ctx = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1756,6 +1764,11 @@ static void
|
||||
mt7925_remove_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
if (dev->new_ctx == ctx)
|
||||
dev->new_ctx = NULL;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2144,6 +2157,11 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mctx->bss_conf = NULL;
|
||||
mconf->mt76.ctx = NULL;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (link_conf->csa_active) {
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
|
||||
@@ -2158,6 +2176,121 @@ static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);
|
||||
}
|
||||
|
||||
static int mt7925_switch_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif_chanctx_switch *vifs,
|
||||
int n_vifs,
|
||||
enum ieee80211_chanctx_switch_mode mode)
|
||||
{
|
||||
return mt7925_assign_vif_chanctx(hw, vifs->vif, vifs->link_conf,
|
||||
vifs->new_ctx);
|
||||
}
|
||||
|
||||
void mt7925_csa_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_vif *mvif;
|
||||
struct mt792x_dev *dev;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
u8 link_id, roc_rtype;
|
||||
int ret = 0;
|
||||
|
||||
mvif = (struct mt792x_vif *)container_of(work, struct mt792x_vif,
|
||||
csa_work);
|
||||
dev = mvif->phy->dev;
|
||||
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
if (!dev->new_ctx)
|
||||
return;
|
||||
|
||||
link_id = 0;
|
||||
mconf = &mvif->bss_conf;
|
||||
link_conf = &vif->bss_conf;
|
||||
roc_rtype = MT7925_ROC_REQ_JOIN;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_set_roc(mvif->phy, mconf, dev->new_ctx->def.chan,
|
||||
4000, roc_rtype);
|
||||
mt792x_mutex_release(dev);
|
||||
if (!ret) {
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76, link_conf,
|
||||
dev->new_ctx);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
mt7925_abort_roc(mvif->phy, mconf);
|
||||
}
|
||||
|
||||
ieee80211_chswitch_done(vif, !ret, link_id);
|
||||
}
|
||||
|
||||
static int mt7925_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
{
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
|
||||
IEEE80211_CHAN_DISABLED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7925_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
u16 beacon_interval;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
beacon_interval = vif->bss_conf.beacon_int;
|
||||
|
||||
mvif->csa_timer.expires = TU_TO_EXP_TIME(beacon_interval * chsw->count);
|
||||
add_timer(&mvif->csa_timer);
|
||||
}
|
||||
|
||||
static void mt7925_abort_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
|
||||
static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_channel_switch *chsw)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
u16 beacon_interval;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
beacon_interval = vif->bss_conf.beacon_int;
|
||||
|
||||
if (cfg80211_chandef_identical(&chsw->chandef,
|
||||
&dev->new_ctx->def) &&
|
||||
chsw->count) {
|
||||
mod_timer(&mvif->csa_timer,
|
||||
TU_TO_EXP_TIME(beacon_interval * chsw->count));
|
||||
}
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7925_ops = {
|
||||
.tx = mt792x_tx,
|
||||
.start = mt7925_start,
|
||||
@@ -2221,6 +2354,12 @@ const struct ieee80211_ops mt7925_ops = {
|
||||
.change_vif_links = mt7925_change_vif_links,
|
||||
.change_sta_links = mt7925_change_sta_links,
|
||||
.rfkill_poll = mt7925_rfkill_poll,
|
||||
|
||||
.switch_vif_chanctx = mt7925_switch_vif_chanctx,
|
||||
.pre_channel_switch = mt7925_pre_channel_switch,
|
||||
.channel_switch = mt7925_channel_switch,
|
||||
.abort_channel_switch = mt7925_abort_channel_switch,
|
||||
.channel_switch_rx_beacon = mt7925_channel_switch_rx_beacon,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt7925_ops);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user