Commit 9f8f4a51 authored by Ming Yen Hsieh's avatar Ming Yen Hsieh Committed by Felix Fietkau
Browse files

wifi: mt76: mt7925: fix incorrect scan probe IE handling for hw_scan



The IEs should be processed and filled into the command tlv separately
according to each band.

Cc: stable@vger.kernel.org
Fixes: c948b5da ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: default avatarMing Yen Hsieh <mingyen.hsieh@mediatek.com>
Link: https://patch.msgid.link/20250616063649.1100503-1-mingyen.hsieh@mediatek.com


Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent c701574c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1481,7 +1481,7 @@ mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

	mt792x_mutex_acquire(dev);

	err = mt7925_mcu_sched_scan_req(mphy, vif, req);
	err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);
	if (err < 0)
		goto out;

+59 −16
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
			       bool suspend, struct cfg80211_wowlan *wowlan)
{
	struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
	struct ieee80211_scan_ies ies = {};
	struct mt76_dev *dev = phy->dev;
	struct {
		struct {
@@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
		req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |
					     UNI_WOW_DETECT_TYPE_BCN_LOST);
	if (wowlan->nd_config) {
		mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config);
		mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies);
		req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;
		mt7925_mcu_sched_scan_enable(phy, vif, suspend);
	}
@@ -2818,6 +2819,54 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
	return err;
}

static void
mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
			     struct sk_buff *skb,
			     struct ieee80211_scan_ies *scan_ies)
{
	u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN;
	struct scan_ie_tlv *ie;
	enum nl80211_band i;
	struct tlv *tlv;
	const u8 *ies;
	u16 ies_len;

	for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
		if (i == NL80211_BAND_60GHZ)
			continue;

		ies = scan_ies->ies[i];
		ies_len = scan_ies->len[i];

		if (!ies || !ies_len)
			continue;

		if (ies_len > max_len)
			return;

		tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
					      sizeof(*ie) + ies_len);
		ie = (struct scan_ie_tlv *)tlv;

		memcpy(ie->ies, ies, ies_len);
		ie->ies_len = cpu_to_le16(ies_len);

		switch (i) {
		case NL80211_BAND_2GHZ:
			ie->band = 1;
			break;
		case NL80211_BAND_6GHZ:
			ie->band = 3;
			break;
		default:
			ie->band = 2;
			break;
		}

		max_len -= (sizeof(*ie) + ies_len);
	}
}

int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
		       struct ieee80211_scan_request *scan_req)
{
@@ -2843,7 +2892,8 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,

	max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) +
		  sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS +
		  sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie);
		  sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) +
		  MT76_CONNAC_SCAN_IE_LEN;

	skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
	if (!skb)
@@ -2925,13 +2975,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
	}
	chan_info->channel_type = sreq->n_channels ? 4 : 0;

	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
	ie = (struct scan_ie_tlv *)tlv;
	if (sreq->ie_len > 0) {
		memcpy(ie->ies, sreq->ie, sreq->ie_len);
		ie->ies_len = cpu_to_le16(sreq->ie_len);
	}

	req->scan_func |= SCAN_FUNC_SPLIT_SCAN;

	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc));
@@ -2942,6 +2985,9 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
		req->scan_func |= SCAN_FUNC_RANDOM_MAC;
	}

	/* Append scan probe IEs as the last tlv */
	mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies);

	err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
				    true);
	if (err < 0)
@@ -2953,7 +2999,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan);

int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
			      struct ieee80211_vif *vif,
			      struct cfg80211_sched_scan_request *sreq)
			      struct cfg80211_sched_scan_request *sreq,
			      struct ieee80211_scan_ies *ies)
{
	struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
	struct ieee80211_channel **scan_list = sreq->channels;
@@ -3041,12 +3088,8 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
	}
	chan_info->channel_type = sreq->n_channels ? 4 : 0;

	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
	ie = (struct scan_ie_tlv *)tlv;
	if (sreq->ie_len > 0) {
		memcpy(ie->ies, sreq->ie, sreq->ie_len);
		ie->ies_len = cpu_to_le16(sreq->ie_len);
	}
	/* Append scan probe IEs as the last tlv */
	mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies);

	return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
				     true);
+3 −2
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ struct scan_ie_tlv {
	__le16 ies_len;
	u8 band;
	u8 pad;
	u8 ies[MT76_CONNAC_SCAN_IE_LEN];
	u8 ies[];
};

struct scan_misc_tlv {
@@ -673,7 +673,8 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
			      struct ieee80211_vif *vif);
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
			      struct ieee80211_vif *vif,
			      struct cfg80211_sched_scan_request *sreq);
			      struct cfg80211_sched_scan_request *sreq,
			      struct ieee80211_scan_ies *ies);
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
				 struct ieee80211_vif *vif,
				 bool enable);