Commit b4b9f0a3 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: mt7915: introduce bss coloring support



Introduce mcu APIs to configure bss coloring and to report bss coloring
collisions. Add support to report coloring countdown in beacon sent by
the device.

Co-developed-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 0421bf80
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -324,6 +324,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
	wiphy->reg_notifier = mt7915_regd_notifier;
	wiphy->reg_notifier = mt7915_regd_notifier;
	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;


	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);


	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
+26 −0
Original line number Original line Diff line number Diff line
@@ -537,6 +537,29 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
	mutex_unlock(&dev->mt76.mutex);
	mutex_unlock(&dev->mt76.mutex);
}
}


static void
mt7915_update_bss_color(struct ieee80211_hw *hw,
			struct ieee80211_vif *vif,
			struct cfg80211_he_bss_color *bss_color)
{
	struct mt7915_dev *dev = mt7915_hw_dev(hw);

	switch (vif->type) {
	case NL80211_IFTYPE_AP: {
		struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;

		if (mvif->omac_idx > HW_BSSID_MAX)
			return;
		fallthrough;
	}
	case NL80211_IFTYPE_STATION:
		mt7915_mcu_update_bss_color(dev, vif, bss_color);
		break;
	default:
		break;
	}
}

static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
				    struct ieee80211_vif *vif,
				    struct ieee80211_vif *vif,
				    struct ieee80211_bss_conf *info,
				    struct ieee80211_bss_conf *info,
@@ -585,6 +608,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
	if (changed & BSS_CHANGED_HE_OBSS_PD)
	if (changed & BSS_CHANGED_HE_OBSS_PD)
		mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
		mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);


	if (changed & BSS_CHANGED_HE_BSS_COLOR)
		mt7915_update_bss_color(hw, vif, &info->he_bss_color);

	if (changed & (BSS_CHANGED_BEACON |
	if (changed & (BSS_CHANGED_BEACON |
		       BSS_CHANGED_BEACON_ENABLED))
		       BSS_CHANGED_BEACON_ENABLED))
		mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
		mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
+65 −19
Original line number Original line Diff line number Diff line
@@ -511,6 +511,15 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
		   (int)(skb->len - sizeof(*rxd)), data);
		   (int)(skb->len - sizeof(*rxd)), data);
}
}


static void
mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
	if (!vif->color_change_active)
		return;

	ieee80211_color_change_finish(vif);
}

static void
static void
mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
{
{
@@ -529,6 +538,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
	case MCU_EXT_EVENT_FW_LOG_2_HOST:
	case MCU_EXT_EVENT_FW_LOG_2_HOST:
		mt7915_mcu_rx_log_message(dev, skb);
		mt7915_mcu_rx_log_message(dev, skb);
		break;
		break;
	case MCU_EXT_EVENT_BCC_NOTIFY:
		ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
				IEEE80211_IFACE_ITER_RESUME_ALL,
				mt7915_mcu_cca_finish, dev);
		break;
	default:
	default:
		break;
		break;
	}
	}
@@ -557,6 +571,7 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb)
	    rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
	    rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST ||
	    rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
	    rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP ||
	    rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
	    rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC ||
	    rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY ||
	    !rxd->seq)
	    !rxd->seq)
		mt7915_mcu_rx_unsolicited_event(dev, skb);
		mt7915_mcu_rx_unsolicited_event(dev, skb);
	else
	else
@@ -2388,25 +2403,28 @@ int mt7915_mcu_add_dev_info(struct mt7915_phy *phy,
}
}


static void
static void
mt7915_mcu_beacon_csa(struct sk_buff *rskb, struct sk_buff *skb,
mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
		      struct bss_info_bcn *bcn,
			 struct sk_buff *skb, struct bss_info_bcn *bcn,
			 struct ieee80211_mutable_offsets *offs)
			 struct ieee80211_mutable_offsets *offs)
{
{
	if (offs->cntdwn_counter_offs[0]) {
	struct bss_info_bcn_cntdwn *info;
	struct tlv *tlv;
	struct tlv *tlv;
		struct bss_info_bcn_csa *csa;
	int sub_tag;


		tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_CSA,
	if (!offs->cntdwn_counter_offs[0])
						   sizeof(*csa), &bcn->sub_ntlv,
		return;
						   &bcn->len);

		csa = (struct bss_info_bcn_csa *)tlv;
	sub_tag = vif->csa_active ? BSS_INFO_BCN_CSA : BSS_INFO_BCN_BCC;
		csa->cnt = skb->data[offs->cntdwn_counter_offs[0]];
	tlv = mt7915_mcu_add_nested_subtlv(rskb, sub_tag, sizeof(*info),
	}
					   &bcn->sub_ntlv, &bcn->len);
	info = (struct bss_info_bcn_cntdwn *)tlv;
	info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
}
}


static void
static void
mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
		       struct sk_buff *skb, struct bss_info_bcn *bcn,
		       struct sk_buff *rskb, struct sk_buff *skb,
		       struct bss_info_bcn *bcn,
		       struct ieee80211_mutable_offsets *offs)
		       struct ieee80211_mutable_offsets *offs)
{
{
	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
@@ -2422,8 +2440,14 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct sk_buff *rskb,
	cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
	cont->pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
	cont->tim_ofs = cpu_to_le16(offs->tim_offset);
	cont->tim_ofs = cpu_to_le16(offs->tim_offset);


	if (offs->cntdwn_counter_offs[0])
	if (offs->cntdwn_counter_offs[0]) {
		cont->csa_ofs = cpu_to_le16(offs->cntdwn_counter_offs[0] - 4);
		u16 offset = offs->cntdwn_counter_offs[0];

		if (vif->csa_active)
			cont->csa_ofs = cpu_to_le16(offset - 4);
		if (vif->color_change_active)
			cont->bcc_ofs = cpu_to_le16(offset - 3);
	}


	buf = (u8 *)tlv + sizeof(*cont);
	buf = (u8 *)tlv + sizeof(*cont);
	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
	mt7915_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
@@ -2471,9 +2495,9 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
		info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
		info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
	}
	}


	/* TODO: subtag - bss color count & 11v MBSSID */
	/* TODO: subtag - 11v MBSSID */
	mt7915_mcu_beacon_csa(rskb, skb, bcn, &offs);
	mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
	mt7915_mcu_beacon_cont(dev, rskb, skb, bcn, &offs);
	mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
	dev_kfree_skb(skb);
	dev_kfree_skb(skb);


out:
out:
@@ -3898,3 +3922,25 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,


	return ret;
	return ret;
}
}

int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
				struct cfg80211_he_bss_color *he_bss_color)
{
	int len = sizeof(struct sta_req_hdr) + sizeof(struct bss_info_color);
	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
	struct bss_info_color *bss_color;
	struct sk_buff *skb;
	struct tlv *tlv;

	skb = mt7915_mcu_alloc_sta_req(dev, mvif, NULL, len);
	if (IS_ERR(skb))
		return PTR_ERR(skb);

	tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_BSS_COLOR, sizeof(*bss_color));
	bss_color = (struct bss_info_color *)tlv;
	bss_color->disable = !he_bss_color->enabled;
	bss_color->color = he_bss_color->color;

	return mt76_mcu_skb_send_msg(&dev->mt76, skb,
				     MCU_EXT_CMD(BSS_INFO_UPDATE), true);
}
+11 −10
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ enum {
	MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
	MCU_EXT_EVENT_ASSERT_DUMP = 0x23,
	MCU_EXT_EVENT_RDD_REPORT = 0x3a,
	MCU_EXT_EVENT_RDD_REPORT = 0x3a,
	MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
	MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
	MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
};
};


enum {
enum {
@@ -503,6 +504,14 @@ struct bss_info_hw_amsdu {
	u8 rsv;
	u8 rsv;
} __packed;
} __packed;


struct bss_info_color {
	__le16 tag;
	__le16 len;
	u8 disable;
	u8 color;
	u8 rsv[2];
} __packed;

struct bss_info_he {
struct bss_info_he {
	__le16 tag;
	__le16 tag;
	__le16 len;
	__le16 len;
@@ -521,14 +530,7 @@ struct bss_info_bcn {
	__le16 sub_ntlv;
	__le16 sub_ntlv;
} __packed __aligned(4);
} __packed __aligned(4);


struct bss_info_bcn_csa {
struct bss_info_bcn_cntdwn {
	__le16 tag;
	__le16 len;
	u8 cnt;
	u8 rsv[3];
} __packed __aligned(4);

struct bss_info_bcn_bcc {
	__le16 tag;
	__le16 tag;
	__le16 len;
	__le16 len;
	u8 cnt;
	u8 cnt;
@@ -1117,8 +1119,7 @@ enum {
					 sizeof(struct bss_info_ext_bss))
					 sizeof(struct bss_info_ext_bss))


#define MT7915_BEACON_UPDATE_SIZE	(sizeof(struct sta_req_hdr) +	\
#define MT7915_BEACON_UPDATE_SIZE	(sizeof(struct sta_req_hdr) +	\
					 sizeof(struct bss_info_bcn_csa) + \
					 sizeof(struct bss_info_bcn_cntdwn) + \
					 sizeof(struct bss_info_bcn_bcc) + \
					 sizeof(struct bss_info_bcn_mbss) + \
					 sizeof(struct bss_info_bcn_mbss) + \
					 sizeof(struct bss_info_bcn_cont))
					 sizeof(struct bss_info_bcn_cont))


+2 −0
Original line number Original line Diff line number Diff line
@@ -305,6 +305,8 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif,
int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif,
		       struct mt7915_sta *msta, struct ieee80211_key_conf *key,
		       struct mt7915_sta *msta, struct ieee80211_key_conf *key,
		       enum set_key_cmd cmd);
		       enum set_key_cmd cmd);
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
				struct cfg80211_he_bss_color *he_bss_color);
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
			  int enable);
			  int enable);
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,