wifi: rtw89: correct BA CAM allocation
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 16 Aug 2022 01:32:47 +0000 (09:32 +0800)
committerKalle Valo <kvalo@kernel.org>
Fri, 2 Sep 2022 08:35:14 +0000 (11:35 +0300)
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: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220816013247.6243-4-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/debug.c
drivers/net/wireless/realtek/rtw89/ser.c

index c478c2959161ad09b159d42488a4710b483e81f0..c1c636812c51c347df9d3615dbcba1d65db193ff 100644 (file)
@@ -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]);
index 90129bba300134db05df8fb0b70878db3b733bc0..9ccf94992a57bda45ef24ff64093775fbd73a627 100644 (file)
@@ -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 {
index 9c93117c62a440eb407bca2ef6f1209fa4e36edb..68dabac68767878aa27658987f01b762946c65bd 100644 (file)
@@ -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;
 }
 
index 1f919854beb176d5cd27ff60c66a6d700c04a652..ee0ae2816860bd526decd1e7c0143c2d1cba285f 100644 (file)
@@ -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)