summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/channel.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2025-01-02 17:34:55 +0100
committerFelix Fietkau <nbd@nbd.name>2025-01-14 13:42:29 +0100
commite411b8190fe7c969c668eedb5b01f2865c89b1af (patch)
tree8e8ab26fbddf1a70c3432ec628aa6b0863a60348 /drivers/net/wireless/mediatek/mt76/channel.c
parent716cc146d58050cb277fefefe1002d634c4379cf (diff)
wifi: mt76: add multi-radio support to scanning code
When scanning on a phy/vif combination that does not have an active link, create a temporary link in order to ensure that we have a valid wcid. Link: https://patch.msgid.link/20250102163508.52945-11-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/channel.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/channel.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/channel.c b/drivers/net/wireless/mediatek/mt76/channel.c
index 1cfeb09b0054..ddb36e958c33 100644
--- a/drivers/net/wireless/mediatek/mt76/channel.c
+++ b/drivers/net/wireless/mediatek/mt76/channel.c
@@ -4,6 +4,20 @@
*/
#include "mt76.h"
+static struct mt76_vif_link *
+mt76_alloc_mlink(struct mt76_dev *dev, struct mt76_vif_data *mvif)
+{
+ struct mt76_vif_link *mlink;
+
+ mlink = kzalloc(dev->drv->link_data_size, GFP_KERNEL);
+ if (!mlink)
+ return NULL;
+
+ mlink->mvif = mvif;
+
+ return mlink;
+}
+
static int
mt76_phy_update_channel(struct mt76_phy *phy,
struct ieee80211_chanctx_conf *conf)
@@ -108,7 +122,7 @@ int mt76_assign_vif_chanctx(struct ieee80211_hw *hw,
mlink = mt76_vif_conf_link(dev, vif, link_conf);
if (!mlink) {
- mlink = kzalloc(dev->drv->link_data_size, GFP_KERNEL);
+ mlink = mt76_alloc_mlink(dev, mvif);
if (!mlink) {
ret = -ENOMEM;
goto out;
@@ -248,3 +262,49 @@ out:
return ret;
}
EXPORT_SYMBOL_GPL(mt76_switch_vif_chanctx);
+
+struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
+ struct ieee80211_vif *vif)
+{
+ struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
+ struct mt76_vif_data *mvif = mlink->mvif;
+ struct mt76_dev *dev = phy->dev;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(mvif->link); i++) {
+ mlink = mt76_dereference(mvif->link[i], dev);
+ if (!mlink)
+ continue;
+
+ if (mt76_vif_link_phy(mlink) == phy)
+ return mlink;
+ }
+
+ if (!dev->drv->vif_link_add)
+ return ERR_PTR(-EINVAL);
+
+ mlink = mt76_alloc_mlink(dev, mvif);
+ if (!mlink)
+ return ERR_PTR(-ENOMEM);
+
+ mlink->offchannel = true;
+ ret = dev->drv->vif_link_add(phy, vif, &vif->bss_conf, mlink);
+ if (ret) {
+ kfree(mlink);
+ return ERR_PTR(ret);
+ }
+
+ return mlink;
+}
+
+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;
+
+ if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
+ return;
+
+ dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
+ kfree(mlink);
+}