Commit 869f0646 authored by MeiChia Chiu's avatar MeiChia Chiu Committed by Felix Fietkau
Browse files

mt76: mt7915: add support for 6G in-band discovery



Add offloading FILS discovery and unsolicited broadcast probe response support.

Reviewed-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarMeiChia Chiu <MeiChia.Chiu@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent f68d6762
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -351,6 +351,8 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY);

	if (!mdev->dev->of_node ||
	    !of_property_read_bool(mdev->dev->of_node,
+12 −5
Original line number Diff line number Diff line
@@ -1177,7 +1177,7 @@ mt7915_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,

void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
			   struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
			   struct ieee80211_key_conf *key, bool beacon)
			   struct ieee80211_key_conf *key, u32 changed)
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_vif *vif = info->control.vif;
@@ -1188,6 +1188,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
	bool mcast = false;
	u16 tx_count = 15;
	u32 val;
	bool beacon = !!(changed & (BSS_CHANGED_BEACON |
				    BSS_CHANGED_BEACON_ENABLED));
	bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
					 BSS_CHANGED_FILS_DISCOVERY));

	if (vif) {
		struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
@@ -1200,7 +1204,10 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
	if (ext_phy && dev->mt76.phy2)
		mphy = dev->mt76.phy2;

	if (beacon) {
	if (inband_disc) {
		p_fmt = MT_TX_TYPE_FW;
		q_idx = MT_LMAC_ALTX0;
	} else if (beacon) {
		p_fmt = MT_TX_TYPE_FW;
		q_idx = MT_LMAC_BCN0;
	} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
@@ -1308,8 +1315,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
		return id;

	pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
	mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
			      false);
	mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, 0);

	txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
	for (i = 0; i < nbuf; i++) {
@@ -2008,7 +2014,8 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
	case NL80211_IFTYPE_MESH_POINT:
	case NL80211_IFTYPE_ADHOC:
	case NL80211_IFTYPE_AP:
		mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
		mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon,
				      BSS_CHANGED_BEACON_ENABLED);
		break;
	default:
		break;
+5 −3
Original line number Diff line number Diff line
@@ -622,8 +622,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
		mt7915_update_bss_color(hw, vif, &info->he_bss_color);

	if (changed & (BSS_CHANGED_BEACON |
		       BSS_CHANGED_BEACON_ENABLED))
		mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
		       BSS_CHANGED_BEACON_ENABLED |
		       BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
		       BSS_CHANGED_FILS_DISCOVERY))
		mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);

	mutex_unlock(&dev->mt76.mutex);
}
@@ -636,7 +638,7 @@ mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
	struct mt7915_dev *dev = mt7915_hw_dev(hw);

	mutex_lock(&dev->mt76.mutex);
	mt7915_mcu_add_beacon(hw, vif, true);
	mt7915_mcu_add_beacon(hw, vif, true, BSS_CHANGED_BEACON);
	mutex_unlock(&dev->mt76.mutex);
}

+72 −3
Original line number Diff line number Diff line
@@ -1892,6 +1892,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
	u8 *buf;
	int len = sizeof(*cont) + MT_TXD_SIZE + skb->len;

	len = (len & 0x3) ? ((len | 0x3) + 1) : len;
	tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CONTENT,
					   len, &bcn->sub_ntlv, &bcn->len);

@@ -1910,7 +1911,7 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,

	buf = (u8 *)tlv + sizeof(*cont);
	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
			      true);
			      BSS_CHANGED_BEACON);
	memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
}

@@ -1992,8 +1993,71 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
	}
}

int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
			  struct ieee80211_vif *vif, int en)
static void
mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
				struct sk_buff *rskb, struct bss_info_bcn *bcn,
				u32 changed)
{
#define OFFLOAD_TX_MODE_SU	BIT(0)
#define OFFLOAD_TX_MODE_MU	BIT(1)
	struct ieee80211_hw *hw = mt76_hw(dev);
	struct mt7915_phy *phy = mt7915_hw_phy(hw);
	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
	struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
	enum nl80211_band band = chandef->chan->band;
	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
	struct bss_info_inband_discovery *discov;
	struct ieee80211_tx_info *info;
	struct sk_buff *skb = NULL;
	struct tlv *tlv;
	bool ext_phy = phy != &dev->phy;
	u8 *buf, interval;
	int len;

	if (changed & BSS_CHANGED_FILS_DISCOVERY &&
	    vif->bss_conf.fils_discovery.max_interval) {
		interval = vif->bss_conf.fils_discovery.max_interval;
		skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
	} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
		   vif->bss_conf.unsol_bcast_probe_resp_interval) {
		interval = vif->bss_conf.unsol_bcast_probe_resp_interval;
		skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
	}

	if (!skb)
		return;

	info = IEEE80211_SKB_CB(skb);
	info->control.vif = vif;
	info->band = band;

	if (ext_phy)
		info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;

	len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
	len = (len & 0x3) ? ((len | 0x3) + 1) : len;

	tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
					   len, &bcn->sub_ntlv, &bcn->len);
	discov = (struct bss_info_inband_discovery *)tlv;
	discov->tx_mode = OFFLOAD_TX_MODE_SU;
	/* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
	discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
	discov->tx_interval = interval;
	discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
	discov->enable = true;

	buf = (u8 *)tlv + sizeof(*discov);

	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
			      changed);
	memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);

	dev_kfree_skb(skb);
}

int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
			  int en, u32 changed)
{
#define MAX_BEACON_SIZE 512
	struct mt7915_dev *dev = mt7915_hw_dev(hw);
@@ -2044,6 +2108,11 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
	mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
	dev_kfree_skb(skb);

	if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
	    changed & BSS_CHANGED_FILS_DISCOVERY)
		mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
						bcn, changed);

out:
	return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
				     MCU_EXT_CMD(BSS_INFO_UPDATE), true);
+14 −1
Original line number Diff line number Diff line
@@ -404,11 +404,23 @@ struct bss_info_bcn_cont {
	__le16 pkt_len;
} __packed __aligned(4);

struct bss_info_inband_discovery {
	__le16 tag;
	__le16 len;
	u8 tx_type;
	u8 tx_mode;
	u8 tx_interval;
	u8 enable;
	__le16 rsv;
	__le16 prob_rsp_len;
} __packed __aligned(4);

enum {
	BSS_INFO_BCN_CSA,
	BSS_INFO_BCN_BCC,
	BSS_INFO_BCN_MBSSID,
	BSS_INFO_BCN_CONTENT,
	BSS_INFO_BCN_DISCOV,
	BSS_INFO_BCN_MAX
};

@@ -490,6 +502,7 @@ enum {
#define MT7915_BEACON_UPDATE_SIZE	(sizeof(struct sta_req_hdr) +	\
					 sizeof(struct bss_info_bcn_cntdwn) + \
					 sizeof(struct bss_info_bcn_mbss) + \
					 sizeof(struct bss_info_bcn_cont))
					 sizeof(struct bss_info_bcn_cont) + \
					 sizeof(struct bss_info_inband_discovery))

#endif
Loading