All of lore.kernel.org
 help / color / mirror / Atom feed
From: viktor.barna@celeno.com
To: linux-wireless@vger.kernel.org
Cc: Kalle Valo <kvalo@codeaurora.org>,
	"David S . Miller" <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Aviad Brikman <aviad.brikman@celeno.com>,
	Eliav Farber <eliav.farber@gmail.com>,
	Oleksandr Savchenko <oleksandr.savchenko@celeno.com>,
	Shay Bar <shay.bar@celeno.com>,
	Viktor Barna <viktor.barna@celeno.com>
Subject: [RFC v1 180/256] cl8k: add sounding.c
Date: Thu, 17 Jun 2021 16:01:07 +0000	[thread overview]
Message-ID: <20210617160223.160998-181-viktor.barna@celeno.com> (raw)
In-Reply-To: <20210617160223.160998-1-viktor.barna@celeno.com>

From: Viktor Barna <viktor.barna@celeno.com>

(Part of the split. Please, take a look at the cover letter for more
details).

Signed-off-by: Viktor Barna <viktor.barna@celeno.com>
---
 drivers/net/wireless/celeno/cl8k/sounding.c | 1432 +++++++++++++++++++
 1 file changed, 1432 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/sounding.c

diff --git a/drivers/net/wireless/celeno/cl8k/sounding.c b/drivers/net/wireless/celeno/cl8k/sounding.c
new file mode 100644
index 000000000000..a51348eacbe7
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/sounding.c
@@ -0,0 +1,1432 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "sounding.h"
+#include "fw/msg_tx.h"
+#include "debug.h"
+#include "bf.h"
+#include "chip.h"
+#include "band.h"
+#include "recovery.h"
+
+#define DBG_PREFIX_MAX_LENGTH 64
+#define sounding_pr(level, format, ...) \
+       do { \
+               if ((level) <= cl_hw->sounding.dbg_level) { \
+                       char __dbg_prefix[DBG_PREFIX_MAX_LENGTH] = {0}; \
+                       if ((level) >= DBG_LVL_TRACE) \
+                               snprintf(__dbg_prefix, DBG_PREFIX_MAX_LENGTH, "[%s][%d]", \
+                                        __func__, __LINE__); \
+                       pr_debug("%s [Sounding] " format, __dbg_prefix, ##__VA_ARGS__); \
+               } \
+       } while (0)
+
+#define sounding_pr_verbose(...) sounding_pr(DBG_LVL_VERBOSE, ##__VA_ARGS__)
+#define sounding_pr_err(...)     sounding_pr(DBG_LVL_ERROR, ##__VA_ARGS__)
+#define sounding_pr_warn(...)    sounding_pr(DBG_LVL_WARNING, ##__VA_ARGS__)
+#define sounding_pr_trace(...)   sounding_pr(DBG_LVL_TRACE, ##__VA_ARGS__)
+#define sounding_pr_info(...)    sounding_pr(DBG_LVL_INFO, ##__VA_ARGS__)
+
+#define CL_SOUNDING_TYPE_2_STR(type) ((type) == SOUNDING_TYPE_HE_SU ? "HE_SU" : \
+                                     (type) == SOUNDING_TYPE_HE_SU_TB ? "HE_SU_TB" : \
+                                     (type) == SOUNDING_TYPE_VHT_SU ? "VHT_SU" : \
+                                     (type) == SOUNDING_TYPE_HE_CQI ? "HE_CQI" : \
+                                     (type) == SOUNDING_TYPE_HE_CQI_TB ? "HE_CQI_TB" :\
+                                     (type) == SOUNDING_TYPE_HE_MU ? "HE_MU" : \
+                                     (type) == SOUNDING_TYPE_VHT_MU ? "VHT_MU" : "INVALID")
+
+#define CL_SOUNDING_ALL_STA          0xff
+#define CL_SOUNDING_LIFETIME_MAX     4095
+#define CL_SOUNDING_LIFETIME_FACTOR  5
+#define CL_SOUNDING_V_MATRIX_PADDING 32
+#define V_MATRIX_MAC_OVERHEAD        41
+#define Q_MATRIX_BITMAP_MASK         0xf
+
+enum cl_sounding_feedback_type {
+       CL_SOUNDING_FEEDBACK_TYPE_SU = 0,
+       CL_SOUNDING_FEEDBACK_TYPE_MU,
+};
+
+enum cl_sounding_ng {
+       CL_SOUNDING_NG_4 = 0,
+       CL_SOUNDING_NG_16,
+       CL_SOUNDING_NG_MAX
+};
+
+struct sounding_work_data {
+       struct work_struct  work;
+       struct cl_hw *cl_hw;
+       bool start;
+       bool is_recovery;
+       struct cl_sounding_info *elem; /* For stop and recovery cases */
+       enum sounding_type sounding_type;
+       u8 gid;
+       u8 sta_num;
+       u8 bw;
+       u8 q_matrix_bitmap;
+       u8 sta_indices[CL_MU_MAX_STA_PER_GROUP];
+};
+
+static u16 ng_bw_to_nsc[CL_SOUNDING_NG_MAX][CHNL_BW_MAX_HE] = {
+       {64, 122, 250, 500},
+       {20, 32, 64, 128}
+};
+
+static int cl_sounding_check_response(struct cl_hw *cl_hw, u8 param_err)
+{
+       int ret = -1;
+
+       switch (param_err) {
+       case CL_SOUNDING_RSP_OK:
+               sounding_pr_trace("param OK!\n");
+               ret = 0;
+               break;
+       case CL_SOUNDING_RSP_ERR_RLIMIT:
+               sounding_pr_err("error, resource limit reached\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_BW:
+               sounding_pr_err("error, unsupported BW tx requested\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_NSS:
+               sounding_pr_err("error, unsupported ndp NSS tx requested\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_INTERVAL:
+               sounding_pr_err("error, interval value is invalid\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_ALREADY:
+               sounding_pr_err("error, station already associated/disassociated with sounding\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_STA:
+               sounding_pr_err("error, station is inactive/active\n");
+               break;
+       case CL_SOUNDING_RSP_ERR_TYPE:
+               sounding_pr_err("error, invalid sounding type\n");
+               break;
+       default:
+               sounding_pr_err("error status unknown, BUG\n");
+               break;
+       }
+
+       return ret;
+}
+
+static u32 cl_sounding_get_lifetime(struct cl_hw *cl_hw, u32 interval)
+{
+       u32 lifetime = (interval * CL_SOUNDING_LIFETIME_FACTOR) >> 1;
+
+       if (lifetime > CL_SOUNDING_LIFETIME_MAX) {
+               sounding_pr_err("lifetime (%u) exceeds 4095\n", lifetime);
+               lifetime = CL_SOUNDING_LIFETIME_MAX;
+       }
+
+       return lifetime;
+}
+
+static bool cl_sounding_is_sta_ng_16_capable(struct cl_hw *cl_hw, struct cl_sta *cl_sta,
+                                            bool mu_cap)
+{
+       struct ieee80211_sta_he_cap *he_cap = &cl_sta->stainfo->sta.he_cap;
+
+       if (he_cap->has_he) {
+               if (mu_cap)
+                       return (he_cap->he_cap_elem.phy_cap_info[5] &
+                               IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK) ? true : false;
+               else
+                       return (he_cap->he_cap_elem.phy_cap_info[5] &
+                               IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK) ? true : false;
+       }
+
+       return false;
+}
+
+static bool cl_sounding_is_sta_codebook_size_75_capable(struct cl_hw *cl_hw, struct cl_sta *cl_sta)
+{
+       struct ieee80211_sta_he_cap *he_cap = &cl_sta->stainfo->sta.he_cap;
+
+       if (he_cap->has_he)
+               return (he_cap->he_cap_elem.phy_cap_info[6] &
+                       IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU) ? true : false;
+
+       return false;
+}
+
+static void cl_sounding_extract_ng_cb_size(struct cl_hw *cl_hw, u8 fb_type_ng_cb_size,
+                                          enum cl_sounding_ng *ng, u8 *phi_psi_sum)
+{
+       enum cl_sounding_feedback_type fb_type =
+               SOUNDING_FEEDBACK_TYPE_VAL(fb_type_ng_cb_size);
+       u8 cb_size = SOUNDING_CODEBOOK_SIZE_VAL(fb_type_ng_cb_size);
+
+       *ng = SOUNDING_NG_VAL(fb_type_ng_cb_size);
+
+       switch (fb_type) {
+       case CL_SOUNDING_FEEDBACK_TYPE_SU:
+               *phi_psi_sum = (cb_size ? 10 : 6);
+               break;
+       case CL_SOUNDING_FEEDBACK_TYPE_MU:
+               *phi_psi_sum = (cb_size ? 16 : 12);
+               break;
+       default:
+               sounding_pr_err("Invalid feedback_type %d\n", fb_type);
+               break;
+       }
+}
+
+static u32 cl_sounding_get_v_matrix_size(struct cl_hw *cl_hw, u8 sta_idx, u8 bw, u8 nc, u8 nr,
+                                        u8 fb_type_ng_cb_size)
+{
+       enum cl_sounding_ng ng = 0;
+       u8 phi_psi_sum = 0;
+       u8 nsc;
+       u32 v_size;
+
+       cl_sounding_extract_ng_cb_size(cl_hw, fb_type_ng_cb_size, &ng, &phi_psi_sum);
+       nsc = ng_bw_to_nsc[ng][bw];
+
+       /* NC and NR should start from 1 and not 0 for the below calculation */
+       nc++;
+       nr++;
+
+       /* v_size = [8*41 + 8*nc + (phi + psi)/2 * nsc*(nc * (2*nr-nc-1))] / 8 + extra padding */
+       v_size = V_MATRIX_MAC_OVERHEAD + nc +
+                    ((phi_psi_sum * nsc * nc * (2 * nr - nc - 1)) >> 4) +
+                    CL_SOUNDING_V_MATRIX_PADDING;
+
+       sounding_pr_info("sta %u, nc %u, nr %u, ng %d, phi_psi_sum %u, nsc %u, v_size %u\n",
+                        sta_idx, nc, nr, ng, phi_psi_sum, nsc, v_size);
+
+       return v_size;
+}
+
+static u32 cl_sounding_get_v_matrices_data_size(struct cl_hw *cl_hw,
+                                               struct sounding_info_per_sta *info_per_sta,
+                                               u8 sta_num, u8 bw, u8 nr)
+{
+       u8 i;
+       u32 v_size = 0;
+
+       for (i = 0; i < sta_num; i++)
+               v_size += cl_sounding_get_v_matrix_size(cl_hw, info_per_sta[i].sta_idx,
+                                                       bw, info_per_sta[i].nc,
+                                                       nr, info_per_sta[i].fb_type_ng_cb_size);
+
+       sounding_pr_info("v_matrices data size %u, sta_num %u\n", v_size, sta_num);
+
+       return v_size;
+}
+
+static u32 cl_sounding_get_q_matrix_size(struct cl_hw *cl_hw,
+                                        const struct sounding_info_per_sta *info_per_sta,
+                                        u8 sta_num, u8 bw, u8 nr)
+{
+       u8 i;
+       u8 nc = 0;
+       enum cl_sounding_ng ng = 0;
+       u8 nsc, phi_psi_sum = 0;
+       u32 q_size = 0;
+
+       /*
+        * NC and NR should start from 1 and not 0 for the below calculation
+        * In MU-MIMO case, when sta_num > 1, we should take the sum of all nc's
+        */
+       for (i = 0; i < sta_num; i++)
+               nc += info_per_sta[i].nc + 1;
+
+       nr++;
+
+       cl_sounding_extract_ng_cb_size(cl_hw, info_per_sta[0].fb_type_ng_cb_size, &ng,
+                                      &phi_psi_sum);
+       nsc = ng_bw_to_nsc[ng][bw];
+       q_size = (nr * nc * nsc) << 2;
+
+       sounding_pr_info("q_matrix size %u, sta_num %u\n", q_size, sta_num);
+
+       return q_size;
+}
+
+static u32 cl_sounding_get_required_xmem_size(struct cl_hw *cl_hw,
+                                             const struct mm_sounding_req *sounding_req,
+                                             const struct sounding_info_per_sta *info_per_sta)
+{
+       u8 i;
+       u8 sta_num = sounding_req->sta_num;
+       u8 q_matrix_bitmap = sounding_req->q_matrix_bitmap;
+       u8 bw = sounding_req->req_txbw;
+       u8 nr = sounding_req->ndp_nsts;
+       u32 total_size = 0;
+
+       /*
+        * In case of MU sounding only one Q matrix is generated.
+        * Otherwise, the number of Q matrices equals to the number of stations
+        */
+       if (sta_num > 1 &&
+           sounding_req->sounding_type != SOUNDING_TYPE_HE_MU &&
+           sounding_req->sounding_type != SOUNDING_TYPE_VHT_MU)
+               for (i = 0; i < sta_num; i++)
+                       total_size +=
+                       cl_sounding_get_q_matrix_size(cl_hw, &info_per_sta[i], 1, bw, nr);
+       else
+               total_size =
+                       cl_sounding_get_q_matrix_size(cl_hw, info_per_sta, sta_num, bw, nr);
+
+       /*
+        * If additional SU Q matrices should be generated - consider them also when calculating
+        * the required XMEM space
+        */
+       if (q_matrix_bitmap) {
+               for (i = 0; i < CL_MU_MIMO_MAX_STA_PER_GRP; i++)
+                       if (q_matrix_bitmap & BIT(i))
+                               total_size +=
+                               cl_sounding_get_q_matrix_size(cl_hw, &info_per_sta[i], 1, bw, nr);
+       }
+
+       return total_size;
+}
+
+static bool cl_sounding_is_enough_xmem_space(struct cl_hw *cl_hw,
+                                            const struct mm_sounding_req *sounding_req,
+                                            const struct sounding_info_per_sta *info_per_sta,
+                                            u32 *required_size)
+{
+       struct cl_xmem *xmem_db = &cl_hw->chip->xmem_db;
+       u32 req_mem = cl_sounding_get_required_xmem_size(cl_hw, sounding_req, info_per_sta);
+
+       if (required_size)
+               *required_size = req_mem;
+
+       return ((xmem_db->size - xmem_db->total_used) >= req_mem);
+}
+
+static void cl_sounding_fill_info_per_sta(struct cl_hw *cl_hw, u8 sounding_type, u8 bw, u8 sta_num,
+                                         struct cl_sta **cl_sta_arr,
+                                         struct sounding_info_per_sta *info_per_sta,
+                                         u8 *n_sts)
+{
+       u8 i;
+       u8 min_sts = cl_hw->num_antennas;
+       struct cl_sta *cl_sta = NULL;
+       u8 mu_fb_type_ng_cb_size = FEEDBACK_TYPE_MU_NG_4_CODEBOOK_SIZE_9_7;
+       u8 curr_fb_type_ng_cb_size;
+       bool should_update_fb_type_ng_cb_size = false;
+
+       for (i = 0; i < sta_num; i++) {
+               cl_sta = cl_sta_arr[i];
+
+               if (!cl_sta)
+                       continue;
+
+               info_per_sta[i].sta_idx = cl_sta->sta_idx;
+               info_per_sta[i].nc = cl_sta->bf_db.nc;
+
+               /* TODO: Add handling of MU-MIMO case. The nc should be taken from the group */
+
+               min_sts = min(min_sts, cl_sta->bf_db.beamformee_sts);
+
+               switch (sounding_type) {
+               case SOUNDING_TYPE_HE_CQI:
+               case SOUNDING_TYPE_HE_SU:
+               case SOUNDING_TYPE_VHT_SU:
+               case SOUNDING_TYPE_VHT_MU:
+                       info_per_sta[i].fb_type_ng_cb_size =
+                               FEEDBACK_TYPE_SU_NG_4_CODEBOOK_SIZE_4_2;
+                       break;
+               case SOUNDING_TYPE_HE_SU_TB:
+                       info_per_sta[i].fb_type_ng_cb_size =
+                               FEEDBACK_TYPE_SU_NG_4_CODEBOOK_SIZE_6_4;
+                       break;
+               case SOUNDING_TYPE_HE_CQI_TB:
+                       info_per_sta[i].fb_type_ng_cb_size =
+                               FEEDBACK_TYPE_CQI_TB;
+                       break;
+               case SOUNDING_TYPE_HE_MU:
+                       if (bw == CHNL_BW_160 &&
+                           info_per_sta[i].nc >= WRS_SS_3 &&
+                           min_sts == MAX_ANTENNAS) {
+                               should_update_fb_type_ng_cb_size = true;
+
+                               if (cl_sounding_is_sta_codebook_size_75_capable(cl_hw, cl_sta)) {
+                                       curr_fb_type_ng_cb_size =
+                                               FEEDBACK_TYPE_MU_NG_4_CODEBOOK_SIZE_7_5;
+                               } else if (cl_sounding_is_sta_ng_16_capable(cl_hw, cl_sta, true)) {
+                                       curr_fb_type_ng_cb_size =
+                                               FEEDBACK_TYPE_MU_NG_16_CODEBOOK_SIZE_9_7;
+                               } else {
+                                       curr_fb_type_ng_cb_size =
+                                               FEEDBACK_TYPE_MU_NG_4_CODEBOOK_SIZE_9_7;
+                                       mu_fb_type_ng_cb_size =
+                                               FEEDBACK_TYPE_MU_NG_4_CODEBOOK_SIZE_9_7;
+                                       min_sts--;
+                               }
+
+                               if ((SOUNDING_NG_VAL(curr_fb_type_ng_cb_size) >
+                                                       SOUNDING_NG_VAL(mu_fb_type_ng_cb_size)) ||
+                                   (SOUNDING_CODEBOOK_SIZE_VAL(curr_fb_type_ng_cb_size) <
+                                    SOUNDING_CODEBOOK_SIZE_VAL(mu_fb_type_ng_cb_size)))
+                                       mu_fb_type_ng_cb_size = curr_fb_type_ng_cb_size;
+                       }
+
+                       info_per_sta[i].fb_type_ng_cb_size = mu_fb_type_ng_cb_size;
+                       break;
+               default:
+                       sounding_pr_trace("Invalid sounding type %u\n", sounding_type);
+                       break;
+               }
+       }
+
+       *n_sts = min_sts;
+
+       if (should_update_fb_type_ng_cb_size)
+               for (i = 0; i < sta_num; i++)
+                       info_per_sta[i].fb_type_ng_cb_size = mu_fb_type_ng_cb_size;
+}
+
+struct cl_sounding_info *cl_sounding_elem_alloc(struct cl_hw *cl_hw, u32 v_mat_len)
+{
+       struct cl_sounding_info *elem = NULL;
+       dma_addr_t phys_dma_addr;
+       struct v_matrix_header *buf = NULL;
+
+       elem = kzalloc(sizeof(*elem), GFP_KERNEL);
+
+       if (!elem) {
+               CL_DBG(cl_hw, DBG_LVL_ERROR, "kzalloc failed\n");
+               return NULL;
+       }
+
+       buf = dma_alloc_coherent(cl_hw->chip->dev, v_mat_len, &phys_dma_addr, GFP_KERNEL);
+
+       if (!buf) {
+               CL_DBG(cl_hw, DBG_LVL_ERROR, "dma_alloc_coherent failed. size=%u\n", v_mat_len);
+               kfree(elem);
+               return NULL;
+       }
+
+       elem->v_matrices_data = buf;
+       elem->v_matrices_dma_addr = phys_dma_addr;
+       elem->v_matrices_data_len = v_mat_len;
+
+       return elem;
+}
+
+void cl_sounding_elem_free(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       struct v_matrix_header *v_data = elem->v_matrices_data;
+
+       if (v_data) {
+               dma_free_coherent(cl_hw->chip->dev, elem->v_matrices_data_len, (void *)v_data,
+                                 elem->v_matrices_dma_addr);
+       } else {
+               sounding_pr_err("%s: v_matrices_data is NULL for sid %u\n",
+                               __func__, elem->sounding_id);
+       }
+
+       elem->v_matrices_data = NULL;
+       kfree(elem);
+}
+
+void cl_sounding_req_success(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       if (!elem->gid)
+               cl_bf_sounding_req_success(cl_hw, elem);
+}
+
+void cl_sounding_req_failure(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       if (!elem->gid)
+               cl_bf_sounding_req_failure(cl_hw, elem);
+}
+
+static void cl_sounding_increase_num_profiles(struct cl_hw *cl_hw, u8 sounding_type, u8 sta_num)
+{
+       if (SOUNDING_TYPE_IS_CQI(sounding_type))
+               cl_hw->sounding.cqi_profiles += sta_num;
+       else
+               cl_hw->sounding.active_profiles += sta_num;
+}
+
+static void cl_sounding_decrease_num_profiles(struct cl_hw *cl_hw, u8 sounding_type, u8 sta_num)
+{
+       if (SOUNDING_TYPE_IS_CQI(sounding_type))
+               cl_hw->sounding.cqi_profiles -= sta_num;
+       else
+               cl_hw->sounding.active_profiles -= sta_num;
+}
+
+static void _cl_sounding_add(struct cl_hw *cl_hw, struct cl_sounding_info *elem, u8 sounding_id,
+                            u32 req_xmem)
+{
+       write_lock_bh(&cl_hw->sounding.list_lock);
+       elem->sounding_id = sounding_id;
+       elem->xmem_space = req_xmem;
+       cl_hw->chip->xmem_db.total_used += req_xmem;
+       cl_hw->sounding.num_soundings++;
+       list_add_tail(&elem->list, &cl_hw->sounding.head);
+       cl_sounding_increase_num_profiles(cl_hw, elem->type, elem->sta_num);
+       write_unlock_bh(&cl_hw->sounding.list_lock);
+}
+
+static void cl_sounding_remove_from_list(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       /* Remove the sounding sequence from the list and update the XMEM and profile counters */
+       write_lock_bh(&cl_hw->sounding.list_lock);
+       list_del(&elem->list);
+       cl_hw->chip->xmem_db.total_used -= elem->xmem_space;
+       cl_hw->sounding.num_soundings--;
+       cl_sounding_decrease_num_profiles(cl_hw, elem->type, elem->sta_num);
+       write_unlock_bh(&cl_hw->sounding.list_lock);
+}
+
+static void cl_sounding_remove_recovery(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       u8 i;
+
+       cl_sounding_remove_from_list(cl_hw, elem);
+
+       /* Set invalid sid for all STAs related to this sounding sequence */
+       for (i = 0; i < elem->sta_num; i++) {
+               struct cl_sta *cl_sta = elem->su_cl_sta_arr[i];
+
+               if (cl_sta)
+                       cl_sta->su_sid = INVALID_SID;
+       }
+
+       /* Free the deleted sounding element */
+       cl_sounding_elem_free(cl_hw, elem);
+}
+
+static void cl_sounding_start_handler(struct cl_hw *cl_hw, struct sounding_work_data *data)
+{
+       struct mm_sounding_req sounding_req;
+       struct mm_sounding_cfm *cfm = NULL;
+       int ret = 0;
+       u32 len = 0;
+       u32 req_xmem = 0;
+       struct cl_sounding_info *elem = NULL;
+       u8 sounding_type = data->sounding_type;
+       u8 bw = data->bw;
+       u8 i, sta_num = 0;
+       u8 q_matrix_bitmap = data->q_matrix_bitmap;
+       u8 min_nsts = 0;
+       struct cl_sta *cl_sta_arr[CL_MU_MAX_STA_PER_GROUP] = {0};
+
+       cl_sta_lock_bh(cl_hw);
+
+       for (i = 0; i < data->sta_num; i++) {
+               u8 sta_idx = data->sta_indices[i];
+               struct cl_sta *cl_sta;
+
+               cl_sta = cl_sta_get(cl_hw, sta_idx);
+
+               if (!cl_sta)
+                       continue;
+
+               cl_sta_arr[sta_num] = cl_sta;
+               sta_num++;
+       }
+
+       if (!sta_num) {
+               cl_sta_unlock_bh(cl_hw);
+               sounding_pr_err("%s: No STA found!\n", __func__);
+               return;
+       }
+
+       q_matrix_bitmap &= Q_MATRIX_BITMAP_MASK;
+
+       /* Configure sounding request parameters */
+       sounding_req.start = true;
+       sounding_req.sounding_type = sounding_type;
+       sounding_req.req_txbw = bw;
+       sounding_req.sta_num = sta_num;
+       sounding_req.interval = cl_sounding_get_interval(cl_hw);
+       sounding_req.lifetime = cl_sounding_get_lifetime(cl_hw, sounding_req.interval);
+       sounding_req.q_matrix_bitmap = q_matrix_bitmap;
+       cl_sounding_fill_info_per_sta(cl_hw, sounding_type, bw, sta_num, cl_sta_arr,
+                                     sounding_req.info_per_sta, &min_nsts);
+       cl_sta_unlock_bh(cl_hw);
+
+       sounding_req.ndp_nsts = min_nsts;
+
+       if (data->is_recovery) {
+               elem = data->elem;
+       } else {
+               /*
+                * Check if there is enough XMEM space.
+                * Should be called after filling sounding req struct
+                */
+               if (!cl_sounding_is_enough_xmem_space(cl_hw, &sounding_req,
+                                                     sounding_req.info_per_sta, &req_xmem)) {
+                       sounding_pr_err("There is not enough space in XMEM!\n");
+                       return;
+               }
+
+               /* Should be called after filling info per STA */
+               len = cl_sounding_get_v_matrices_data_size(cl_hw, sounding_req.info_per_sta,
+                                                          sta_num, bw, min_nsts);
+               elem = cl_sounding_elem_alloc(cl_hw, len);
+
+               if (!elem)
+                       return;
+
+               elem->type = sounding_type;
+               elem->bw = bw;
+               elem->sta_num = sta_num;
+               elem->q_matrix_bitmap = q_matrix_bitmap;
+
+               if (data->gid)
+                       elem->gid = data->gid;
+               else
+                       memcpy(elem->su_cl_sta_arr, cl_sta_arr,
+                              sta_num * sizeof(cl_sta_arr[0]));
+       }
+
+       sounding_req.host_address = cpu_to_le32(elem->v_matrices_dma_addr);
+
+       /* Print request parameters */
+       sounding_pr_trace("Request: start=%u, bfr_lifetime=%u, interval=%u, "
+                          "req_txbw=%u, ndp_nsts=%u, sounding_type=%u\n",
+                          sounding_req.start,
+                          sounding_req.lifetime,
+                          sounding_req.interval,
+                          sounding_req.req_txbw,
+                          sounding_req.ndp_nsts,
+                          sounding_req.sounding_type);
+
+       /* Send message to firmware */
+       ret = cl_msg_tx_sounding(cl_hw, &sounding_req);
+
+       cfm = cl_hw->msg_cfm_params[MM_SOUNDING_CFM];
+
+       /* Check firmware response */
+       if (ret == 0 && cfm) {
+
+               ret = cl_sounding_check_response(cl_hw, cfm->param_err);
+
+               if (ret == 0) {
+                       if (!data->is_recovery)
+                               _cl_sounding_add(cl_hw, elem, cfm->sounding_id, req_xmem);
+
+                       cl_sounding_req_success(cl_hw, elem);
+
+                       sounding_pr_trace("Sounding %u was enabled successfully\n",
+                                         cfm->sounding_id);
+               } else {
+                       cl_sounding_req_failure(cl_hw, elem);
+
+                       if (data->is_recovery)
+                               cl_sounding_remove_recovery(cl_hw, elem);
+               }
+       } else {
+               sounding_pr_err("%s: failed to send message (%d)\n", __func__, ret);
+               cl_sounding_req_failure(cl_hw, elem);
+
+               if (data->is_recovery)
+                       cl_sounding_remove_recovery(cl_hw, elem);
+               else
+                       cl_sounding_elem_free(cl_hw, elem);
+       }
+
+       /* Free message confirmation */
+       cl_msg_tx_free_cfm_params(cl_hw, MM_SOUNDING_CFM);
+}
+
+static void _cl_sounding_remove(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       u8 i;
+       struct sounding_work_data data = {
+               .cl_hw = cl_hw,
+               .bw = elem->bw,
+               .start = true,
+               .is_recovery = false,
+               .sta_num = 0
+       };
+
+       cl_sounding_remove_from_list(cl_hw, elem);
+
+       for (i = 0; i < elem->sta_num; i++) {
+               struct cl_sta *cl_sta = elem->su_cl_sta_arr[i];
+
+               if (!cl_sta)
+                       continue;
+
+               cl_sta->su_sid = INVALID_SID;
+
+               /* After stopping the multi STA sounding - check if a new sounding is needed */
+               if (elem->sounding_restart_required) {
+                       if (!cl_sta->bf_db.sounding_remove_required) {
+                               data.sta_indices[data.sta_num] = cl_sta->sta_idx;
+                               data.sta_num++;
+                       } else {
+                               cl_sta->bf_db.sounding_remove_required = false;
+                       }
+               }
+       }
+
+       /* Start a new sounding for the remaining stations only when needed */
+       if (data.sta_num) {
+               /* Determine new sounding type */
+               if (SOUNDING_TYPE_IS_CQI(elem->type)) {
+                       if (data.sta_num > 1)
+                               data.sounding_type = elem->type;
+                       else
+                               data.sounding_type = SOUNDING_TYPE_HE_CQI;
+               } else if (SOUNDING_TYPE_IS_VHT(elem->type)) {
+                       data.sounding_type = SOUNDING_TYPE_VHT_SU;
+               } else {
+                       if (data.sta_num > 1)
+                               data.sounding_type = SOUNDING_TYPE_HE_SU_TB;
+                       else
+                               data.sounding_type = SOUNDING_TYPE_HE_SU;
+               }
+
+               cl_sounding_start_handler(cl_hw, &data);
+       }
+
+       /* Free the deleted sounding element */
+       cl_sounding_elem_free(cl_hw, elem);
+}
+
+static void cl_sounding_stop_handler(struct cl_hw *cl_hw, struct cl_sounding_info *elem)
+{
+       struct mm_sounding_req sounding_req;
+       int ret = 0;
+
+       if (!elem) {
+               sounding_pr_err("elem is NULL!!\n");
+               return;
+       }
+
+       /* Configure sounding request parameters */
+       sounding_req.start = false;
+       sounding_req.sounding_type = elem->type;
+       sounding_req.sid = elem->sounding_id;
+
+       /* Print request parameters */
+       sounding_pr_trace("Delete request: sid=%u, sounding_type=%u\n",
+                         elem->sounding_id, elem->type);
+
+       /* Send message to firmware */
+       ret = cl_msg_tx_sounding(cl_hw, &sounding_req);
+
+       /* Check firmware response */
+       if (ret)
+               sounding_pr_err("%s: failed to send message (%d)\n", __func__, ret);
+       else
+               /* Free message confirmation */
+               cl_msg_tx_free_cfm_params(cl_hw, MM_SOUNDING_CFM);
+
+       /* Remove the sounding sequence from the list and update the used XMEM counter.
+        * Notice that elem is freed and shouldn't be accessed after the call to this function.
+        */
+       _cl_sounding_remove(cl_hw, elem);
+}
+
+static void cl_sounding_handler_send_request(struct work_struct *work)
+{
+       struct sounding_work_data *data = (struct sounding_work_data *)work;
+       struct cl_hw *cl_hw = data->cl_hw;
+
+       if (data->start) {
+               cl_sounding_start_handler(cl_hw, data);
+       } else {
+               u8 sid;
+               u8 sta_idx = data->sta_indices[0];
+               struct cl_sta *cl_sta;
+
+               cl_sta_lock_bh(cl_hw);
+               cl_sta = cl_sta_get(cl_hw, sta_idx);
+               sid = cl_sta ? cl_sta->su_sid : U8_MAX;
+               cl_sta_unlock_bh(cl_hw);
+
+               if (data->elem)
+                       cl_sounding_stop_handler(cl_hw, data->elem);
+               else
+                       cl_sounding_stop_by_sid(cl_hw, sid, false);
+       }
+
+       kfree(data);
+}
+
+static u16 cl_sounding_calc_interval(struct cl_hw *cl_hw, u8 active_profiles)
+{
+       /* Sounding interval = min interval + [(active_profiles - 1) / STA step] * interval step */
+
+       u16 *coefs = cl_hw->conf->ce_sounding_interval_coefs;
+       u16 min_interval = coefs[SOUNDING_INTERVAL_COEF_MIN_INTERVAL];
+       u16 max_interval = coefs[SOUNDING_INTERVAL_COEF_MAX_INTERVAL];
+       u8 sta_step = coefs[SOUNDING_INTERVAL_COEF_STA_STEP];
+       u8 interval_step = coefs[SOUNDING_INTERVAL_COEF_INTERVAL_STEP];
+       u16 ret = min_interval;
+
+       if (active_profiles <= sta_step)
+               return ret;
+
+       active_profiles--;
+       ret += (active_profiles / sta_step) * interval_step;
+
+       return min(ret, max_interval);
+}
+
+static void cl_sounding_handler_change_interval(struct work_struct *work)
+{
+       struct sounding_work_data *data = (struct sounding_work_data *)work;
+       struct cl_hw *cl_hw = data->cl_hw;
+       struct mm_sounding_interval_cfm *sounding_interval_cfm = NULL;
+       int ret = 0;
+       /* Configure sounding request parameters */
+       u16 interval = cl_sounding_get_interval(cl_hw);
+       u16 lifetime = cl_sounding_get_lifetime(cl_hw, interval);
+
+       sounding_pr_trace("Sounding interval request: sta_idx=%d, interval=%u, "
+                         "lifetime=%u, sounding_type=%u\n",
+                         CL_SOUNDING_ALL_STA, interval, lifetime, data->sounding_type);
+
+       /* Start/Stop synchronize sounding request periodically */
+       ret = cl_msg_tx_sounding_interval(cl_hw, interval, lifetime, data->sounding_type,
+                                         CL_SOUNDING_ALL_STA);
+       sounding_interval_cfm = (struct mm_sounding_interval_cfm *)
+                               (cl_hw->msg_cfm_params[MM_SOUNDING_INTERVAL_CFM]);
+
+       if (ret == 0 && sounding_interval_cfm)
+               cl_sounding_check_response(cl_hw, sounding_interval_cfm->param_err);
+       else
+               sounding_pr_err("%s: failed to send message (%d)\n", __func__, ret);
+
+       cl_msg_tx_free_cfm_params(cl_hw, MM_SOUNDING_INTERVAL_CFM);
+       kfree(data);
+}
+
+static void cl_sounding_recovery_reset(struct cl_hw *cl_hw)
+{
+       struct cl_sounding_db *sounding_db = &cl_hw->sounding;
+
+       memset(sounding_db->active_profiles_prev, 0, sizeof(u8) * CL_SOUNDING_STABILITY_TIME);
+       sounding_db->active_profiles_idx = 0;
+       cl_sta_loop(cl_hw, cl_bf_reset_sounding_ind);
+}
+
+static int cl_sounding_cli_help(struct cl_hw *cl_hw)
+{
+       char *ret_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+
+       if (!ret_buf)
+               return -ENOMEM;
+
+       snprintf(ret_buf, PAGE_SIZE,
+                "sounding usage\n"
+                "-a: Create a sounding sequence [type].[bw].[gid].[q_matrix_bitmap].[sta_idx 1]"
+                "...[sta_idx n]\n\t* Available types: 0-HE_SU, 1-HE_SU_TB, 2-VHT_SU, 3-HE_CQI, "
+                "4-HE_CQI_TB, 5-HE_MU, 6-VHT_MU\n\t"
+                "* Notice that gid and q_matrix_bitmap should be passed only for MU sounding\n"
+                "-b: Delete a sounding sequence [sounding_id]\n"
+                "-c: Print sounding configuration\n"
+                "-d: Set debug level [0-Off, ..., 4-Highest]\n"
+                "-p: Print sounding db\n"
+                "-s: Simulate sounding indication [sid].[sta_idx (255 in case of MU)]\n");
+
+       err = cl_vendor_reply(cl_hw, ret_buf, strlen(ret_buf));
+       kfree(ret_buf);
+
+       return err;
+}
+
+void cl_sounding_init(struct cl_hw *cl_hw)
+{
+       struct cl_sounding_db *sounding_db = &cl_hw->sounding;
+
+       memset(sounding_db, 0, sizeof(*sounding_db));
+       sounding_db->sounding_wq = create_workqueue("cl_sounding_wq");
+       sounding_db->current_interval =
+               cl_hw->conf->ce_sounding_interval_coefs[SOUNDING_INTERVAL_COEF_MIN_INTERVAL];
+       sounding_db->dbg_level = 1;
+       cl_hw->chip->xmem_db.size = XMEM_SIZE;
+       INIT_LIST_HEAD(&sounding_db->head);
+       rwlock_init(&sounding_db->list_lock);
+}
+
+void cl_sounding_close(struct cl_hw *cl_hw)
+{
+       struct cl_sounding_info *elem, *tmp;
+
+       if (cl_hw->sounding.sounding_wq)
+               destroy_workqueue(cl_hw->sounding.sounding_wq);
+
+       list_for_each_entry_safe(elem, tmp, &cl_hw->sounding.head, list) {
+               /* Don't try to start a new sounding sequence after stopping this one */
+               elem->sounding_restart_required = false;
+               cl_sounding_stop_handler(cl_hw, elem);
+       }
+}
+
+struct cl_sounding_info *cl_sounding_get_elem(struct cl_hw *cl_hw, u8 sounding_id)
+{
+       struct cl_sounding_info *elem = NULL;
+
+       read_lock_bh(&cl_hw->sounding.list_lock);
+
+       list_for_each_entry(elem, &cl_hw->sounding.head, list) {
+               if (elem->sounding_id == sounding_id) {
+                       read_unlock_bh(&cl_hw->sounding.list_lock);
+                       return elem;
+               }
+       }
+
+       read_unlock_bh(&cl_hw->sounding.list_lock);
+
+       return NULL;
+}
+
+void cl_sounding_send_request(struct cl_hw *cl_hw, struct cl_sta **cl_sta_arr,
+                             u8 sta_num, bool enable, u8 sounding_type, u8 bw,
+                             u8 q_matrix_bitmap, struct cl_sounding_info *recovery_elem)
+{
+       struct sounding_work_data *data;
+       struct cl_sounding_info *elem = NULL;
+       u8 i;
+       bool background = (preempt_count() != 0);
+
+       if (!cl_sta_arr) {
+               sounding_pr_err("Sta_indices is NULL! for sounding type %u\n", sounding_type);
+               return;
+       }
+
+       if (cl_band_is_24g(cl_hw) && SOUNDING_TYPE_IS_VHT(sounding_type)) {
+               sounding_pr_err("A VHT sounding type (%u) is not supported in 2.4g band\n",
+                               sounding_type);
+               return;
+       }
+
+       /*
+        * When Multiple STAs are members of a single sounding process, that is about to be stopped,
+        * we want to schedule the stopping work only once and possibly start another sounding
+        * sequence for STAs that still want to use it.
+        */
+       if (!enable) {
+               struct cl_sta *cl_sta = cl_sta_arr[0];
+
+               if (cl_sta) {
+                       u8 sid = cl_sta->su_sid;
+
+                       if (sid != INVALID_SID) {
+                               elem = cl_sounding_get_elem(cl_hw, sid);
+
+                               if (!elem) {
+                                       sounding_pr_trace("Sounding %u not found\n", sid);
+                                       return;
+                               }
+
+                               cl_sta->bf_db.sounding_remove_required = true;
+
+                               if (elem->sounding_restart_required)
+                                       return;
+
+                               elem->sounding_restart_required = true;
+                       }
+               }
+       }
+
+       /* data will be freed in work handler */
+       data = kzalloc(sizeof(*data), GFP_ATOMIC);
+
+       if (!data)
+               return;
+
+       data->cl_hw = cl_hw;
+       data->start = enable;
+       data->sounding_type = sounding_type;
+       data->bw = bw;
+       data->is_recovery = cl_recovery_in_progress(cl_hw);
+       data->elem = recovery_elem ? recovery_elem : elem;
+
+       /* Fill cl_sta_arr */
+       for (i = 0; i < sta_num; i++)
+               data->sta_indices[i] = cl_sta_arr[i]->sta_idx;
+
+       data->sta_num = sta_num;
+
+       if (background) {
+               INIT_WORK(&data->work, cl_sounding_handler_send_request);
+               queue_work(cl_hw->sounding.sounding_wq, &data->work);
+       } else {
+               cl_sounding_handler_send_request((struct work_struct *)data);
+       }
+}
+
+static void cl_sounding_change_interval(struct cl_hw *cl_hw, u8 sounding_type)
+{
+       /* Data will be freed in work handler */
+       struct sounding_work_data *data = kzalloc(sizeof(*data), GFP_ATOMIC);
+
+       if (!data)
+               return;
+
+       INIT_WORK(&data->work, cl_sounding_handler_change_interval);
+       data->cl_hw = cl_hw;
+       data->sounding_type = sounding_type;
+       queue_work(cl_hw->sounding.sounding_wq, &data->work);
+}
+
+u8 cl_sounding_get_active_profiles(struct cl_hw *cl_hw)
+{
+       return cl_hw->sounding.active_profiles;
+}
+
+void cl_sounding_stop_by_sid(struct cl_hw *cl_hw, u8 sid, bool sounding_restart_check)
+{
+       struct cl_sounding_info *elem = cl_sounding_get_elem(cl_hw, sid);
+
+       if (!elem) {
+               sounding_pr_trace("Sounding with id %u not found or is in the middle of removal\n",
+                                 sid);
+               return;
+       }
+
+       elem->sounding_restart_required = sounding_restart_check;
+       cl_sounding_stop_handler(cl_hw, elem);
+}
+
+void cl_sounding_maintenance(struct cl_hw *cl_hw)
+{
+       /*
+        * Change sounding_index according to the number of active_profiles.
+        * sounding_index is modified only if number of active_profiles is stable for 5 seconds.
+        *
+        * Examples:
+        * e.g #1: active_profiles=2, active_profiles_prev=3,3,3,3,3 - stabilised on 3
+        * e.g #3: active_profiles=2, active_profiles_prev=1,1,1,1,1 - stabilised on 1
+        * e.g #2: active_profiles=5, active_profiles_prev=6,7,7,6,6 - stabilised on 6
+        * e.g #4: active_profiles=5, active_profiles_prev=4,3,3,2,4 - stabilised on 4
+        */
+
+       int i = 0;
+       u8 active_profiles_min = 255;
+       u8 active_profiles_max = 0;
+       u8 active_profiles = cl_hw->sounding.last_conf_active_profiles;
+       u8 active_profiles_new = 0;
+       u16 interval;
+       u16 interval_new;
+
+       /* Add to last 5 sec buffer */
+       cl_hw->sounding.active_profiles_prev[cl_hw->sounding.active_profiles_idx] =
+               cl_hw->sounding.active_profiles;
+
+       /* Increase cyclic index */
+       cl_hw->sounding.active_profiles_idx++;
+       if (cl_hw->sounding.active_profiles_idx == CL_SOUNDING_STABILITY_TIME)
+               cl_hw->sounding.active_profiles_idx = 0;
+
+       /* Find active_profiles min/max in last 5 seconds */
+       for (i = 0; i < CL_SOUNDING_STABILITY_TIME; i++) {
+               if (cl_hw->sounding.active_profiles_prev[i] < active_profiles_min)
+                       active_profiles_min = cl_hw->sounding.active_profiles_prev[i];
+
+               if (cl_hw->sounding.active_profiles_prev[i] > active_profiles_max)
+                       active_profiles_max = cl_hw->sounding.active_profiles_prev[i];
+       }
+
+       if (active_profiles < active_profiles_min)
+               active_profiles_new = active_profiles_min;
+       else if (active_profiles > active_profiles_max)
+               active_profiles_new = active_profiles_max;
+       else /* Active_profiles in last 5 seconds did not change or is not stable */
+               return;
+
+       interval = cl_sounding_calc_interval(cl_hw, active_profiles);
+       interval_new = cl_sounding_calc_interval(cl_hw, active_profiles_new);
+
+       /* Check if sounding interval changed */
+       if (interval != interval_new) {
+               cl_hw->sounding.last_conf_active_profiles = active_profiles_new;
+               cl_hw->sounding.current_interval = interval_new;
+               cl_sounding_change_interval(cl_hw, SOUNDING_TYPE_MAX);
+               sounding_pr_trace("Interval: current = %u, new = %u\n",
+                                 interval, interval_new);
+       }
+}
+
+u16 cl_sounding_get_interval(struct cl_hw *cl_hw)
+{
+       return cl_hw->sounding.current_interval;
+}
+
+static void cl_sounding_indication_pr(struct cl_hw *cl_hw,
+                                     struct mm_sounding_ind *ind,
+                                     struct v_matrix_header *v_matrix,
+                                     u8 *avg_snr)
+{
+       sounding_pr_info("Sounding indication: nc index = %u, BFR BW = %u, "
+                 "SNR1 = %u, SNR2 = %u, SNR3 = %u, SNR4 = %u, SNR5 = %u, SNR6 = %u,"
+                 "feedback type = %u, sta index = %u\n",
+                 v_matrix->nc_index, v_matrix->bw,
+                 avg_snr[0], avg_snr[1], avg_snr[2], avg_snr[3], avg_snr[4],
+                 avg_snr[5], ind->sounding_type, ind->sta_idx);
+}
+
+static void cl_sounding_indication_su(struct cl_hw *cl_hw,
+                                     struct mm_sounding_ind *ind,
+                                     struct cl_sounding_info *sounding_elem)
+{
+       struct cl_sta *cl_sta;
+       struct v_matrix_header *v_matrix = NULL;
+       u8 *avg_snr = NULL;
+       bool pairing = false;
+
+       v_matrix = sounding_elem->v_matrices_data + ind->v_matrix_offset[0];
+       avg_snr = (u8 *)v_matrix + v_matrix->padding;
+
+       cl_sta_lock(cl_hw);
+       cl_sta = cl_sta_get(cl_hw, ind->sta_idx);
+
+       if (cl_sta) {
+               struct cl_bf_sta_db *bf_db = &cl_sta->bf_db;
+
+               /* Update Nc for the current STA */
+               bf_db->nc = v_matrix->nc_index;
+               bf_db->sounding_indications++;
+
+               if (bf_db->sounding_indications == 1) {
+                       /*
+                        * After getting first indication disable the timer and set the BF
+                        * bit in the firmware rate flags.
+                        */
+                       cl_timer_disable(&bf_db->timer);
+                       cl_bf_update_rate(cl_hw, cl_sta);
+                       pairing = true;
+               }
+       }
+
+       cl_sta_unlock(cl_hw);
+
+       /* Send a msg to fw to pair the STA with sounding ID */
+       if (pairing)
+               cl_msg_tx_sounding_pairing(cl_hw, ind->sid, ind->sounding_type, 0, ind->sta_idx);
+
+       cl_sounding_indication_pr(cl_hw, ind, v_matrix, avg_snr);
+}
+
+void cl_sounding_indication(struct cl_hw *cl_hw, struct mm_sounding_ind *ind)
+{
+       struct cl_sounding_info *sounding_elem = NULL;
+       bool is_mu = false;
+
+       sounding_elem = cl_sounding_get_elem(cl_hw, ind->sid);
+
+       if (!sounding_elem) {
+               sounding_pr_err("[%s]: sounding id %u not found!\n", __func__, ind->sid);
+               return;
+       }
+
+       switch (ind->sounding_type) {
+       case SOUNDING_TYPE_HE_SU:
+       case SOUNDING_TYPE_HE_SU_TB:
+       case SOUNDING_TYPE_VHT_SU:
+       case SOUNDING_TYPE_HE_CQI:
+       case SOUNDING_TYPE_HE_CQI_TB:
+               is_mu = false;
+               break;
+       case SOUNDING_TYPE_HE_MU:
+               is_mu = ind->mu;
+               break;
+       case SOUNDING_TYPE_VHT_MU:
+               is_mu = true;
+               break;
+       default:
+               sounding_pr_err("[%s]: Invalid sounding type %u\n", __func__,
+                               ind->sounding_type);
+               return;
+       }
+
+       cl_sounding_indication_su(cl_hw, ind, sounding_elem);
+}
+
+void cl_sounding_recovery(struct cl_hw *cl_hw)
+{
+       /*
+        * After recovery process we need to update sounding requests and
+        * sounding interval in firmware
+        */
+       struct cl_sounding_info *elem;
+
+       /* No sounding is active */
+       if (!cl_hw->sounding.num_soundings)
+               return;
+
+       /* Reset sounding parameters */
+       cl_sounding_recovery_reset(cl_hw);
+
+       /*
+        * Go over all clients that had sounding before recovery,
+        * and send a new sounding request to firmware.
+        */
+
+       sounding_pr_trace("Start sounding recovery\n");
+
+       list_for_each_entry(elem, &cl_hw->sounding.head, list)
+               cl_bf_sounding_start(cl_hw, elem->type, elem->su_cl_sta_arr, elem->sta_num, elem);
+}
+
+int cl_sounding_cli_create(struct cl_hw *cl_hw, struct cli_params *cli_params)
+{
+       u8 i;
+       u8 max_sta_params = 0;
+       u8 curr_param_idx = 0;
+       bool is_mu = false;
+       struct sounding_work_data *data = NULL;
+       int err = 0;
+
+       /* parameters extraction and validity checks */
+       if (cli_params->num_params < 4) {
+               sounding_pr_err("Too few parameters..\n");
+               return -EIO;
+       }
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+       if (!data)
+               return -ENOMEM;
+
+       data->sounding_type = (u8)cli_params->params[curr_param_idx++];
+       data->bw = (u8)cli_params->params[curr_param_idx++];
+       data->gid = (u8)cli_params->params[curr_param_idx++];
+       data->q_matrix_bitmap = (u8)cli_params->params[curr_param_idx++];
+
+       if (cl_band_is_24g(cl_hw) && SOUNDING_TYPE_IS_VHT(data->sounding_type)) {
+               sounding_pr_err("A VHT sounding type (%u) is not supported in 2.4g band\n",
+                               data->sounding_type);
+               err = -EIO;
+               goto out_err;
+       }
+
+       switch (data->sounding_type) {
+       case SOUNDING_TYPE_VHT_SU:
+       case SOUNDING_TYPE_HE_CQI:
+       case SOUNDING_TYPE_HE_SU:
+               max_sta_params = 1;
+               break;
+       case SOUNDING_TYPE_HE_SU_TB:
+       case SOUNDING_TYPE_HE_CQI_TB:
+               max_sta_params = CL_MU_OFDMA_MAX_STA_PER_GRP;
+               break;
+       case SOUNDING_TYPE_VHT_MU:
+       case SOUNDING_TYPE_HE_MU:
+               max_sta_params = 0;
+               is_mu = true;
+               break;
+       default:
+               sounding_pr_err("Invalid sounding type %u\n", data->sounding_type);
+               err = -EIO;
+               goto out_err;
+       }
+
+       if (cli_params->num_params > (curr_param_idx + max_sta_params)) {
+               sounding_pr_err("Too many parameters..\n");
+               err = -EIO;
+               goto out_err;
+       }
+
+       /* SU case */
+       struct cl_sta *cl_sta;
+
+       if (data->gid || data->q_matrix_bitmap) {
+               sounding_pr_err("Don't insert gid or q_matrix_bitmap != 0 for SU types\n");
+               err = -EIO;
+               goto out_err;
+       }
+
+       if (cli_params->num_params < curr_param_idx + 1) {
+               sounding_pr_err("For SU sounding types at least 1 STA idx is required\n");
+               err = -EIO;
+               goto out_err;
+       }
+
+       /* Fill cl_sta_arr */
+       for (i = 0;
+            curr_param_idx < cli_params->num_params; curr_param_idx++, i++) {
+               u8 sta_idx = (u8)cli_params->params[curr_param_idx];
+
+               cl_sta_lock_bh(cl_hw);
+               cl_sta = cl_sta_get(cl_hw, sta_idx);
+
+               if (!cl_sta || cl_sta->su_sid != INVALID_SID) {
+                       if (!cl_sta)
+                               sounding_pr_err("Invalid STA index %u\n", sta_idx);
+                       else
+                               sounding_pr_err("STA %u already associated with sid %u\n",
+                                               cl_sta->sta_idx, cl_sta->su_sid);
+                       cl_sta_unlock_bh(cl_hw);
+                       err = -EIO;
+                       goto out_err;
+               }
+
+               data->sta_indices[i] = cl_sta->sta_idx;
+               cl_sta_unlock_bh(cl_hw);
+       }
+
+       data->sta_num = i;
+
+       /* Start the new sounding sequence */
+       cl_sounding_start_handler(cl_hw, data);
+
+out_err:
+       kfree(data);
+       return err;
+}
+
+void cl_sounding_cli_print_configuration(struct cl_hw *cl_hw)
+{
+       struct cl_tcv_conf *conf = cl_hw->conf;
+
+       pr_debug("Min sounding interval:      %u\n",
+                conf->ce_sounding_interval_coefs[SOUNDING_INTERVAL_COEF_MIN_INTERVAL]);
+       pr_debug("Sounding interval STA step: %u\n",
+                conf->ce_sounding_interval_coefs[SOUNDING_INTERVAL_COEF_STA_STEP]);
+       pr_debug("Sounding interval step:     %u\n",
+                conf->ce_sounding_interval_coefs[SOUNDING_INTERVAL_COEF_INTERVAL_STEP]);
+       pr_debug("Max sounding interval:      %u\n",
+                conf->ce_sounding_interval_coefs[SOUNDING_INTERVAL_COEF_MAX_INTERVAL]);
+       pr_debug("Current interval:           %u\n\n", cl_sounding_get_interval(cl_hw));
+}
+
+void cl_sounding_cli_print_sounding_db(struct cl_hw *cl_hw)
+{
+#define STA_INDICES_STR_LEN 64
+
+       struct cl_sounding_info *elem = NULL;
+       char sta_indices_str[STA_INDICES_STR_LEN];
+       struct cl_sounding_db *sounding_db = &cl_hw->sounding;
+       struct cl_xmem *xmem_db = &cl_hw->chip->xmem_db;
+
+       pr_debug("----------------------------------------------------------------------"
+                "-------------------------------------------------------\n");
+       pr_debug("| sid |   type    | bw  | gid | sta num |            sta indices           |"
+                " q matrix bitmap | xmem space | v matrices size |");
+
+       read_lock_bh(&cl_hw->sounding.list_lock);
+
+       list_for_each_entry(elem, &cl_hw->sounding.head, list) {
+               u8 i, len = 0;
+
+               memset(sta_indices_str, '\0', sizeof(sta_indices_str));
+
+               for (i = 0; i < elem->sta_num; i++) {
+                       len += snprintf(sta_indices_str + len, STA_INDICES_STR_LEN - len,
+                                       "%u%s", elem->su_cl_sta_arr[i]->sta_idx,
+                                       (i == elem->sta_num - 1 ? "" : ","));
+               }
+
+               pr_debug("+-----+-----------+-----+-----+---------+"
+                        "----------------------------------+-----------------+------------+"
+                        "-----------------+\n");
+               pr_debug("| %2u  | %-9s | %3u | %2u  |    %1u    | %-32s |       0x%01x       |"
+                        "  %6u    |     %6u      |",
+                        elem->sounding_id, CL_SOUNDING_TYPE_2_STR(elem->type), BW_TO_MHZ(elem->bw),
+                        elem->gid, elem->sta_num, sta_indices_str, elem->q_matrix_bitmap,
+                        elem->xmem_space, elem->v_matrices_data_len);
+       }
+
+       read_unlock_bh(&cl_hw->sounding.list_lock);
+
+       pr_debug("-----------------------------------------------------------------------"
+                "------------------------------------------------------\n\n");
+       pr_debug("Num of soundings:         %u\n", sounding_db->num_soundings);
+       pr_debug("Active non-CQI profiles:  %u\n", sounding_db->active_profiles);
+       pr_debug("Active CQI profiles:      %u\n", sounding_db->cqi_profiles);
+       pr_debug("Xmem size:                %u\n", xmem_db->size);
+       pr_debug("Total xmem used:          %u\n", xmem_db->total_used);
+#undef STA_INDICES_STR_LEN
+}
+
+static void cl_sounding_cli_simulate_indication(struct cl_hw *cl_hw, u8 sid, u8 sta_idx)
+{
+       struct cl_sounding_info *sounding_elem = NULL;
+       struct mm_sounding_ind ind = {
+               .sid = sid,
+               .status = 1
+       };
+
+       sounding_elem = cl_sounding_get_elem(cl_hw, sid);
+
+       if (!sounding_elem) {
+               sounding_pr_err("[%s]: sounding id %u not found!\n", __func__, sid);
+               return;
+       }
+
+       ind.sounding_type = sounding_elem->type;
+       ind.sta_idx = sta_idx;
+
+       cl_sounding_indication_su(cl_hw, &ind, sounding_elem);
+}
+
+int cl_sounding_cli(struct cl_hw *cl_hw, struct cli_params *cli_params)
+{
+       u32 expected_params = 0;
+       bool create_sounding = false;
+       bool delete_sounding = false;
+       bool print_conf = false;
+       bool set_debug_level = false;
+       bool print_sounding_db = false;
+       bool simulate_indication = false;
+
+       switch (cli_params->option) {
+       case 'a':
+               create_sounding = true;
+               goto skip_exp_params_check;
+       case 'b':
+               delete_sounding = true;
+               expected_params = 1;
+               break;
+       case 'c':
+               print_conf = true;
+               expected_params = 0;
+               break;
+       case 'd':
+               set_debug_level = true;
+               expected_params = 1;
+               break;
+       case 'p':
+               print_sounding_db = true;
+               expected_params = 0;
+               break;
+       case 's':
+               simulate_indication = true;
+               expected_params = 2;
+               break;
+       case '?':
+               return cl_sounding_cli_help(cl_hw);
+       default:
+               cl_dbg_err(cl_hw, "Illegal option (%c) - try '?' for help\n", cli_params->option);
+               goto out_err;
+       }
+
+       if (expected_params != cli_params->num_params) {
+               cl_dbg_err(cl_hw, "Wrong number of arguments (expected %u) (actual %u)\n",
+                          expected_params, cli_params->num_params);
+               goto out_err;
+       }
+
+skip_exp_params_check:
+       if (create_sounding) {
+               cl_sounding_cli_create(cl_hw, cli_params);
+       } else if (delete_sounding) {
+               u8 sid = (u8)cli_params->params[0];
+
+               cl_sounding_stop_by_sid(cl_hw, sid, false);
+       } else if (print_conf) {
+               cl_sounding_cli_print_configuration(cl_hw);
+       } else if (set_debug_level) {
+               u8 dbg_level = (u8)cli_params->params[0];
+
+               cl_hw->sounding.dbg_level = dbg_level;
+       } else if (print_sounding_db) {
+               cl_sounding_cli_print_sounding_db(cl_hw);
+       } else if (simulate_indication) {
+               u8 sid = (u8)cli_params->params[0];
+               u8 sta_idx = (u8)cli_params->params[1];
+
+               cl_sounding_cli_simulate_indication(cl_hw, sid, sta_idx);
+       }
+
+       return 0;
+out_err:
+       return -EIO;
+}
--
2.30.0

________________________________
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any retransmission, dissemination, copying or other use of, or taking of any action in reliance upon this information is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Nothing contained herein shall be deemed as a representation, warranty or a commitment by Celeno. No warranties are expressed or implied, including, but not limited to, any implied warranties of non-infringement, merchantability and fitness for a particular purpose.
________________________________


  parent reply	other threads:[~2021-06-17 16:09 UTC|newest]

Thread overview: 262+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-17 15:58 [RFC v1 000/256] wireless: cl8k driver for Celeno IEEE 802.11ax devices viktor.barna
2021-06-17 15:58 ` [RFC v1 001/256] celeno: add Kconfig viktor.barna
2021-06-17 15:58 ` [RFC v1 002/256] celeno: add Makefile viktor.barna
2021-06-17 15:58 ` [RFC v1 003/256] cl8k: add Kconfig viktor.barna
2021-06-17 15:58 ` [RFC v1 004/256] cl8k: add Makefile viktor.barna
2021-06-17 15:58 ` [RFC v1 005/256] cl8k: add afe.c viktor.barna
2021-06-17 15:58 ` [RFC v1 006/256] cl8k: add afe.h viktor.barna
2021-06-17 15:58 ` [RFC v1 007/256] cl8k: add agc_params.c viktor.barna
2021-06-17 15:58 ` [RFC v1 008/256] cl8k: add agc_params.h viktor.barna
2021-06-17 15:58 ` [RFC v1 009/256] cl8k: add ampdu.c viktor.barna
2021-06-17 15:58 ` [RFC v1 010/256] cl8k: add ampdu.h viktor.barna
2021-06-17 15:58 ` [RFC v1 011/256] cl8k: add ate.c viktor.barna
2021-06-17 15:58 ` [RFC v1 012/256] cl8k: add ate.h viktor.barna
2021-06-17 15:58 ` [RFC v1 013/256] cl8k: add band.c viktor.barna
2021-06-17 15:58 ` [RFC v1 014/256] cl8k: add band.h viktor.barna
2021-06-17 15:58 ` [RFC v1 015/256] cl8k: add bf.c viktor.barna
2021-06-17 15:58 ` [RFC v1 016/256] cl8k: add bf.h viktor.barna
2021-06-17 15:58 ` [RFC v1 017/256] cl8k: add bus/pci/ipc.c viktor.barna
2021-06-17 15:58 ` [RFC v1 018/256] cl8k: add bus/pci/ipc.h viktor.barna
2021-06-17 15:58 ` [RFC v1 019/256] cl8k: add bus/pci/irq.c viktor.barna
2021-06-17 15:58 ` [RFC v1 020/256] cl8k: add bus/pci/irq.h viktor.barna
2021-06-17 15:58 ` [RFC v1 021/256] cl8k: add bus/pci/msg_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 022/256] cl8k: add bus/pci/msg_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 023/256] cl8k: add bus/pci/pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 024/256] cl8k: add bus/pci/rx_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 025/256] cl8k: add bus/pci/rx_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 026/256] cl8k: add bus/pci/tx_pci.c viktor.barna
2021-06-17 15:58 ` [RFC v1 027/256] cl8k: add bus/pci/tx_pci.h viktor.barna
2021-06-17 15:58 ` [RFC v1 028/256] cl8k: add calib.c viktor.barna
2021-06-17 15:58 ` [RFC v1 029/256] cl8k: add calib.h viktor.barna
2021-06-17 15:58 ` [RFC v1 030/256] cl8k: add cap.c viktor.barna
2021-06-17 15:58 ` [RFC v1 031/256] cl8k: add cap.h viktor.barna
2021-06-17 15:58 ` [RFC v1 032/256] cl8k: add cca.c viktor.barna
2021-06-17 15:58 ` [RFC v1 033/256] cl8k: add cca.h viktor.barna
2021-06-17 15:58 ` [RFC v1 034/256] cl8k: add cecli.c viktor.barna
2021-06-17 15:58 ` [RFC v1 035/256] cl8k: add cecli.h viktor.barna
2021-06-17 15:58 ` [RFC v1 036/256] cl8k: add chandef.c viktor.barna
2021-06-17 15:58 ` [RFC v1 037/256] cl8k: add chandef.h viktor.barna
2021-06-17 15:58 ` [RFC v1 038/256] cl8k: add channel.c viktor.barna
2021-06-17 15:58 ` [RFC v1 039/256] cl8k: add channel.h viktor.barna
2021-06-17 15:58 ` [RFC v1 040/256] cl8k: add chan_info.c viktor.barna
2021-06-17 15:58 ` [RFC v1 041/256] cl8k: add chan_info.h viktor.barna
2021-06-17 15:58 ` [RFC v1 042/256] cl8k: add chip.c viktor.barna
2021-06-17 15:58 ` [RFC v1 043/256] cl8k: add chip.h viktor.barna
2021-06-17 15:58 ` [RFC v1 044/256] cl8k: add chip_config.c viktor.barna
2021-06-17 15:58 ` [RFC v1 045/256] cl8k: add chip_config.h viktor.barna
2021-06-17 15:58 ` [RFC v1 046/256] cl8k: add config.c viktor.barna
2021-06-17 15:58 ` [RFC v1 047/256] cl8k: add config.h viktor.barna
2021-06-17 15:58 ` [RFC v1 048/256] cl8k: add coredump.c viktor.barna
2021-06-17 15:58 ` [RFC v1 049/256] cl8k: add coredump.h viktor.barna
2021-06-17 15:58 ` [RFC v1 050/256] cl8k: add data_rates.c viktor.barna
2021-06-17 15:58 ` [RFC v1 051/256] cl8k: add data_rates.h viktor.barna
2021-06-17 15:58 ` [RFC v1 052/256] cl8k: add dbgfile.c viktor.barna
2021-06-17 15:59 ` [RFC v1 053/256] cl8k: add dbgfile.h viktor.barna
2021-06-17 15:59 ` [RFC v1 054/256] cl8k: add debug.h viktor.barna
2021-06-17 15:59 ` [RFC v1 055/256] cl8k: add debugfs.c viktor.barna
2021-06-17 15:59 ` [RFC v1 056/256] cl8k: add debugfs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 057/256] cl8k: add debugfs_defs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 058/256] cl8k: add def.h viktor.barna
2021-06-17 15:59 ` [RFC v1 059/256] cl8k: add dfs/dfs.c viktor.barna
2021-06-17 15:59 ` [RFC v1 060/256] cl8k: add dfs/dfs.h viktor.barna
2021-06-17 15:59 ` [RFC v1 061/256] cl8k: add dfs/dfs_db.h viktor.barna
2021-06-17 15:59 ` [RFC v1 062/256] cl8k: add dfs/radar.c viktor.barna
2021-06-17 15:59 ` [RFC v1 063/256] cl8k: add dfs/radar.h viktor.barna
2021-06-17 15:59 ` [RFC v1 064/256] cl8k: add drv_ops.h viktor.barna
2021-06-17 15:59 ` [RFC v1 065/256] cl8k: add dsp.c viktor.barna
2021-06-17 15:59 ` [RFC v1 066/256] cl8k: add dsp.h viktor.barna
2021-06-17 15:59 ` [RFC v1 067/256] cl8k: add e2p.c viktor.barna
2021-06-17 15:59 ` [RFC v1 068/256] cl8k: add e2p.h viktor.barna
2021-06-17 15:59 ` [RFC v1 069/256] cl8k: add edca.c viktor.barna
2021-06-17 15:59 ` [RFC v1 070/256] cl8k: add edca.h viktor.barna
2021-06-17 15:59 ` [RFC v1 071/256] cl8k: add ela.c viktor.barna
2021-06-17 15:59 ` [RFC v1 072/256] cl8k: add ela.h viktor.barna
2021-06-17 15:59 ` [RFC v1 073/256] cl8k: add enhanced_tim.c viktor.barna
2021-06-17 15:59 ` [RFC v1 074/256] cl8k: add enhanced_tim.h viktor.barna
2021-06-17 15:59 ` [RFC v1 075/256] cl8k: add env_det.c viktor.barna
2021-06-17 15:59 ` [RFC v1 076/256] cl8k: add env_det.h viktor.barna
2021-06-17 15:59 ` [RFC v1 077/256] cl8k: add ext/dyn_bcast_rate.c viktor.barna
2021-06-17 15:59 ` [RFC v1 078/256] cl8k: add ext/dyn_bcast_rate.h viktor.barna
2021-06-17 15:59 ` [RFC v1 079/256] cl8k: add ext/dyn_mcast_rate.c viktor.barna
2021-06-17 15:59 ` [RFC v1 080/256] cl8k: add ext/dyn_mcast_rate.h viktor.barna
2021-06-17 15:59 ` [RFC v1 081/256] cl8k: add ext/vlan_dscp.c viktor.barna
2021-06-17 15:59 ` [RFC v1 082/256] cl8k: add ext/vlan_dscp.h viktor.barna
2021-06-17 15:59 ` [RFC v1 083/256] cl8k: add fem.c viktor.barna
2021-06-17 15:59 ` [RFC v1 084/256] cl8k: add fem.h viktor.barna
2021-06-17 15:59 ` [RFC v1 085/256] cl8k: add fem_common.h viktor.barna
2021-06-17 15:59 ` [RFC v1 086/256] cl8k: add fw/fw_dbg.c viktor.barna
2021-06-17 15:59 ` [RFC v1 087/256] cl8k: add fw/fw_dbg.h viktor.barna
2021-06-17 15:59 ` [RFC v1 088/256] cl8k: add fw/fw_file.c viktor.barna
2021-06-17 15:59 ` [RFC v1 089/256] cl8k: add fw/fw_file.h viktor.barna
2021-06-17 15:59 ` [RFC v1 090/256] cl8k: add fw/fw_msg.c viktor.barna
2021-06-17 15:59 ` [RFC v1 091/256] cl8k: add fw/fw_msg.h viktor.barna
2021-06-17 15:59 ` [RFC v1 092/256] cl8k: add fw/msg_cfm.c viktor.barna
2021-06-17 15:59 ` [RFC v1 093/256] cl8k: add fw/msg_cfm.h viktor.barna
2021-06-17 15:59 ` [RFC v1 094/256] cl8k: add fw/msg_rx.c viktor.barna
2021-06-17 15:59 ` [RFC v1 095/256] cl8k: add fw/msg_rx.h viktor.barna
2021-06-17 15:59 ` [RFC v1 096/256] cl8k: add fw/msg_tx.c viktor.barna
2021-06-17 15:59 ` [RFC v1 097/256] cl8k: add fw/msg_tx.h viktor.barna
2021-06-17 15:59 ` [RFC v1 098/256] cl8k: add hw.c viktor.barna
2021-06-17 15:59 ` [RFC v1 099/256] cl8k: add hw.h viktor.barna
2021-06-17 15:59 ` [RFC v1 100/256] cl8k: add hw_assert.c viktor.barna
2021-06-17 15:59 ` [RFC v1 101/256] cl8k: add hw_assert.h viktor.barna
2021-06-17 15:59 ` [RFC v1 102/256] cl8k: add ipc_shared.h viktor.barna
2021-06-17 15:59 ` [RFC v1 103/256] cl8k: add key.c viktor.barna
2021-06-17 15:59 ` [RFC v1 104/256] cl8k: add key.h viktor.barna
2021-06-17 15:59 ` [RFC v1 105/256] cl8k: add mac80211.c viktor.barna
2021-06-17 15:59 ` [RFC v1 106/256] cl8k: add mac80211.h viktor.barna
2021-06-17 15:59 ` [RFC v1 107/256] cl8k: add mac_addr.c viktor.barna
2021-06-17 15:59 ` [RFC v1 108/256] cl8k: add mac_addr.h viktor.barna
2021-06-17 15:59 ` [RFC v1 109/256] cl8k: add main.c viktor.barna
2021-06-17 15:59 ` [RFC v1 110/256] cl8k: add main.h viktor.barna
2021-06-17 15:59 ` [RFC v1 111/256] cl8k: add maintenance.c viktor.barna
2021-06-17 15:59 ` [RFC v1 112/256] cl8k: add maintenance.h viktor.barna
2021-06-17 16:00 ` [RFC v1 113/256] cl8k: add mib.c viktor.barna
2021-06-17 16:00 ` [RFC v1 114/256] cl8k: add mib.h viktor.barna
2021-06-17 16:00 ` [RFC v1 115/256] cl8k: add motion_sense.c viktor.barna
2021-06-17 16:00 ` [RFC v1 116/256] cl8k: add motion_sense.h viktor.barna
2021-06-17 16:00 ` [RFC v1 117/256] cl8k: add netlink.c viktor.barna
2021-06-17 16:00 ` [RFC v1 118/256] cl8k: add netlink.h viktor.barna
2021-06-17 16:00 ` [RFC v1 119/256] cl8k: add noise.c viktor.barna
2021-06-17 16:00 ` [RFC v1 120/256] cl8k: add noise.h viktor.barna
2021-06-17 16:00 ` [RFC v1 121/256] cl8k: add omi.c viktor.barna
2021-06-17 16:00 ` [RFC v1 122/256] cl8k: add omi.h viktor.barna
2021-06-17 16:00 ` [RFC v1 123/256] cl8k: add ops.c viktor.barna
2021-06-17 16:00 ` [RFC v1 124/256] cl8k: add ops.h viktor.barna
2021-06-17 16:00 ` [RFC v1 125/256] cl8k: add phy/phy.c viktor.barna
2021-06-17 16:00 ` [RFC v1 126/256] cl8k: add phy/phy.h viktor.barna
2021-06-17 16:00 ` [RFC v1 127/256] cl8k: add phy/phy_athos_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 128/256] cl8k: add phy/phy_athos_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 129/256] cl8k: add phy/phy_common_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 130/256] cl8k: add phy/phy_common_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 131/256] cl8k: add phy/phy_olympus_lut.c viktor.barna
2021-06-17 16:00 ` [RFC v1 132/256] cl8k: add phy/phy_olympus_lut.h viktor.barna
2021-06-17 16:00 ` [RFC v1 133/256] cl8k: add power.c viktor.barna
2021-06-17 16:00 ` [RFC v1 134/256] cl8k: add power.h viktor.barna
2021-06-17 16:00 ` [RFC v1 135/256] cl8k: add power_cli.c viktor.barna
2021-06-17 16:00 ` [RFC v1 136/256] cl8k: add power_cli.h viktor.barna
2021-06-17 16:00 ` [RFC v1 137/256] cl8k: add power_table.c viktor.barna
2021-06-17 16:00 ` [RFC v1 138/256] cl8k: add power_table.h viktor.barna
2021-06-17 16:00 ` [RFC v1 139/256] cl8k: add prot_mode.c viktor.barna
2021-06-17 16:00 ` [RFC v1 140/256] cl8k: add prot_mode.h viktor.barna
2021-06-17 16:00 ` [RFC v1 141/256] cl8k: add radio.c viktor.barna
2021-06-17 16:00 ` [RFC v1 142/256] cl8k: add radio.h viktor.barna
2021-06-17 16:00 ` [RFC v1 143/256] cl8k: add rate_ctrl.c viktor.barna
2021-06-17 16:00 ` [RFC v1 144/256] cl8k: add rate_ctrl.h viktor.barna
2021-06-17 16:00 ` [RFC v1 145/256] cl8k: add recovery.c viktor.barna
2021-06-17 16:00 ` [RFC v1 146/256] cl8k: add recovery.h viktor.barna
2021-06-17 16:00 ` [RFC v1 147/256] cl8k: add reg/ceva.h viktor.barna
2021-06-17 16:00 ` [RFC v1 148/256] cl8k: add reg/reg_access.h viktor.barna
2021-06-17 16:00 ` [RFC v1 149/256] cl8k: add reg/reg_cli.c viktor.barna
2021-06-17 16:00 ` [RFC v1 150/256] cl8k: add reg/reg_cli.h viktor.barna
2021-06-17 16:00 ` [RFC v1 151/256] cl8k: add reg/reg_cmu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 152/256] cl8k: add reg/reg_fem.h viktor.barna
2021-06-17 16:00 ` [RFC v1 153/256] cl8k: add reg/reg_io_ctrl.h viktor.barna
2021-06-17 16:00 ` [RFC v1 154/256] cl8k: add reg/reg_ipc.h viktor.barna
2021-06-17 16:00 ` [RFC v1 155/256] cl8k: add reg/reg_lcu_common.h viktor.barna
2021-06-17 16:00 ` [RFC v1 156/256] cl8k: add reg/reg_lcu_phy.h viktor.barna
2021-06-17 16:00 ` [RFC v1 157/256] cl8k: add reg/reg_macdsp_api.h viktor.barna
2021-06-17 16:00 ` [RFC v1 158/256] cl8k: add reg/reg_macsys_gcu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 159/256] cl8k: add reg/reg_mac_hw.h viktor.barna
2021-06-17 16:00 ` [RFC v1 160/256] cl8k: add reg/reg_mac_hw_mu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 161/256] cl8k: add reg/reg_modem_gcu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 162/256] cl8k: add reg/reg_otp_pvt.h viktor.barna
2021-06-17 16:00 ` [RFC v1 163/256] cl8k: add reg/reg_ricu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 164/256] cl8k: add reg/reg_riu.h viktor.barna
2021-06-17 16:00 ` [RFC v1 165/256] cl8k: add reg/reg_riu_rc.h viktor.barna
2021-06-17 16:00 ` [RFC v1 166/256] cl8k: add rf_boot.c viktor.barna
2021-06-17 16:00 ` [RFC v1 167/256] cl8k: add rf_boot.h viktor.barna
2021-06-17 16:00 ` [RFC v1 168/256] cl8k: add rsrc_mgmt.c viktor.barna
2021-06-17 16:00 ` [RFC v1 169/256] cl8k: add rsrc_mgmt.h viktor.barna
2021-06-17 16:00 ` [RFC v1 170/256] cl8k: add rssi.c viktor.barna
2021-06-17 16:00 ` [RFC v1 171/256] cl8k: add rssi.h viktor.barna
2021-06-17 16:00 ` [RFC v1 172/256] cl8k: add rx/rx.c viktor.barna
2021-06-17 16:01 ` [RFC v1 173/256] cl8k: add rx/rx.h viktor.barna
2021-06-17 16:01 ` [RFC v1 174/256] cl8k: add rx/rx_amsdu.c viktor.barna
2021-06-17 16:01 ` [RFC v1 175/256] cl8k: add rx/rx_amsdu.h viktor.barna
2021-06-17 16:01 ` [RFC v1 176/256] cl8k: add rx/rx_filter.c viktor.barna
2021-06-17 16:01 ` [RFC v1 177/256] cl8k: add rx/rx_filter.h viktor.barna
2021-06-17 16:01 ` [RFC v1 178/256] cl8k: add rx/rx_reorder.c viktor.barna
2021-06-17 16:01 ` [RFC v1 179/256] cl8k: add rx/rx_reorder.h viktor.barna
2021-06-17 16:01 ` viktor.barna [this message]
2021-06-17 16:01 ` [RFC v1 181/256] cl8k: add sounding.h viktor.barna
2021-06-17 16:01 ` [RFC v1 182/256] cl8k: add sta.c viktor.barna
2021-06-17 16:01 ` [RFC v1 183/256] cl8k: add sta.h viktor.barna
2021-06-17 16:01 ` [RFC v1 184/256] cl8k: add stats.c viktor.barna
2021-06-17 16:01 ` [RFC v1 185/256] cl8k: add stats.h viktor.barna
2021-06-17 16:01 ` [RFC v1 186/256] cl8k: add tcv_config.c viktor.barna
2021-06-17 16:01 ` [RFC v1 187/256] cl8k: add tcv_config.h viktor.barna
2021-06-17 16:01 ` [RFC v1 188/256] cl8k: add temperature.c viktor.barna
2021-06-17 16:01 ` [RFC v1 189/256] cl8k: add temperature.h viktor.barna
2021-06-17 16:01 ` [RFC v1 190/256] cl8k: add trace.c viktor.barna
2021-06-17 16:01 ` [RFC v1 191/256] cl8k: add trace.h viktor.barna
2021-06-17 16:01 ` [RFC v1 192/256] cl8k: add traffic.c viktor.barna
2021-06-17 16:01 ` [RFC v1 193/256] cl8k: add traffic.h viktor.barna
2021-06-17 16:01 ` [RFC v1 194/256] cl8k: add twt.c viktor.barna
2021-06-17 16:01 ` [RFC v1 195/256] cl8k: add twt.h viktor.barna
2021-06-17 16:01 ` [RFC v1 196/256] cl8k: add twt_cli.c viktor.barna
2021-06-17 16:01 ` [RFC v1 197/256] cl8k: add twt_cli.h viktor.barna
2021-06-17 16:01 ` [RFC v1 198/256] cl8k: add twt_frame.c viktor.barna
2021-06-17 16:01 ` [RFC v1 199/256] cl8k: add twt_frame.h viktor.barna
2021-06-17 16:01 ` [RFC v1 200/256] cl8k: add tx/agg_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 201/256] cl8k: add tx/agg_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 202/256] cl8k: add tx/agg_tx_report.c viktor.barna
2021-06-17 16:01 ` [RFC v1 203/256] cl8k: add tx/agg_tx_report.h viktor.barna
2021-06-17 16:01 ` [RFC v1 204/256] cl8k: add tx/baw.c viktor.barna
2021-06-17 16:01 ` [RFC v1 205/256] cl8k: add tx/baw.h viktor.barna
2021-06-17 16:01 ` [RFC v1 206/256] cl8k: add tx/bcmc_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 207/256] cl8k: add tx/bcmc_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 208/256] cl8k: add tx/single_cfm.c viktor.barna
2021-06-17 16:01 ` [RFC v1 209/256] cl8k: add tx/single_cfm.h viktor.barna
2021-06-17 16:01 ` [RFC v1 210/256] cl8k: add tx/sw_txhdr.c viktor.barna
2021-06-17 16:01 ` [RFC v1 211/256] cl8k: add tx/sw_txhdr.h viktor.barna
2021-06-17 16:01 ` [RFC v1 212/256] cl8k: add tx/tx.c viktor.barna
2021-06-17 16:01 ` [RFC v1 213/256] cl8k: add tx/tx.h viktor.barna
2021-06-17 16:01 ` [RFC v1 214/256] cl8k: add tx/tx_amsdu.c viktor.barna
2021-06-17 16:01 ` [RFC v1 215/256] cl8k: add tx/tx_amsdu.h viktor.barna
2021-06-17 16:01 ` [RFC v1 216/256] cl8k: add tx/tx_inject.c viktor.barna
2021-06-17 16:01 ` [RFC v1 217/256] cl8k: add tx/tx_inject.h viktor.barna
2021-06-17 16:01 ` [RFC v1 218/256] cl8k: add tx/tx_queue.c viktor.barna
2021-06-17 16:01 ` [RFC v1 219/256] cl8k: add tx/tx_queue.h viktor.barna
2021-06-17 16:01 ` [RFC v1 220/256] cl8k: add utils/file.c viktor.barna
2021-06-17 16:01 ` [RFC v1 221/256] cl8k: add utils/file.h viktor.barna
2021-06-17 16:01 ` [RFC v1 222/256] cl8k: add utils/ip.c viktor.barna
2021-06-17 16:01 ` [RFC v1 223/256] cl8k: add utils/ip.h viktor.barna
2021-06-17 16:01 ` [RFC v1 224/256] cl8k: add utils/math.h viktor.barna
2021-06-17 16:01 ` [RFC v1 225/256] cl8k: add utils/string.c viktor.barna
2021-06-17 16:01 ` [RFC v1 226/256] cl8k: add utils/string.h viktor.barna
2021-06-17 16:01 ` [RFC v1 227/256] cl8k: add utils/timer.c viktor.barna
2021-06-17 16:01 ` [RFC v1 228/256] cl8k: add utils/timer.h viktor.barna
2021-06-17 16:01 ` [RFC v1 229/256] cl8k: add utils/utils.c viktor.barna
2021-06-17 16:01 ` [RFC v1 230/256] cl8k: add utils/utils.h viktor.barna
2021-06-17 16:01 ` [RFC v1 231/256] cl8k: add vendor_cmd.c viktor.barna
2021-06-17 16:01 ` [RFC v1 232/256] cl8k: add vendor_cmd.h viktor.barna
2021-06-17 16:02 ` [RFC v1 233/256] cl8k: add version.c viktor.barna
2021-06-17 16:02 ` [RFC v1 234/256] cl8k: add version.h viktor.barna
2021-06-17 16:02 ` [RFC v1 235/256] cl8k: add vif.c viktor.barna
2021-06-17 16:02 ` [RFC v1 236/256] cl8k: add vif.h viktor.barna
2021-06-17 16:02 ` [RFC v1 237/256] cl8k: add vns.c viktor.barna
2021-06-17 16:02 ` [RFC v1 238/256] cl8k: add vns.h viktor.barna
2021-06-17 16:02 ` [RFC v1 239/256] cl8k: add wrs/wrs.c viktor.barna
2021-06-17 16:02 ` [RFC v1 240/256] cl8k: add wrs/wrs.h viktor.barna
2021-06-17 16:02 ` [RFC v1 241/256] cl8k: add wrs/wrs_ap.c viktor.barna
2021-06-17 16:02 ` [RFC v1 242/256] cl8k: add wrs/wrs_ap.h viktor.barna
2021-06-17 16:02 ` [RFC v1 243/256] cl8k: add wrs/wrs_api.c viktor.barna
2021-06-17 16:02 ` [RFC v1 244/256] cl8k: add wrs/wrs_api.h viktor.barna
2021-06-17 16:02 ` [RFC v1 245/256] cl8k: add wrs/wrs_cli.c viktor.barna
2021-06-17 16:02 ` [RFC v1 246/256] cl8k: add wrs/wrs_cli.h viktor.barna
2021-06-17 16:02 ` [RFC v1 247/256] cl8k: add wrs/wrs_db.h viktor.barna
2021-06-17 16:02 ` [RFC v1 248/256] cl8k: add wrs/wrs_rssi.c viktor.barna
2021-06-17 16:02 ` [RFC v1 249/256] cl8k: add wrs/wrs_rssi.h viktor.barna
2021-06-17 16:02 ` [RFC v1 250/256] cl8k: add wrs/wrs_sta.c viktor.barna
2021-06-17 16:02 ` [RFC v1 251/256] cl8k: add wrs/wrs_sta.h viktor.barna
2021-06-17 16:02 ` [RFC v1 252/256] cl8k: add wrs/wrs_stats.c viktor.barna
2021-06-17 16:02 ` [RFC v1 253/256] cl8k: add wrs/wrs_stats.h viktor.barna
2021-06-17 16:02 ` [RFC v1 254/256] cl8k: add wrs/wrs_tables.c viktor.barna
2021-06-17 16:02 ` [RFC v1 255/256] cl8k: add wrs/wrs_tables.h viktor.barna
2021-06-17 16:02 ` [RFC v1 256/256] wireless: add Celeno vendor viktor.barna
2021-06-17 17:23 ` [RFC v1 000/256] wireless: cl8k driver for Celeno IEEE 802.11ax devices Johannes Berg
2022-05-22 17:51   ` viktor.barna
2021-06-19  6:39 ` Kalle Valo
2022-05-13 21:11   ` viktor.barna
2022-05-14  4:25     ` Kalle Valo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210617160223.160998-181-viktor.barna@celeno.com \
    --to=viktor.barna@celeno.com \
    --cc=aviad.brikman@celeno.com \
    --cc=davem@davemloft.net \
    --cc=eliav.farber@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kvalo@codeaurora.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=oleksandr.savchenko@celeno.com \
    --cc=shay.bar@celeno.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.