Commit b56b08ae authored by Rajkumar Manoharan's avatar Rajkumar Manoharan Committed by Kalle Valo
Browse files

ath11k: add support to configure spatial reuse parameter set



The SPR parameter set comprises OBSS PD threshold for SRG
and non SRG and Bitmap of BSS color and partial BSSID. This adds
support to configure fields of SPR element to firmware.

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1-01164-QCAHKSWPL_SILICONZ-1
Tested-by: default avatarMuna Sinada <msinada@codeaurora.org>
Signed-off-by: default avatarRajkumar Manoharan <rmanohar@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1612843714-29174-1-git-send-email-rmanohar@codeaurora.org
parent e6f1c0d2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3845,6 +3845,18 @@ htt_print_pdev_obss_pd_stats_tlv_v(const void *tag_buf,
			   htt_stats_buf->num_obss_tx_ppdu_success);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "OBSS Tx failures PPDU = %u\n",
			   htt_stats_buf->num_obss_tx_ppdu_failure);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG Opportunities = %u\n",
			   htt_stats_buf->num_non_srg_opportunities);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG tried PPDU = %u\n",
			   htt_stats_buf->num_non_srg_ppdu_tried);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "Non-SRG success PPDU = %u\n",
			   htt_stats_buf->num_non_srg_ppdu_success);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG Opportunies = %u\n",
			   htt_stats_buf->num_srg_opportunities);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG tried PPDU = %u\n",
			   htt_stats_buf->num_srg_ppdu_tried);
	len += HTT_DBG_OUT(buf + len, buf_len - len, "SRG success PPDU = %u\n",
			   htt_stats_buf->num_srg_ppdu_success);

	if (len >= buf_len)
		buf[buf_len - 1] = 0;
+13 −2
Original line number Diff line number Diff line
@@ -1658,6 +1658,17 @@ struct htt_tx_sounding_stats_tlv {
struct htt_pdev_obss_pd_stats_tlv {
	u32 num_obss_tx_ppdu_success;
	u32 num_obss_tx_ppdu_failure;
	u32 num_sr_tx_transmissions;
	u32 num_spatial_reuse_opportunities;
	u32 num_non_srg_opportunities;
	u32 num_non_srg_ppdu_tried;
	u32 num_non_srg_ppdu_success;
	u32 num_srg_opportunities;
	u32 num_srg_ppdu_tried;
	u32 num_srg_ppdu_success;
	u32 num_psr_opportunities;
	u32 num_psr_ppdu_tried;
	u32 num_psr_ppdu_success;
};

struct htt_ring_backpressure_stats_tlv {
+153 −2
Original line number Diff line number Diff line
@@ -1871,6 +1871,158 @@ static int ath11k_mac_fils_discovery(struct ath11k_vif *arvif,
	return ret;
}

static int ath11k_mac_config_obss_pd(struct ath11k *ar,
				     struct ieee80211_he_obss_pd *he_obss_pd)
{
	u32 bitmap[2], param_id, param_val, pdev_id;
	int ret;
	s8 non_srg_th = 0, srg_th = 0;

	pdev_id = ar->pdev->pdev_id;

	/* Set and enable SRG/non-SRG OBSS PD Threshold */
	param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD;
	if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags)) {
		ret = ath11k_wmi_pdev_set_param(ar, param_id, 0, pdev_id);
		if (ret)
			ath11k_warn(ar->ab,
				    "failed to set obss_pd_threshold for pdev: %u\n",
				    pdev_id);
		return ret;
	}

	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
		   "mac obss pd sr_ctrl %x non_srg_thres %u srg_max %u\n",
		   he_obss_pd->sr_ctrl, he_obss_pd->non_srg_max_offset,
		   he_obss_pd->max_offset);

	param_val = 0;

	if (he_obss_pd->sr_ctrl &
	    IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED) {
		non_srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD;
	} else {
		if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT)
			non_srg_th = (ATH11K_OBSS_PD_MAX_THRESHOLD +
				      he_obss_pd->non_srg_max_offset);
		else
			non_srg_th = ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD;

		param_val |= ATH11K_OBSS_PD_NON_SRG_EN;
	}

	if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) {
		srg_th = ATH11K_OBSS_PD_MAX_THRESHOLD + he_obss_pd->max_offset;
		param_val |= ATH11K_OBSS_PD_SRG_EN;
	}

	if (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
		     ar->ab->wmi_ab.svc_map)) {
		param_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM;
		param_val |= FIELD_PREP(GENMASK(15, 8), srg_th);
	} else {
		non_srg_th -= ATH11K_DEFAULT_NOISE_FLOOR;
		/* SRG not supported and threshold in dB */
		param_val &= ~(ATH11K_OBSS_PD_SRG_EN |
			       ATH11K_OBSS_PD_THRESHOLD_IN_DBM);
	}

	param_val |= (non_srg_th & GENMASK(7, 0));
	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set obss_pd_threshold for pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Enable OBSS PD for all access category */
	param_id  = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC;
	param_val = 0xf;
	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set obss_pd_per_ac for pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Set SR Prohibit */
	param_id  = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT;
	param_val = !!(he_obss_pd->sr_ctrl &
		       IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED);
	ret = ath11k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id);
	if (ret) {
		ath11k_warn(ar->ab, "failed to set sr_prohibit for pdev: %u\n",
			    pdev_id);
		return ret;
	}

	if (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,
		      ar->ab->wmi_ab.svc_map))
		return 0;

	/* Set SRG BSS Color Bitmap */
	memcpy(bitmap, he_obss_pd->bss_color_bitmap, sizeof(bitmap));
	ret = ath11k_wmi_pdev_set_srg_bss_color_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set bss_color_bitmap for pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Set SRG Partial BSSID Bitmap */
	memcpy(bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(bitmap));
	ret = ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set partial_bssid_bitmap for pdev: %u\n",
			    pdev_id);
		return ret;
	}

	memset(bitmap, 0xff, sizeof(bitmap));

	/* Enable all BSS Colors for SRG */
	ret = ath11k_wmi_pdev_srg_obss_color_enable_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set srg_color_en_bitmap pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Enable all patial BSSID mask for SRG */
	ret = ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set srg_bssid_en_bitmap pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Enable all BSS Colors for non-SRG */
	ret = ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set non_srg_color_en_bitmap pdev: %u\n",
			    pdev_id);
		return ret;
	}

	/* Enable all patial BSSID mask for non-SRG */
	ret = ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, bitmap);
	if (ret) {
		ath11k_warn(ar->ab,
			    "failed to set non_srg_bssid_en_bitmap pdev: %u\n",
			    pdev_id);
		return ret;
	}

	return 0;
}

static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
					   struct ieee80211_vif *vif,
					   struct ieee80211_bss_conf *info,
@@ -2114,8 +2266,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
	}

	if (changed & BSS_CHANGED_HE_OBSS_PD)
		ath11k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id,
					     &info->he_obss_pd);
		ath11k_mac_config_obss_pd(ar, &info->he_obss_pd);

	if (changed & BSS_CHANGED_HE_BSS_COLOR) {
		if (vif->type == NL80211_IFTYPE_AP) {
+6 −0
Original line number Diff line number Diff line
@@ -116,6 +116,12 @@ struct ath11k_generic_iter {

#define ATH11K_CHAN_WIDTH_NUM			8

#define ATH11K_OBSS_PD_MAX_THRESHOLD			-82
#define ATH11K_OBSS_PD_NON_SRG_MAX_THRESHOLD		-62
#define ATH11K_OBSS_PD_THRESHOLD_IN_DBM			BIT(29)
#define ATH11K_OBSS_PD_SRG_EN				BIT(30)
#define ATH11K_OBSS_PD_NON_SRG_EN			BIT(31)

extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default;

void ath11k_mac_destroy(struct ath11k_base *ab);
+227 −0
Original line number Diff line number Diff line
@@ -2970,6 +2970,233 @@ ath11k_wmi_send_obss_spr_cmd(struct ath11k *ar, u32 vdev_id,
	return ret;
}

int
ath11k_wmi_pdev_set_srg_bss_color_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
				     WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD) |
			  FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd pdev_id %d bss color bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_pdev_set_srg_patial_bssid_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header =
		FIELD_PREP(WMI_TLV_TAG,
			   WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD) |
		FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd pdev_id %d partial bssid bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header =
		FIELD_PREP(WMI_TLV_TAG,
			   WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) |
		FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd srg pdev_id %d bss color enable bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header =
		FIELD_PREP(WMI_TLV_TAG,
			   WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) |
		FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd srg pdev_id %d bssid enable bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header =
		FIELD_PREP(WMI_TLV_TAG,
			   WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD) |
		FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd non_srg pdev_id %d bss color enable bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath11k *ar, u32 *bitmap)
{
	struct ath11k_pdev_wmi *wmi = ar->wmi;
	struct ath11k_base *ab = wmi->wmi_ab->ab;
	struct wmi_pdev_obss_pd_bitmap_cmd *cmd;
	struct sk_buff *skb;
	int ret, len;

	len = sizeof(*cmd);

	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data;
	cmd->tlv_header =
		FIELD_PREP(WMI_TLV_TAG,
			   WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD) |
		FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE);
	cmd->pdev_id = ar->pdev->pdev_id;
	memcpy(cmd->bitmap, bitmap, sizeof(cmd->bitmap));

	ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
		   "obss pd non_srg pdev_id %d bssid enable bitmap %08x %08x\n",
		   cmd->pdev_id, cmd->bitmap[0], cmd->bitmap[1]);

	ret = ath11k_wmi_cmd_send(wmi, skb,
				  WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID);
	if (ret) {
		ath11k_warn(ab,
			    "failed to send WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID");
		dev_kfree_skb(skb);
	}

	return ret;
}

int
ath11k_wmi_send_obss_color_collision_cfg_cmd(struct ath11k *ar, u32 vdev_id,
					     u8 bss_color, u32 period,
Loading