Commit 08aa8077 authored by Ping-Ke Shih's avatar Ping-Ke Shih Committed by Kalle Valo
Browse files

wifi: rtw89: correct BA CAM allocation



BA CAM entries are global resource of hardware, so move the bitmap and
instances to rtw89_cam_info, and then use link list from rtw89_sta to
these instances.

To check the allocation, add ba_cam to debugfs:

  map:
  	mac_id:    01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  	addr_cam:  01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  	bssid_cam: 01 00 00 00 00 00 00 00
  	sec_cam:   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  	ba_cam:    03 00 00 00 00 00 00 00
  VIF [0] 94:08:53:8e:ef:21
  	bssid_cam_idx=0
  	addr_cam_idx=0
  	-> bssid_cam_idx=0
  	sec_cam_bitmap=00 00 00 00 00 00 00 00
  STA [0] 38:78:62:8b:cb:c6
  	addr_cam_idx=0
  	-> bssid_cam_idx=0
  	sec_cam_bitmap=00 00 00 00 00 00 00 00
  	ba_cam tid[6]=0, tid[1]=1

Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220816013247.6243-4-pkshih@realtek.com
parent 8b1b4730
Loading
Loading
Loading
Loading
+36 −15
Original line number Diff line number Diff line
@@ -2242,23 +2242,42 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
				    struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
{
	const struct rtw89_chip_info *chip = rtwdev->chip;
	struct rtw89_ba_cam_entry *entry;
	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
	struct rtw89_ba_cam_entry *entry = NULL, *tmp;
	u8 idx;
	int i;

	lockdep_assert_held(&rtwdev->mutex);

	idx = rtw89_core_acquire_bit_map(rtwsta->ba_cam_map, chip->bacam_num);
	idx = rtw89_core_acquire_bit_map(cam_info->ba_cam_map, chip->bacam_num);
	if (idx == chip->bacam_num) {
		/* allocate a static BA CAM to tid=0, so replace the existing
		/* allocate a static BA CAM to tid=0/5, so replace the existing
		 * one if BA CAM is full. Hardware will process the original tid
		 * automatically.
		 */
		if (tid != 0)
		if (tid != 0 && tid != 5)
			return -ENOSPC;

		idx = 0;
		for_each_set_bit(i, cam_info->ba_cam_map, chip->bacam_num) {
			tmp = &cam_info->ba_cam_entry[i];
			if (tmp->tid == 0 || tmp->tid == 5)
				continue;

			idx = i;
			entry = tmp;
			list_del(&entry->list);
			break;
		}

		if (!entry)
			return -ENOSPC;
	} else {
		entry = &cam_info->ba_cam_entry[idx];
	}

	entry = &rtwsta->ba_cam_entry[idx];
	entry->tid = tid;
	list_add_tail(&entry->list, &rtwsta->ba_cam_list);

	*cam_idx = idx;

	return 0;
@@ -2267,20 +2286,21 @@ int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
				    struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
{
	const struct rtw89_chip_info *chip = rtwdev->chip;
	struct rtw89_ba_cam_entry *entry;
	int i;
	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
	struct rtw89_ba_cam_entry *entry = NULL, *tmp;
	u8 idx;

	for (i = 0; i < chip->bacam_num; i++) {
		if (!test_bit(i, rtwsta->ba_cam_map))
			continue;
	lockdep_assert_held(&rtwdev->mutex);

		entry = &rtwsta->ba_cam_entry[i];
	list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) {
		if (entry->tid != tid)
			continue;

		rtw89_core_release_bit_map(rtwsta->ba_cam_map, i);
		*cam_idx = i;
		idx = entry - cam_info->ba_cam_entry;
		list_del(&entry->list);

		rtw89_core_release_bit_map(cam_info->ba_cam_map, idx);
		*cam_idx = idx;
		return 0;
	}

@@ -2343,6 +2363,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,

	rtwsta->rtwvif = rtwvif;
	rtwsta->prev_rssi = 0;
	INIT_LIST_HEAD(&rtwsta->ba_cam_list);

	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
		rtw89_core_txq_init(rtwdev, sta->txq[i]);
+4 −3
Original line number Diff line number Diff line
@@ -2084,6 +2084,7 @@ struct rtw89_ra_report {
DECLARE_EWMA(rssi, 10, 16);

struct rtw89_ba_cam_entry {
	struct list_head list;
	u8 tid;
};

@@ -2146,6 +2147,7 @@ struct rtw89_sta {
	__le32 htc_template;
	struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
	struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
	struct list_head ba_cam_list;

	bool use_cfg_mask;
	struct cfg80211_bitrate_mask mask;
@@ -2154,9 +2156,6 @@ struct rtw89_sta {
	u32 ampdu_max_time:4;
	bool cctl_tx_retry_limit;
	u32 data_tx_cnt_lmt:6;

	DECLARE_BITMAP(ba_cam_map, RTW89_MAX_BA_CAM_NUM);
	struct rtw89_ba_cam_entry ba_cam_entry[RTW89_MAX_BA_CAM_NUM];
};

struct rtw89_efuse {
@@ -2764,6 +2763,8 @@ struct rtw89_cam_info {
	DECLARE_BITMAP(addr_cam_map, RTW89_MAX_ADDR_CAM_NUM);
	DECLARE_BITMAP(bssid_cam_map, RTW89_MAX_BSSID_CAM_NUM);
	DECLARE_BITMAP(sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
	DECLARE_BITMAP(ba_cam_map, RTW89_MAX_BA_CAM_NUM);
	struct rtw89_ba_cam_entry ba_cam_entry[RTW89_MAX_BA_CAM_NUM];
};

enum rtw89_sar_sources {
+27 −0
Original line number Diff line number Diff line
@@ -2434,6 +2434,26 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
	rtw89_dump_addr_cam(m, &rtwvif->addr_cam);
}

static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
{
	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
	struct rtw89_ba_cam_entry *entry;
	bool first = true;

	list_for_each_entry(entry, &rtwsta->ba_cam_list, list) {
		if (first) {
			seq_puts(m, "\tba_cam ");
			first = false;
		} else {
			seq_puts(m, ", ");
		}
		seq_printf(m, "tid[%u]=%d", entry->tid,
			   (int)(entry - rtwdev->cam_info.ba_cam_entry));
	}
	seq_puts(m, "\n");
}

static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
{
	struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
@@ -2442,6 +2462,7 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
	seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr,
		   sta->tdls ? "(TDLS)" : "");
	rtw89_dump_addr_cam(m, &rtwsta->addr_cam);
	rtw89_dump_ba_cam(m, rtwsta);
}

static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
@@ -2450,6 +2471,8 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
	struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
	struct rtw89_cam_info *cam_info = &rtwdev->cam_info;

	mutex_lock(&rtwdev->mutex);

	seq_puts(m, "map:\n");
	seq_printf(m, "\tmac_id:    %*ph\n", (int)sizeof(rtwdev->mac_id_map),
		   rtwdev->mac_id_map);
@@ -2459,12 +2482,16 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
		   cam_info->bssid_cam_map);
	seq_printf(m, "\tsec_cam:   %*ph\n", (int)sizeof(cam_info->sec_cam_map),
		   cam_info->sec_cam_map);
	seq_printf(m, "\tba_cam:    %*ph\n", (int)sizeof(cam_info->ba_cam_map),
		   cam_info->ba_cam_map);

	ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
		IEEE80211_IFACE_ITER_NORMAL, rtw89_vif_ids_get_iter, m);

	ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_ids_get_iter, m);

	mutex_unlock(&rtwdev->mutex);

	return 0;
}

+6 −2
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
	rtwvif->trigger = false;
}

static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
{
	struct rtw89_vif *rtwvif = (struct rtw89_vif *)data;
	struct rtw89_dev *rtwdev = rtwvif->rtwdev;
@@ -312,15 +312,19 @@ static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
		rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
	if (sta->tdls)
		rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);

	INIT_LIST_HEAD(&rtwsta->ba_cam_list);
}

static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
	ieee80211_iterate_stations_atomic(rtwdev->hw,
					  ser_sta_deinit_addr_cam_iter,
					  ser_sta_deinit_cam_iter,
					  rtwvif);

	rtw89_cam_deinit(rtwdev, rtwvif);

	bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM);
}

static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)