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 028/256] cl8k: add calib.c
Date: Thu, 17 Jun 2021 15:58:35 +0000	[thread overview]
Message-ID: <20210617160223.160998-29-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/calib.c | 1682 ++++++++++++++++++++++
 1 file changed, 1682 insertions(+)
 create mode 100644 drivers/net/wireless/celeno/cl8k/calib.c

diff --git a/drivers/net/wireless/celeno/cl8k/calib.c b/drivers/net/wireless/celeno/cl8k/calib.c
new file mode 100644
index 000000000000..8861964e3aff
--- /dev/null
+++ b/drivers/net/wireless/celeno/cl8k/calib.c
@@ -0,0 +1,1682 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+
+#include "calib.h"
+#include "temperature.h"
+#include "utils/utils.h"
+#include "chip.h"
+#include "chandef.h"
+#include "fw/msg_cfm.h"
+#include "fw/msg_tx.h"
+#include "band.h"
+#include "e2p.h"
+#include "channel.h"
+#include "power.h"
+#include "afe.h"
+#include "radio.h"
+
+/*
+ * CL80x0: TCV0 - 5g, TCV1 - 24g
+ * ==============================================
+ * 50  48  46  44  42  40  38  36  --> Start 5g
+ * 100 64  62  60  58  56  54  52
+ * 116 114 112 110 108 106 104 102
+ * 134 132 128 126 124 122 120 118
+ * 153 151 149 144 142 140 138 136
+ * 3   2   1   165 161 159 157 155  --> Start 24g
+ * 11  10  9   8   7   6   5   4
+ *                     14  13  12
+ */
+
+/*
+ * CL80x6: TCV0 - 6g, TCV1 - 5g
+ * ==============================================
+ * 25  21  17  13  9   5   2   1   --> Start 6g
+ * 57  53  49  45  41  37  33  29
+ * 89  85  81  77  73  69  65  61
+ * 121 117 113 109 105 101 97  93
+ * 153 147 143 139 135 131 127 123
+ * 185 181 177 173 169 165 161 157
+ * 217 213 209 205 201 197 193 189
+ * 42  40  38  36  233 229 225 221 --> Start 5g
+ * 58  56  54  52  50  48  46  44
+ * 108 106 104 102 100 64  62  60
+ * 124 122 120 118 116 114 112 110
+ * 142 140 138 136 134 132 128 126
+ * 161 159 157 155 153 151 149 144
+ *                             165
+ */
+
+#define BITMAP_80X0_START_TCV0  0
+#define BITMAP_80X0_MAX_TCV0    NUM_CHANNELS_5G
+
+#define BITMAP_80X0_START_TCV1 NUM_CHANNELS_5G
+#define BITMAP_80X0_MAX_TCV1   (NUM_CHANNELS_5G + NUM_CHANNELS_24G)
+
+#define BITMAP_80X6_START_TCV0  0
+#define BITMAP_80X6_MAX_TCV0    NUM_CHANNELS_6G
+
+#define BITMAP_80X6_START_TCV1  NUM_CHANNELS_6G
+#define BITMAP_80X6_MAX_TCV1    (NUM_CHANNELS_6G + NUM_CHANNELS_5G)
+
+#define INVALID_ADDR 0xffff
+
+#define S12_S_BIT (0x00000800)
+#define U12_BIT_MASK (0x00000FFF)
+#define CAST_S12_TO_S32(i) ((~(i) & S12_S_BIT) ? (i) : ((i) | ~U12_BIT_MASK))
+
+static const u8 calib_channels_24g[CALIB_CHAN_24G_MAX] = {
+       1, 6, 11
+};
+
+static const u8 calib_channels_5g[CALIB_CHAN_5G_MAX] = {
+       36, 52, 100, 116, 132, 149
+};
+
+static const u8 calib_channels_6g[CALIB_CHAN_6G_MAX] = {
+       1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177, 193, 209, 225
+};
+
+static u8 tone_vector_arr[CHNL_BW_MAX][IQ_NUM_TONES_REQ] = {
+       {6, 10, 14, 18, 22, 24, 26, 27},
+       {10, 18, 26, 34, 41, 48, 53, 58},
+       {18, 34, 50, 66, 82, 98, 110, 122},
+       {18, 34, 66, 98, 130, 164, 224, 250}
+};
+
+static u8 get_bitmap_start_tcv1(struct cl_chip *chip)
+{
+       if (cl_chip_is_6g(chip))
+               return BITMAP_80X6_START_TCV1;
+       else
+               return BITMAP_80X0_START_TCV1;
+}
+
+static void get_bitmap_boundaries(struct cl_chip *chip, u8 tcv_idx, u8 *start, u8 *max)
+{
+       if (cl_chip_is_6g(chip)) {
+               if (tcv_idx == TCV0) {
+                       *start = BITMAP_80X6_START_TCV0;
+                       *max = BITMAP_80X6_MAX_TCV0;
+               } else {
+                       *start = BITMAP_80X6_START_TCV1;
+                       *max = BITMAP_80X6_MAX_TCV1;
+               }
+       } else {
+               if (tcv_idx == TCV0) {
+                       *start = BITMAP_80X0_START_TCV0;
+                       *max = BITMAP_80X0_MAX_TCV0;
+               } else {
+                       *start = BITMAP_80X0_START_TCV1;
+                       *max = BITMAP_80X0_MAX_TCV1;
+               }
+       }
+}
+
+static u8 idx_to_arr_offset(u8 idx)
+{
+       /* Divide by 8 for array index */
+       return idx >> 3;
+}
+
+static u8 idx_to_bit_offset(u8 idx)
+{
+       /* Reminder is for bit index (assummed array of u8) */
+       return idx & 0x07;
+}
+
+static const u8 bits_cnt_table256[] = {
+       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+static u8 count_bits(const u8 *bitmap)
+{
+       /*
+        * Count bits in a given u8 array ASSUMED ARRAY SIZE IS BIT_MAP_SIZE
+        * bitmap - pointer to u8 array (bitmap)
+        */
+       u8 i = 0, cnt = 0;
+
+       for (i = 0; i < BIT_MAP_SIZE; i++)
+               cnt += bits_cnt_table256[bitmap[i]];
+
+       return cnt;
+}
+
+static bool is_vector_unset(const u8 *bitmap)
+{
+       /* Check bitmap is unset i.e. all values are CURR_BMP_UNSET */
+       u8 empty_bitmap[BIT_MAP_SIZE] = {0};
+
+       return !memcmp(bitmap, empty_bitmap, BIT_MAP_SIZE);
+}
+
+static bool bitmap_test_bit_idx(const u8 *bitmap, u8 idx)
+{
+       /* Check bit at a given index is set i.e. 1 */
+       u8 arr_idx = idx_to_arr_offset(idx), bit_idx = idx_to_bit_offset(idx);
+
+       if (arr_idx >= BIT_MAP_SIZE)
+               return false;
+
+       /* Convert non-zero to true and zero to false */
+       return !!(bitmap[arr_idx] & BIT(bit_idx));
+}
+
+static void bitmap_shift(u8 *bitmap, u8 shft)
+{
+       /* Shifts an array of byte of size len by shft number of bits to the left */
+       u8 bitmap_tmp[BIT_MAP_SIZE] = {0};
+       u8 msb_shifts = shft % 8;
+       u8 lsb_shifts = 8 - msb_shifts;
+       u8 byte_shift = shft / 8;
+       u8 last_byte = BIT_MAP_SIZE - byte_shift - 1;
+       u8 msb_idx;
+       u8 i;
+
+       memcpy(bitmap_tmp, bitmap, BIT_MAP_SIZE);
+       memset(bitmap, 0, BIT_MAP_SIZE);
+
+       for (i = 0;  i < BIT_MAP_SIZE; i++) {
+               if (i <= last_byte) {
+                       msb_idx = i + byte_shift;
+                       bitmap[i] = bitmap_tmp[msb_idx] >> msb_shifts;
+                       if (i != last_byte)
+                               bitmap[i] |= bitmap_tmp[msb_idx + 1] << lsb_shifts;
+               }
+       }
+}
+
+static bool bitmap_set_bit_idx(struct cl_hw *cl_hw, u8 *bitmap, u8 idx)
+{
+       /* Set bit at a given index */
+       u8 arr_idx = idx_to_arr_offset(idx), bit_idx = idx_to_bit_offset(idx);
+
+       if (arr_idx >= BIT_MAP_SIZE) {
+               cl_dbg_err(cl_hw, "invalid arr_idx (%u)\n", arr_idx);
+               return false;
+       }
+
+       bitmap[arr_idx] |= BIT(bit_idx);
+       return true;
+}
+
+static bool bitmap_clear_bit_idx(struct cl_hw *cl_hw, u8 *bitmap, u8 idx)
+{
+       /* Clear bit at a given index */
+       u8 arr_idx = idx_to_arr_offset(idx), bit_idx = idx_to_bit_offset(idx);
+
+       if (arr_idx >= BIT_MAP_SIZE) {
+               cl_dbg_err(cl_hw, "invalid arr_idx (%u)\n", arr_idx);
+               return false;
+       }
+
+       bitmap[arr_idx] &= ~BIT(bit_idx);
+       return true;
+}
+
+static u16 bitmap_look_lsb_up(struct cl_hw *cl_hw, u8 *bitmap, u16 idx)
+{
+       /* Find closest ON(1) bit with index haigher than idx inside bitmap */
+       u16 curr_idx = idx;
+       u8 curr = 0;
+
+       while (++curr_idx < cl_channel_num(cl_hw)) {
+               curr = bitmap[idx_to_arr_offset(curr_idx)];
+               if (curr & (1ULL << idx_to_bit_offset(curr_idx)))
+                       return curr_idx;
+       }
+
+       /* No matching bit found - return original index */
+       return idx;
+}
+
+static u16 bitmap_look_msb_down(struct cl_hw *cl_hw, u8 *bitmap, u16 idx)
+{
+       /* Find closest ON(1) bit with index lower than idx inside bitmap */
+       u16 curr_idx = idx;
+       u8 curr = 0;
+
+       if (idx >= cl_channel_num(cl_hw)) {
+               cl_dbg_err(cl_hw, "Invalid channel index [%u]\n", idx);
+               return idx;
+       }
+
+       while (curr_idx-- != 0) {
+               curr = bitmap[idx_to_arr_offset(curr_idx)];
+               if (curr & (1ULL << idx_to_bit_offset(curr_idx)))
+                       return curr_idx;
+       }
+
+       /* No matching bit found - return original index */
+       return idx;
+}
+
+static u8 address_offset_tcv1(struct cl_hw *cl_hw)
+{
+       /* Calculate eeprom calibration data offset for tcv1 */
+       struct cl_chip *chip = cl_hw->chip;
+       u8 i, cnt = 0;
+       u8 bitmap[BIT_MAP_SIZE] = {0};
+
+       if (cl_e2p_read(chip, bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return 0;
+
+       for (i = 0; i < get_bitmap_start_tcv1(chip); i++)
+               cnt += bitmap_test_bit_idx(bitmap, i);
+
+       return cnt;
+}
+
+static int point_idx_to_address(struct cl_hw *cl_hw, u8 *bitmap, struct point *pt)
+{
+       /* Calculate eeprom address for a given idx and phy (initiated point) */
+       u8 i, cnt = 0;
+
+       pt->addr = INVALID_ADDR;
+
+       if (!bitmap_test_bit_idx(bitmap, pt->idx))
+               return 0;
+
+       if (pt->phy >= MAX_ANTENNAS) {
+               cl_dbg_err(cl_hw, "Invalid phy number %u", pt->phy);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < pt->idx; i++)
+               cnt += bitmap_test_bit_idx(bitmap, i);
+
+       if (cl_hw_is_tcv1(cl_hw))
+               cnt += address_offset_tcv1(cl_hw);
+
+       pt->addr = ADDR_CALIB_PHY +
+               sizeof(struct eeprom_phy_calib) * (cnt * MAX_ANTENNAS + pt->phy);
+
+       return 0;
+}
+
+static bool linear_equation_signed(struct cl_hw *cl_hw, const u16 x, s8 *y,
+                                  const u16 x0, const s8 y0, const u16 x1, const s8 y1)
+{
+       /* Calculate y given to points (x0,y0) and (x1,y1) and x */
+       s32 numerator = (x - x0) * (y1 - y0);
+       s32 denominator = x1 - x0;
+
+       if (unlikely(!denominator)) {
+               cl_dbg_err(cl_hw, "zero denominator\n");
+               return false;
+       }
+
+       *y = (s8)(y0 + DIV_ROUND_CLOSEST(numerator, denominator));
+
+       return true;
+}
+
+static bool calculate_calib(struct cl_hw *cl_hw, u8 *bitmap,
+                           struct point *p0, struct point *p1, struct point *p2)
+{
+       /* Main interpolation/extrapolation function */
+       bool calc_succsess = false;
+       u16 freq0, freq1, freq2;
+
+       if (unlikely(is_vector_unset(bitmap)))
+               return false;
+
+       p1->idx = bitmap_look_lsb_up(cl_hw, bitmap, p0->idx);
+       p2->idx = bitmap_look_msb_down(cl_hw, bitmap, p0->idx);
+
+       /* Invalid case */
+       if (p1->idx == p0->idx && p2->idx == p0->idx) {
+               cl_dbg_err(cl_hw, "Invalid index %u or bad bit map\n", p0->idx);
+               return false;
+       }
+
+       /* Extrapolation case */
+       if (p1->idx == p0->idx)
+               p1->idx = bitmap_look_msb_down(cl_hw, bitmap, p2->idx);
+       if (p2->idx == p0->idx)
+               p2->idx = bitmap_look_lsb_up(cl_hw, bitmap, p1->idx);
+
+       /* Address from index */
+       if (point_idx_to_address(cl_hw, bitmap, p1) || p1->addr == INVALID_ADDR) {
+               cl_dbg_err(cl_hw, "Point calculation failed\n");
+               return false;
+       }
+
+       if (point_idx_to_address(cl_hw, bitmap, p2) || p2->addr == INVALID_ADDR) {
+               cl_dbg_err(cl_hw, "Point calculation failed\n");
+               return false;
+       }
+
+       /* Read from eeprom */
+       if (cl_e2p_read(cl_hw->chip, (u8 *)&p1->calib, sizeof(struct eeprom_phy_calib), p1->addr))
+               return false;
+
+       /* No interpolation required */
+       if (p1->addr == p2->addr) {
+               p0->calib = p1->calib;
+               return true;
+       }
+
+       /* Interpolation or extrapolation is required - read from eeprom */
+       if (cl_e2p_read(cl_hw->chip, (u8 *)&p2->calib, sizeof(struct eeprom_phy_calib), p2->addr))
+               return false;
+
+       freq0 = cl_channel_idx_to_freq(cl_hw, p0->idx);
+       freq1 = cl_channel_idx_to_freq(cl_hw, p1->idx);
+       freq2 = cl_channel_idx_to_freq(cl_hw, p2->idx);
+
+       /* Interpolate/extrapolate target power */
+       calc_succsess = linear_equation_signed(cl_hw,
+                                              freq0, &p0->calib.pow,
+                                              freq1, p1->calib.pow,
+                                              freq2, p2->calib.pow);
+
+       /* Interpolate/extrapolate power offset */
+       calc_succsess = calc_succsess && linear_equation_signed(cl_hw,
+                                                               freq0, &p0->calib.offset,
+                                                               freq1, p1->calib.offset,
+                                                               freq2, p2->calib.offset);
+
+       /* Interpolate/extrapolate calibration temperature */
+       calc_succsess = calc_succsess && linear_equation_signed(cl_hw,
+                                                               freq0, &p0->calib.tmp,
+                                                               freq1, p1->calib.tmp,
+                                                               freq2, p2->calib.tmp);
+
+       if (unlikely(!calc_succsess)) {
+               cl_dbg_err(cl_hw,
+                          "Calc failed: freq0 %u idx0 %u, freq1 %u idx1 %u, freq2 %u idx2 %u\n",
+                          freq0, p0->idx, freq1, p1->idx, freq2, p2->idx);
+               return false;
+       }
+
+       return true;
+}
+
+static int read_validate_vector_bitmap(struct cl_hw *cl_hw, u8 *bitmap)
+{
+       struct cl_chip *chip = cl_hw->chip;
+
+       if (cl_e2p_read(chip, bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return -1;
+
+       /* Test if e2p was read succsefull since it is not ALL EMPTY */
+       if (is_vector_unset(bitmap)) {
+               cl_dbg_err(cl_hw, "Vector not ready\n");
+               return -EPERM;
+       }
+
+       if (cl_hw_is_tcv1(cl_hw)) {
+               u8 bitmap_start = get_bitmap_start_tcv1(chip);
+
+               bitmap_shift(bitmap, bitmap_start);
+       }
+
+       return 0;
+}
+
+static int e2p_prepare(struct cl_hw *cl_hw, struct point *data, u8 *bitmap)
+{
+       int ret = read_validate_vector_bitmap(cl_hw, bitmap);
+
+       if (ret) {
+               cl_dbg_err(cl_hw, "read_validate_vector_bitmap failed\n");
+               return ret;
+       }
+
+       data->idx = cl_channel_to_index(cl_hw, data->chan);
+
+       return point_idx_to_address(cl_hw, bitmap, data);
+}
+
+static int read_or_interpolate_point(struct cl_hw *cl_hw, u8 *bitmap, struct point *p0)
+{
+       struct point p1 = {.phy = p0->phy};
+       struct point p2 = {.phy = p0->phy};
+       struct point tmp_pt = *p0;
+
+       /* Invalid address = no physical address was allocated to this channel */
+       if (tmp_pt.addr != INVALID_ADDR) {
+               if (cl_e2p_read(cl_hw->chip, (u8 *)&tmp_pt.calib,
+                               sizeof(struct eeprom_phy_calib), tmp_pt.addr))
+                       return -1;
+       } else {
+               /* Interpolate */
+               if (!calculate_calib(cl_hw, bitmap, &tmp_pt, &p1, &p2)) {
+                       cl_dbg_err(cl_hw, "Interpolation Error\n");
+                       return -EFAULT;
+               }
+       }
+
+       if (tmp_pt.calib.pow == 0 && tmp_pt.calib.offset == 0 && tmp_pt.calib.tmp == 0) {
+               u16 freq = cl_channel_idx_to_freq(cl_hw, tmp_pt.idx);
+
+               cl_dbg_err(cl_hw, "Verify calibration point: addr %x, idx %u, freq %u, phy %u\n",
+                          tmp_pt.addr, tmp_pt.idx, freq, tmp_pt.phy);
+               /* *Uninitiated eeprom value */
+               return -EINVAL;
+       }
+
+       /* Now p0 will contain "Valid" calculations of calib" */
+       p0->calib = tmp_pt.calib;
+       return 0;
+}
+
+int cl_calib_get(struct wiphy *wiphy, struct wireless_dev *wdev,
+                            const void *data, int data_len)
+{
+       /* Kernel space callback for handling E2P_GET_CALIB vendor subcmd */
+       int ret;
+       struct point *p0;
+       u8 e2p_bitmap[BIT_MAP_SIZE] = {0};
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+
+       if (!data) {
+               cl_dbg_err(cl_hw, "data is null\n");
+               return -1;
+       }
+
+       p0 = (struct point *)data;
+
+       ret = e2p_prepare(cl_hw, p0, e2p_bitmap);
+       if (ret) {
+               cl_dbg_err(cl_hw, "Unable prepare e2p\n");
+               return ret;
+       }
+
+       ret = read_or_interpolate_point(cl_hw, e2p_bitmap, p0);
+       if (ret) {
+               cl_dbg_trace(cl_hw, "read_or_interpolate_point error\n");
+               return ret;
+       }
+
+       return cl_vendor_reply(cl_hw, &p0->calib, sizeof(p0->calib));
+}
+
+int cl_calib_set(struct wiphy *wiphy, struct wireless_dev *wdev,
+                            const void *data, int data_len)
+{
+       /* Kernel space callback for handling E2P_SET_CALIB vendor subcmd */
+       struct cl_hw *cl_hw = WIPHY_TO_CL_HW(wiphy);
+       struct point pt;
+       int ret;
+       u8 e2p_bitmap[BIT_MAP_SIZE] = {0};
+       u8 ch_idx = 0;
+
+       if (!data) {
+               cl_dbg_err(cl_hw, "data is null\n");
+               return -1;
+       }
+
+       pt = *(struct point *)data;
+
+       ret = e2p_prepare(cl_hw, &pt, e2p_bitmap);
+       if (ret) {
+               cl_dbg_err(cl_hw, "Unable prepare e2p\n");
+               return ret;
+       }
+
+       if (pt.addr == INVALID_ADDR) {
+               cl_dbg_err(cl_hw, "Invalid address - permission denied\n");
+               return -EPERM;
+       }
+
+       if (pt.calib.pow < POWER_MIN_DB || pt.calib.pow > POWER_MAX_DB) {
+               cl_dbg_err(cl_hw, "Invalid power (%d). Valid range (%d - %d)\n",
+                          pt.calib.pow, POWER_MIN_DB, POWER_MAX_DB);
+               return -1;
+       }
+
+       if (pt.calib.offset < POWER_OFFSET_MIN_Q2 || pt.calib.offset > POWER_OFFSET_MAX_Q2) {
+               cl_dbg_err(cl_hw, "Invalid power offset (%d). Valid range (%d - %d)\n",
+                          pt.calib.offset, POWER_OFFSET_MIN_Q2, POWER_OFFSET_MAX_Q2);
+               return -1;
+       }
+
+       if (!bitmap_test_bit_idx(e2p_bitmap, pt.idx)) {
+               cl_dbg_err(cl_hw, "No permition to write to this channel %u\n", pt.idx);
+               return -EACCES;
+       }
+
+       /*
+        * Temperature is an optional argument for "e2p set calib" command.
+        * If value is 0x7f then temperature argument was not set, and it
+        * should be set by the driver.
+        */
+       if (pt.calib.tmp == S8_MAX)
+               pt.calib.tmp = cl_temperature_read(cl_hw, TEMP_MODE_INTERNAL);
+
+       if (cl_e2p_write(cl_hw->chip, (u8 *)&pt.calib, sizeof(struct eeprom_phy_calib), pt.addr))
+               return -1;
+
+       ch_idx = cl_channel_to_index(cl_hw, pt.chan);
+
+       if (ch_idx < MAX_CHANNELS && pt.phy < MAX_ANTENNAS) {
+               cl_hw->tx_pow_info[ch_idx][pt.phy].power = pt.calib.pow;
+               cl_hw->tx_pow_info[ch_idx][pt.phy].offset = pt.calib.offset;
+               cl_hw->tx_pow_info[ch_idx][pt.phy].temperature = pt.calib.tmp;
+               cl_hw->set_calib = true;
+       }
+
+       return 0;
+}
+
+static void cl_calib_power_reset(struct cl_hw *cl_hw)
+{
+       u8 ch_idx;
+       u16 phy;
+       static const struct cl_tx_power_info default_info = {
+               .power       = UNCALIBRATED_POWER,
+               .offset      = UNCALIBRATED_POWER_OFFSET,
+               .temperature = UNCALIBRATED_TEMPERATURE
+       };
+
+       /* Initiate tx_pow_info struct to default values */
+       for (ch_idx = 0; ch_idx < cl_channel_num(cl_hw); ch_idx++)
+               for (phy = 0; phy < MAX_ANTENNAS; phy++)
+                       cl_hw->tx_pow_info[ch_idx][phy] = default_info;
+}
+
+#define PHY0_OFFSET_FIX_Q2 -8 /* -2db */
+#define PHY3_OFFSET_FIX_Q2 14 /* +3.5db */
+
+void cl_calib_power_read(struct cl_hw *cl_hw)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       int ret;
+       u8 bitmap[BIT_MAP_SIZE] = {0};
+       struct point curr_point = {0};
+       u8 *phy = &curr_point.phy;
+       u8 *ch_idx = &curr_point.idx;
+
+       /* Initiate tx_pow_info struct to default values */
+       cl_calib_power_reset(cl_hw);
+
+       /* Vector not initiated set table to default values */
+       if (unlikely(read_validate_vector_bitmap(cl_hw, bitmap))) {
+               cl_dbg_trace(cl_hw, "initiate to default values\n");
+               return;
+       }
+
+       /* Perform only on calibrated boards - read_validate_vector_bitmap succeeded (0) */
+       for (*ch_idx = 0; *ch_idx < cl_channel_num(cl_hw); (*ch_idx)++)
+               for (*phy = 0; *phy < cl_hw->num_antennas; (*phy)++) {
+                       ret = point_idx_to_address(cl_hw, bitmap, &curr_point);
+
+                       if (ret) {
+                               /* *don't overwrite default values */
+                               cl_dbg_err(cl_hw, "point idx to address failed\n");
+                               continue;
+                       }
+
+                       ret = read_or_interpolate_point(cl_hw, bitmap, &curr_point);
+                       /* Unable to calculate new value ==> DON'T overwrite default values */
+                       if (unlikely(ret))
+                               continue;
+
+                       /*
+                        * Work around:
+                        * Add 3.5dB offset to PHY3 if EEPROM version is 0.
+                        * Decrease 2dB offset to all PHYs if EEPROM version is 1.
+                        */
+                       if (!cl_chip_is_6g(chip)) {
+                               u8 eeprom_version = chip->eeprom_cache->general.version;
+
+                               if (cl_band_is_5g(cl_hw) && eeprom_version == 0 && *phy == 3)
+                                       curr_point.calib.offset += PHY3_OFFSET_FIX_Q2;
+                               else if (cl_band_is_24g(cl_hw) && eeprom_version == 1)
+                                       curr_point.calib.offset += PHY0_OFFSET_FIX_Q2;
+                       }
+
+                       cl_hw->tx_pow_info[*ch_idx][*phy].power = curr_point.calib.pow;
+                       cl_hw->tx_pow_info[*ch_idx][*phy].offset = curr_point.calib.offset;
+                       cl_hw->tx_pow_info[*ch_idx][*phy].temperature = curr_point.calib.tmp;
+               }
+
+       cl_dbg_trace(cl_hw, "Created tx_pow_info\n");
+}
+
+void cl_calib_power_offset_fill(struct cl_hw *cl_hw, u8 channel,
+                                     u8 bw, u8 offset[MAX_ANTENNAS])
+{
+       u8 i;
+       u8 chan_idx = cl_channel_to_index(cl_hw, channel);
+       s8 signed_offset;
+       struct cl_ate_db *ate_db = &cl_hw->ate_db;
+
+       if (chan_idx == INVALID_CHAN_IDX)
+               return;
+
+       /* In ATE mode, use values of 'ATE power_offset' if it was set */
+       if (ate_db->active && ate_db->tx_power_offset[0] != S8_MAX) {
+               for (i = 0; i < MAX_ANTENNAS; i++) {
+                       s8 pow_offset = ate_db->tx_power_offset[i];
+
+                       signed_offset = cl_power_offset_check_margin(cl_hw, bw, i, pow_offset);
+                       offset[i] = cl_convert_signed_to_reg_value(signed_offset);
+               }
+
+               return;
+       }
+
+       for (i = 0; i < MAX_ANTENNAS; i++) {
+               s8 pow_offset = cl_hw->tx_pow_info[chan_idx][i].offset;
+
+               signed_offset = cl_power_offset_check_margin(cl_hw, bw, i, pow_offset);
+               offset[i] = cl_convert_signed_to_reg_value(signed_offset);
+       }
+}
+
+static void pivot_channels_reset(struct cl_hw *cl_hw, u8 *bitmap)
+{
+       u8 i, start = 0, max = 0;
+
+       get_bitmap_boundaries(cl_hw->chip, cl_hw->tcv_idx, &start, &max);
+
+       for (i = start; i < max; i++)
+               bitmap_clear_bit_idx(cl_hw, bitmap, i);
+}
+
+static u8 count_num_pivots(struct cl_chip *chip, const u8 *bitmap, u8 tcv_idx)
+{
+       u8 i = 0, cnt = 0, start = 0, max = 0;
+
+       get_bitmap_boundaries(chip, tcv_idx, &start, &max);
+
+       for (i = start; i < max; i++)
+               if (bitmap_test_bit_idx(bitmap, i))
+                       cnt++;
+
+       return cnt;
+}
+
+int cl_calib_pivot_channels_set(struct cl_hw *cl_hw, const void *chan_list, u32 size)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       u8 bitmap[BIT_MAP_SIZE] = {0};
+       u8 num_pivots = 0;
+       u8 idx = 0;
+
+       if (cl_e2p_read(chip, bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return -1;
+
+       num_pivots = count_num_pivots(chip, bitmap, cl_hw->tcv_idx);
+
+       if (num_pivots > 0) {
+               cl_dbg_err(cl_hw, "Vector already set\n");
+               return -EACCES;
+       }
+
+       while (size--) {
+               idx = cl_channel_to_index(cl_hw, ((u32 *)chan_list)[size]);
+
+               if (idx == INVALID_CHAN_IDX) {
+                       cl_dbg_err(cl_hw, "Bad channel index %u", idx);
+                       return -EINVAL;
+               }
+
+               if (cl_hw_is_tcv1(cl_hw))
+                       idx += get_bitmap_start_tcv1(chip);
+
+               if (!bitmap_set_bit_idx(cl_hw, bitmap, idx)) {
+                       cl_dbg_err(cl_hw, "Bad channel index %u", idx);
+                       return -EINVAL;
+               }
+       }
+
+       if (count_bits(bitmap) > NUM_OF_PIVOTS) {
+               cl_dbg_err(cl_hw, "Too much pivot channels chosen\n");
+               return -EINVAL;
+       }
+
+       if (cl_e2p_write(chip, bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return -1;
+
+       /*
+        * Pivots of tcv0 are located before the pivots of tcv1.
+        * If calibration of tcv1 was done before calibration of tcv0, we must move the
+        * calibration data of tcv1 so that there is room for the tcv0 calibration data.
+        */
+       if (cl_hw_is_tcv0(cl_hw)) {
+               u8 num_pivots_tcv0 = count_num_pivots(chip, bitmap, TCV0);
+               u8 num_pivots_tcv1 = count_num_pivots(chip, bitmap, TCV1);
+
+               if (num_pivots_tcv1 > 0) {
+                       struct eeprom_phy_calib phy_calib[NUM_PIVOT_PHYS] = { {0} };
+
+                       if (cl_e2p_read(chip, (u8 *)phy_calib, SIZE_CALIB_PHY, ADDR_CALIB_PHY))
+                               return -1;
+
+                       memmove(&phy_calib[num_pivots_tcv0 * MAX_ANTENNAS],
+                               &phy_calib[0],
+                               num_pivots_tcv1 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+                       memset(&phy_calib[0],
+                              0,
+                              num_pivots_tcv0 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+
+                       if (cl_e2p_write(chip, (u8 *)phy_calib, SIZE_CALIB_PHY, ADDR_CALIB_PHY))
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
+int cl_calib_pivot_channels_reset(struct cl_hw *cl_hw)
+{
+       /* Both eeprom and efuse are being set to 0 for reset */
+       struct cl_chip *chip = cl_hw->chip;
+       u8 bitmap[BIT_MAP_SIZE] = {0};
+       struct eeprom_phy_calib phy_calib[NUM_PIVOT_PHYS] = { {0} };
+       u8 num_pivots_tcv0 = 0;
+       u8 num_pivots_tcv1 = 0;
+
+       if (sizeof(phy_calib) != SIZE_CALIB_PHY) {
+               cl_dbg_err(cl_hw, "sizeof(phy_calib) != SIZE_CALIB_PHY\n");
+               return -1;
+       }
+
+       /* Read current bitmap and calibration data */
+       if (cl_e2p_read(chip, (u8 *)bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return -1;
+       if (cl_e2p_read(chip, (u8 *)phy_calib, SIZE_CALIB_PHY, ADDR_CALIB_PHY))
+               return -1;
+
+       /* Find number of pivots for each band */
+       num_pivots_tcv0 = count_num_pivots(chip, bitmap, TCV0);
+       num_pivots_tcv1 = count_num_pivots(chip, bitmap, TCV1);
+
+       /* Reset bitmap of this band */
+       pivot_channels_reset(cl_hw, bitmap);
+
+       /* Reset calibration data of this band */
+       if (cl_hw_is_tcv0(cl_hw)) {
+               if (num_pivots_tcv1 > 0) {
+                       /* For tcv0 shift calibration data of tcv1 to the beginning */
+                       memcpy(&phy_calib[0], &phy_calib[num_pivots_tcv0 * MAX_ANTENNAS],
+                              num_pivots_tcv1 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+                       memset(&phy_calib[num_pivots_tcv1 * MAX_ANTENNAS], 0,
+                              num_pivots_tcv0 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+               } else {
+                       memset(&phy_calib[0], 0,
+                              num_pivots_tcv0 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+               }
+       } else {
+               memset(&phy_calib[num_pivots_tcv0 * MAX_ANTENNAS],
+                      0, num_pivots_tcv1 * MAX_ANTENNAS * sizeof(struct eeprom_phy_calib));
+       }
+
+       /* Write back modified bitmap and calibration data */
+       if (cl_e2p_write(chip, (u8 *)bitmap, BIT_MAP_SIZE, ADDR_CALIB_CHAN_BMP))
+               return -1;
+       if (cl_e2p_write(chip, (u8 *)phy_calib, SIZE_CALIB_PHY, ADDR_CALIB_PHY))
+               return -1;
+
+       /* Reset host calibration data */
+       cl_calib_power_reset(cl_hw);
+
+       return 0;
+}
+
+static void cl_calib_init_cfm(struct cl_iq_dcoc_data *iq_dcoc_data)
+{
+       int i;
+
+       for (i = 0; i < CALIB_CFM_MAX; i++)
+               iq_dcoc_data->dcoc_iq_cfm[i].status = CALIB_FAIL;
+}
+
+static void cl_calib_save_channel(struct cl_hw *cl_hw, struct cl_calib_restore *calib_restore)
+{
+       calib_restore->bw = cl_hw->bw;
+       calib_restore->primary = cl_hw->primary_freq;
+       calib_restore->center = cl_hw->center_freq;
+       calib_restore->channel = ieee80211_frequency_to_channel(cl_hw->primary_freq);
+}
+
+static int cl_calib_set_idle(struct cl_hw *cl_hw, bool idle)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_hw *cl_hw_tcv0 = chip->cl_hw_tcv0;
+       struct cl_hw *cl_hw_tcv1 = chip->cl_hw_tcv1;
+       u8 is_prod = chip->conf->ce_production_mode;
+       bool tcv0_en = (cl_radio_is_on(cl_hw_tcv0) || (is_prod && cl_hw_tcv0->ate_db.active));
+       bool tcv1_en = (cl_radio_is_on(cl_hw_tcv1) || (is_prod && cl_hw_tcv1->ate_db.active));
+
+       if (!idle) {
+               if (tcv1_en)
+                       cl_msg_tx_set_idle(cl_hw_tcv1, MAC_ACTIVE);
+
+               if (tcv0_en)
+                       cl_msg_tx_set_idle(cl_hw_tcv0, MAC_ACTIVE);
+
+               return 0;
+       }
+
+       if (tcv1_en)
+               cl_msg_tx_idle_async(cl_hw_tcv1);
+
+       if (tcv0_en)
+               cl_msg_tx_set_idle(cl_hw_tcv0, MAC_IDLE_SYNC);
+
+       if (wait_event_timeout(cl_hw->wait_queue, !cl_hw->idle_async_set,
+                              CL_MSG_CFM_TIMEOUT_JIFFIES))
+               return 0;
+
+       cl_dbg_err(cl_hw, "Timeout occurred - MM_IDLE_ASYNC_IND\n");
+
+       return -ETIMEDOUT;
+}
+
+static int _cl_calib_set_channel(struct cl_hw *cl_hw, u32 channel, u32 bw)
+{
+       u32 primary = 0;
+       u32 center = 0;
+       enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20;
+
+       if (cl_chandef_calc(cl_hw, channel, bw, &width, &primary, &center)) {
+               cl_dbg_err(cl_hw, "cl_chandef_calc failed\n");
+               return -EINVAL;
+       }
+
+       cl_dbg_verbose(cl_hw, "Calibrate channel %u bw %u\n", channel, BW_TO_MHZ(bw));
+
+       return _cl_msg_tx_set_channel(cl_hw, channel, bw, primary, center, SET_CHANNEL_MODE_CALIB);
+}
+
+static void cl_calib_channels_6g(struct cl_hw *cl_hw)
+{
+       int i;
+
+       /* Calibrate channels: 1, 33, 65, 97, 129, 161, 193, 225 */
+       for (i = 0; i < CALIB_CHAN_6G_MAX; i += 2)
+               _cl_calib_set_channel(cl_hw, calib_channels_6g[i], CHNL_BW_160);
+
+       for (i = 0; i < CALIB_CHAN_6G_MAX; i++) {
+               _cl_calib_set_channel(cl_hw, calib_channels_6g[i], CHNL_BW_80);
+               _cl_calib_set_channel(cl_hw, calib_channels_6g[i], CHNL_BW_20);
+       }
+}
+
+static void cl_calib_channels_5g(struct cl_hw *cl_hw)
+{
+       int i;
+
+       _cl_calib_set_channel(cl_hw, 36, CHNL_BW_160);
+       _cl_calib_set_channel(cl_hw, 100, CHNL_BW_160);
+
+       for (i = 0; i < CALIB_CHAN_5G_MAX; i++) {
+               _cl_calib_set_channel(cl_hw, calib_channels_5g[i], CHNL_BW_80);
+               _cl_calib_set_channel(cl_hw, calib_channels_5g[i], CHNL_BW_20);
+       }
+}
+
+static void cl_calib_channels_24g(struct cl_hw *cl_hw)
+{
+       int i;
+
+       for (i = 0; i < CALIB_CHAN_24G_MAX; i++) {
+               _cl_calib_set_channel(cl_hw, calib_channels_24g[i], CHNL_BW_40);
+               _cl_calib_set_channel(cl_hw, calib_channels_24g[i], CHNL_BW_20);
+       }
+}
+
+static void cl_calib_scan_all_channels(struct cl_hw *cl_hw)
+{
+       if (cl_band_is_6g(cl_hw))
+               cl_calib_channels_6g(cl_hw);
+       else if (cl_band_is_5g(cl_hw))
+               cl_calib_channels_5g(cl_hw);
+       else
+               cl_calib_channels_24g(cl_hw);
+}
+
+static void cl_calib_restore_channel(struct cl_hw *cl_hw, struct cl_calib_restore *calib_restore)
+{
+       u8 bw = calib_restore->bw;
+       u32 primary = calib_restore->primary;
+       u32 center = calib_restore->center;
+       u8 channel = calib_restore->channel;
+
+       cl_msg_tx_set_channel(cl_hw, channel, bw, primary, center);
+}
+
+static void cl_calib_print_errors(struct cl_hw *cl_hw)
+{
+       struct cl_calib_errors *errors = &cl_hw->chip->calib_db.errors[cl_hw->tcv_idx];
+
+       if (!errors->dcoc && !errors->lolc && !errors->iq_rx && !errors->iq_tx)
+               return;
+
+       pr_warn("Calibration errors: DCOC %u, LOLC %u, IQ RX %u, IQ TX %u\n",
+               errors->dcoc, errors->lolc, errors->iq_rx, errors->iq_tx);
+}
+
+static u8 cl_calib_channel_to_idx(struct cl_hw *cl_hw, u8 channel)
+{
+       u8 i = 0;
+
+       if (cl_band_is_6g(cl_hw)) {
+               for (i = 0; i < CALIB_CHAN_6G_MAX; i++)
+                       if (calib_channels_6g[i] == channel)
+                               return i;
+       } else if (cl_band_is_5g(cl_hw)) {
+               for (i = 0; i < CALIB_CHAN_5G_MAX; i++)
+                       if (calib_channels_5g[i] == channel)
+                               return i;
+       } else {
+               for (i = 0; i < CALIB_CHAN_24G_MAX; i++)
+                       if (calib_channels_24g[i] == channel)
+                               return i;
+       }
+
+       return 0;
+}
+
+static void cl_calib_check_err_dcoc(struct cl_hw *cl_hw, s16 calib_temperature,
+                                   int channel, u8 bw)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       int lna, ant;
+       struct cl_dcoc_report *dcoc_calib_report_dma;
+       u8 dcoc_threshold = chip->conf->ci_dcoc_mv_thr[bw];
+       s16 i, q;
+
+       for (lna = 0; lna < DCOC_LNA_GAIN_NUM; lna++) {
+               ant_for_each(ant) {
+                       dcoc_calib_report_dma =
+                               &cl_hw->iq_dcoc_data_info.iq_dcoc_data->report.dcoc[lna][ant];
+                       i = (s16)le16_to_cpu(dcoc_calib_report_dma->i_dc);
+                       q = (s16)le16_to_cpu(dcoc_calib_report_dma->q_dc);
+
+                       if (abs(i) > dcoc_threshold) {
+                               chip->calib_db.errors[cl_hw->tcv_idx].dcoc++;
+                               cl_dbg_info(cl_hw,
+                                           "DCOC Error: lna = %u, ant = %u, "
+                                           "i (|%d|) > threshold (%d)\n",
+                                           lna, ant, i, dcoc_threshold);
+                       } else {
+                               cl_dbg_info(cl_hw,
+                                           "DCOC Valid: lna = %u, ant = %u, "
+                                           "i (|%d|) < threshold (%d)\n",
+                                           lna, ant, i, dcoc_threshold);
+                       }
+
+                       if (abs(q) > dcoc_threshold) {
+                               chip->calib_db.errors[cl_hw->tcv_idx].dcoc++;
+                               cl_dbg_info(cl_hw,
+                                           "DCOC Error: lna = %u, ant = %u, "
+                                           "q (|%d|) > threshold (%d)\n",
+                                           lna, ant, q, dcoc_threshold);
+                       } else {
+                               cl_dbg_info(cl_hw,
+                                           "DCOC Valid: lna = %u, ant = %u, "
+                                           "q (|%d|) < threshold (%d)\n",
+                                           lna, ant, q, dcoc_threshold);
+                       }
+               }
+       }
+}
+
+static void cl_calib_check_err_iq_lolc(struct cl_hw *cl_hw, s16 calib_temperature,
+                                      int channel, u8 bw, u8 plan_bitmap)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_iq_dcoc_report *report = &cl_hw->iq_dcoc_data_info.iq_dcoc_data->report;
+       int ant;
+       struct cl_lolc_report lolc_report_dma;
+       s16 lolc_threshold = chip->conf->ci_lolc_db_thr;
+       s32 lolc_qual = 0;
+
+       ant_for_each(ant) {
+               if ((plan_bitmap & (1 << ant)) == 0)
+                       continue;
+
+               lolc_report_dma = report->lolc_report[ant];
+               lolc_qual = (s16)le16_to_cpu(lolc_report_dma.lolc_qual) >> 8;
+
+               if (lolc_qual > lolc_threshold) {
+                       chip->calib_db.errors[cl_hw->tcv_idx].lolc++;
+
+                       cl_dbg_info(cl_hw,
+                                   "LOLC Error: ant = %u, n_iter = %u, "
+                                   "quality (%d) > threshold (%d)\n",
+                                   ant, lolc_report_dma.n_iter, lolc_qual, lolc_threshold);
+               } else {
+                       cl_dbg_info(cl_hw,
+                                   "LOLC Valid: ant = %u, n_iter = %u, "
+                                   "quality (%d) < threshold (%d)\n",
+                                   ant, lolc_report_dma.n_iter, lolc_qual, lolc_threshold);
+               }
+       }
+}
+
+static void cl_calib_check_err_iq(struct cl_hw *cl_hw, s16 calib_temperature,
+                                 u8 ch, u8 bw, u8 plan_bitmap)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 ant = 0;
+       struct cl_iq_report iq_report_dma;
+       s8 iq_threshold = cl_hw->chip->conf->ci_iq_db_thr;
+
+       ant_for_each(ant) {
+               if ((plan_bitmap & (1 << ant)) == 0)
+                       continue;
+
+               iq_report_dma = cl_hw->iq_dcoc_data_info.iq_dcoc_data->report.iq_tx[ant];
+
+               if (iq_report_dma.ir_db_avg_post > iq_threshold) {
+                       chip->calib_db.errors[tcv_idx].iq_tx++;
+                       cl_dbg_info(cl_hw, "IQ TX Error: ant = %u, ir (%d) > threshold (%d)\n",
+                                   ant, iq_report_dma.ir_db_avg_post, iq_threshold);
+               } else {
+                       cl_dbg_info(cl_hw, "IQ TX Valid: ant = %u, ir (%d) < threshold (%d)\n",
+                                   ant, iq_report_dma.ir_db_avg_post, iq_threshold);
+               }
+
+               iq_report_dma = cl_hw->iq_dcoc_data_info.iq_dcoc_data->report.iq_rx[ant];
+
+               if (iq_report_dma.ir_db_avg_post > iq_threshold) {
+                       chip->calib_db.errors[tcv_idx].iq_rx++;
+                       cl_dbg_info(cl_hw, "IQ RX Error: ant = %u, ir (%d) > threshold (%d)\n",
+                                   ant, iq_report_dma.ir_db_avg_post, iq_threshold);
+               } else {
+                       cl_dbg_info(cl_hw, "IQ RX Valid: ant = %u, ir (%d) < threshold (%d)\n",
+                                   ant, iq_report_dma.ir_db_avg_post, iq_threshold);
+               }
+       }
+}
+
+static u8 cl_calib_center_freq_to_idx(struct cl_hw *cl_hw, u32 center_freq)
+{
+       u8 i = 0;
+       u8 center_channel = ieee80211_frequency_to_channel(center_freq);
+
+       if (cl_band_is_6g(cl_hw)) {
+               for (i = 1; i < CALIB_CHAN_6G_MAX; i++)
+                       if (calib_channels_6g[i] > center_channel)
+                               return (i - 1);
+
+               return (CALIB_CHAN_6G_MAX - 1);
+       }
+
+       if (cl_band_is_5g(cl_hw)) {
+               for (i = 1; i < CALIB_CHAN_5G_MAX; i++)
+                       if (calib_channels_5g[i] > center_channel)
+                               return (i - 1);
+
+               return (CALIB_CHAN_5G_MAX - 1);
+       }
+
+       for (i = 0; i < CALIB_CHAN_24G_MAX; i++)
+               if (abs(calib_channels_24g[i] - center_channel) < 3)
+                       return i;
+
+       return (CALIB_CHAN_24G_MAX - 1);
+}
+
+static void cl_calib_fill_data_dcoc(struct cl_hw *cl_hw, struct cl_iq_dcoc_info *iq_dcoc_db)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       u8 lna = 0, ant = 0;
+       u8 channel_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 bw = cl_hw->bw;
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+
+       for (lna = 0; lna < DCOC_LNA_GAIN_NUM; lna++)
+               ant_for_each(ant)
+                       iq_dcoc_db->dcoc[lna][ant] =
+                               chip->calib_db.dcoc[tcv_idx][channel_idx][bw][sx][ant][lna];
+}
+
+static void cl_calib_fill_data_iq(struct cl_hw *cl_hw, struct cl_iq_calib *iq_data,
+                                 struct cl_iq_calib *iq_chip_data)
+{
+       u8 ant = 0;
+
+       ant_for_each(ant) {
+               iq_data[ant].coef0 = cpu_to_le32(iq_chip_data[ant].coef0);
+               iq_data[ant].coef1 = cpu_to_le32(iq_chip_data[ant].coef1);
+               iq_data[ant].coef2 = cpu_to_le32(iq_chip_data[ant].coef2);
+               iq_data[ant].gain = cpu_to_le32(iq_chip_data[ant].gain);
+       }
+}
+
+static void cl_calib_fill_data_iq_lolc(struct cl_hw *cl_hw, __le32 *iq_lolc)
+{
+       struct cl_calib_db *calib_db = &cl_hw->chip->calib_db;
+       u8 ant = 0;
+       u8 chan_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 bw = cl_hw->bw;
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+
+       ant_for_each(ant)
+               iq_lolc[ant] = cpu_to_le32(calib_db->iq_tx_lolc[tcv_idx][chan_idx][bw][sx][ant]);
+}
+
+static void cl_calib_handle_cfm_dcoc(struct cl_hw *cl_hw)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_dcoc_calib *dcoc_calib;
+       struct cl_dcoc_calib *dcoc_calib_dma;
+       struct calib_cfm *dcoc_iq_cfm =
+               &cl_hw->iq_dcoc_data_info.iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_DCOC];
+       int lna, ant;
+       u16 raw_bits = (le16_to_cpu(dcoc_iq_cfm->raw_bits_data_0) +
+                       le16_to_cpu(dcoc_iq_cfm->raw_bits_data_1)) / 2;
+       s16 calib_temperature = cl_temperature_calib_calc(cl_hw, raw_bits);
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+       u8 channel = cl_hw->channel;
+       u8 bw = cl_hw->bw;
+       u8 channel_idx = cl_calib_channel_to_idx(cl_hw, channel);
+
+       for (lna = 0; lna < DCOC_LNA_GAIN_NUM; lna++) {
+               ant_for_each(ant) {
+                       dcoc_calib = &chip->calib_db.dcoc[tcv_idx][channel_idx][bw][sx][ant][lna];
+                       dcoc_calib_dma =
+                               &cl_hw->iq_dcoc_data_info.iq_dcoc_data->iq_dcoc_db.dcoc[lna][ant];
+                       dcoc_calib->i = dcoc_calib_dma->i;
+                       dcoc_calib->q = dcoc_calib_dma->q;
+               }
+       }
+
+       cl_calib_check_err_dcoc(cl_hw, calib_temperature, channel, bw);
+
+       /*
+        * Set the default status to FAIL, to ensure FW is actually changing the value,
+        * if the calibration succeeded.
+        */
+       cl_hw->iq_dcoc_data_info.iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_DCOC].status = CALIB_FAIL;
+}
+
+static void cl_calib_handle_cfm_iq(struct cl_hw *cl_hw, u8 plan_bitmap)
+{
+       struct calib_cfm *dcoc_iq_cfm =
+               &cl_hw->iq_dcoc_data_info.iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_IQ];
+       u16 raw_bits_data_0 = le16_to_cpu(dcoc_iq_cfm->raw_bits_data_0);
+       u16 raw_bits_data_1 = le16_to_cpu(dcoc_iq_cfm->raw_bits_data_1);
+       u16 raw_bits = (raw_bits_data_0 + raw_bits_data_1) / 2;
+       s16 calib_temperature = cl_temperature_calib_calc(cl_hw, raw_bits);
+       u8 channel = cl_hw->channel;
+       u8 bw = cl_hw->bw;
+       int ant;
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+       u8 channel_idx = cl_calib_channel_to_idx(cl_hw, channel);
+
+       ant_for_each(ant) {
+               if ((plan_bitmap & (1 << ant)) == 0)
+                       continue;
+
+               cl_hw->chip->calib_db.iq_tx[tcv_idx][channel_idx][bw][sx][ant] =
+                       cl_hw->iq_dcoc_data_info.iq_dcoc_data->iq_dcoc_db.iq_tx[ant];
+
+               cl_hw->chip->calib_db.iq_rx[tcv_idx][channel_idx][bw][sx][ant] =
+                       cl_hw->iq_dcoc_data_info.iq_dcoc_data->iq_dcoc_db.iq_rx[ant];
+       }
+
+       cl_calib_check_err_iq(cl_hw, calib_temperature, channel, bw, plan_bitmap);
+
+       /*
+        * Set the default status to FAIL, to ensure FW is actually changing the value,
+        * if the calibration succeeded.
+        */
+       dcoc_iq_cfm->status = CALIB_FAIL;
+}
+
+static void cl_calib_handle_cfm_iq_lolc(struct cl_hw *cl_hw, u8 plan_bitmap)
+{
+       struct calib_cfm *dcoc_iq_cfm =
+               &cl_hw->iq_dcoc_data_info.iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_IQ];
+       u16 raw_bits = (le16_to_cpu(dcoc_iq_cfm->raw_bits_data_0) +
+               le16_to_cpu(dcoc_iq_cfm->raw_bits_data_1)) / 2;
+       s16 calib_temperature = cl_temperature_calib_calc(cl_hw, raw_bits);
+       u8 channel = cl_hw->channel;
+       u8 channel_idx = cl_calib_channel_to_idx(cl_hw, channel);
+       u8 bw = cl_hw->bw;
+       u8 sx = cl_hw->tcv_idx;
+       int ant;
+
+       ant_for_each(ant) {
+               if ((plan_bitmap & (1 << ant)) == 0)
+                       continue;
+
+               cl_hw->chip->calib_db.iq_tx_lolc[cl_hw->tcv_idx][channel_idx][bw][sx][ant] =
+                       cl_hw->iq_dcoc_data_info.iq_dcoc_data->iq_dcoc_db.iq_tx_lolc[ant];
+       }
+
+       cl_calib_check_err_iq_lolc(cl_hw, calib_temperature, channel, bw, plan_bitmap);
+
+       /*
+        * Set the default status to FAIL, to ensure FW is actually changing the value,
+        * if the calibration succeeded.
+        */
+       dcoc_iq_cfm->status = CALIB_FAIL;
+}
+
+static void cl_calib_set_channel_start_work(struct work_struct *ws)
+{
+       struct cl_calib_work *calib_work = container_of(ws, struct cl_calib_work, ws);
+       struct cl_hw *cl_hw = calib_work->cl_hw;
+       struct cl_hw *cl_hw_other = cl_hw_other_tcv(cl_hw);
+       struct cl_chip *chip = cl_hw->chip;
+
+       cl_calib_start(cl_hw);
+
+       if (cl_chip_is_both_enabled(chip))
+               cl_calib_start(cl_hw_other);
+
+       chip->calib_db.scan_complete = true;
+}
+
+int cl_calib_start(struct cl_hw *cl_hw)
+{
+       u8 channel = cl_hw->conf->ha_channel;
+       u8 bw = cl_hw->conf->ce_channel_bandwidth;
+       enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20;
+       u32 primary = 0;
+       u32 center = 0;
+
+       if (cl_chandef_calc(cl_hw, channel, bw, &width, &primary, &center))
+               return -EINVAL;
+
+       return cl_calib_set_channel(cl_hw, channel, bw, primary, center);
+}
+
+void cl_calib_fill_phy_data(struct cl_hw *cl_hw, struct cl_iq_dcoc_info *iq_dcoc_db, u8 flags)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       u8 channel_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 bw = cl_hw->bw;
+       u8 tcv_idx = cl_hw->tcv_idx;
+
+       if (flags & SET_PHY_DATA_FLAGS_DCOC)
+               cl_calib_fill_data_dcoc(cl_hw, iq_dcoc_db);
+
+       if (flags & SET_PHY_DATA_FLAGS_IQ_TX_LOLC)
+               cl_calib_fill_data_iq_lolc(cl_hw, iq_dcoc_db->iq_tx_lolc);
+
+       if (flags & SET_PHY_DATA_FLAGS_IQ_TX)
+               cl_calib_fill_data_iq(cl_hw, iq_dcoc_db->iq_tx,
+                                     chip->calib_db.iq_tx[tcv_idx][channel_idx][bw][tcv_idx]);
+
+       if (flags & SET_PHY_DATA_FLAGS_IQ_RX)
+               cl_calib_fill_data_iq(cl_hw, iq_dcoc_db->iq_rx,
+                                     chip->calib_db.iq_rx[tcv_idx][channel_idx][bw][tcv_idx]);
+}
+
+int cl_calib_tables_alloc(struct cl_hw *cl_hw)
+{
+       struct cl_iq_dcoc_data *buf = NULL;
+       u32 len = sizeof(struct cl_iq_dcoc_data);
+       dma_addr_t phys_dma_addr;
+
+       buf = dma_alloc_coherent(cl_hw->chip->dev, len, &phys_dma_addr, GFP_KERNEL);
+
+       if (!buf)
+               return -1;
+
+       cl_hw->iq_dcoc_data_info.iq_dcoc_data = buf;
+       cl_hw->iq_dcoc_data_info.dma_addr = cpu_to_le32(phys_dma_addr);
+
+       cl_calib_init_cfm(cl_hw->iq_dcoc_data_info.iq_dcoc_data);
+
+       return 0;
+}
+
+void cl_calib_tables_free(struct cl_hw *cl_hw)
+{
+       struct cl_iq_dcoc_data_info *iq_dcoc_data_info = &cl_hw->iq_dcoc_data_info;
+       u32 len = sizeof(struct cl_iq_dcoc_data);
+       dma_addr_t phys_dma_addr = le32_to_cpu(iq_dcoc_data_info->dma_addr);
+
+       if (!iq_dcoc_data_info->iq_dcoc_data)
+               return;
+
+       dma_free_coherent(cl_hw->chip->dev, len, (void *)iq_dcoc_data_info->iq_dcoc_data,
+                         phys_dma_addr);
+       iq_dcoc_data_info->iq_dcoc_data = NULL;
+}
+
+bool cl_calib_is_needed(struct cl_hw *cl_hw, u8 channel, u8 bw)
+{
+       u8 channel_idx;
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 ant;
+       u32 primary = 0;
+       u32 center_freq = 0;
+       enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20;
+
+       if (cl_chandef_calc(cl_hw, channel, bw, &width, &primary, &center_freq)) {
+               cl_dbg_err(cl_hw, "cl_chandef_calc failed\n");
+               return false;
+       }
+
+       channel_idx = cl_calib_center_freq_to_idx(cl_hw, center_freq);
+
+       /* Check if we already calibrated */
+       ant_for_each(ant) {
+               if (cl_hw->chip->calib_db.iq_tx_lolc[tcv_idx][channel_idx][bw][tcv_idx][ant])
+                       return false;
+       }
+
+       return true;
+}
+
+int cl_calib_set_channel(struct cl_hw *cl_hw, u8 channel, u8 bw, u32 primary, u32 center)
+{
+       struct cl_chip *chip = cl_hw->chip;
+       struct cl_hw *cl_hw_other = cl_hw_other_tcv(cl_hw);
+       struct cl_calib_restore calib_restore;
+       int ret = 0;
+       u8 fem_mode = cl_hw->fem_system_mode;
+       bool save_ch_other = !!cl_hw_other->primary_freq;
+
+       if (save_ch_other)
+               cl_calib_save_channel(cl_hw_other, &calib_restore);
+
+       ret = cl_calib_set_idle(cl_hw, true);
+       if (ret)
+               return ret;
+
+       cl_fem_set_system_mode(cl_hw, FEM_MODE_LNA_BYPASS_ONLY, U8_MAX);
+       cl_afe_cfg_calib(chip);
+
+       if (chip->conf->ce_calib_scan_en && !chip->calib_db.scan_complete && cl_hw->calib_ready)
+               cl_calib_scan_all_channels(cl_hw);
+       else
+               _cl_calib_set_channel(cl_hw, channel, bw);
+
+       cl_fem_set_system_mode(cl_hw, fem_mode, U8_MAX);
+       cl_afe_cfg_restore(chip);
+
+       _cl_msg_tx_set_channel(cl_hw, channel, bw, primary, center, SET_CHANNEL_MODE_OPERETIONAL);
+
+       if (save_ch_other)
+               cl_calib_restore_channel(cl_hw_other, &calib_restore);
+
+       cl_calib_set_idle(cl_hw, false);
+
+       return ret;
+}
+
+void cl_calib_start_work(struct cl_hw *cl_hw)
+{
+       struct cl_calib_work *calib_work = kzalloc(sizeof(*calib_work), GFP_ATOMIC);
+
+       if (!calib_work)
+               return;
+
+       calib_work->cl_hw = cl_hw;
+       INIT_WORK(&calib_work->ws, cl_calib_set_channel_start_work);
+       queue_work(cl_hw->drv_workqueue, &calib_work->ws);
+}
+
+int cl_calib_handle_cfm(struct cl_hw *cl_hw, u8 mode)
+{
+       struct cl_iq_dcoc_data *iq_dcoc_data = cl_hw->iq_dcoc_data_info.iq_dcoc_data;
+       struct cl_calib_errors *errors = &cl_hw->chip->calib_db.errors[cl_hw->tcv_idx];
+
+       /*
+        * In case any of the requested calibrations failed - no need to copy
+        * the other Calibration data, and fail the whole calibration process.
+        */
+       if ((mode & SET_CHANNEL_MODE_CALIB_DCOC &&
+            iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_DCOC].status != CALIB_SUCCESS) ||
+           (mode & SET_CHANNEL_MODE_CALIB_IQ &&
+            iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_IQ].status != CALIB_SUCCESS)) {
+               cl_dbg_err(cl_hw, "Calibration failed! mode = %u, DCOC_CFM_STATUS = %u, "
+                          "IQ_CFM_STATUS = %u\n",
+                          mode,
+                          iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_DCOC].status,
+                          iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_IQ].status);
+               /* Set status to CALIB_FAIL to ensure that FW is writing the values. */
+               iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_DCOC].status = CALIB_FAIL;
+               iq_dcoc_data->dcoc_iq_cfm[CALIB_CFM_IQ].status = CALIB_FAIL;
+               return -1;
+       }
+
+       if (mode & SET_CHANNEL_MODE_CALIB_DCOC)
+               cl_calib_handle_cfm_dcoc(cl_hw);
+
+       if (mode & SET_CHANNEL_MODE_CALIB_IQ)
+               cl_calib_handle_cfm_iq(cl_hw, cl_hw->mask_num_antennas);
+
+       if (mode & SET_CHANNEL_MODE_CALIB_LOLC)
+               cl_calib_handle_cfm_iq_lolc(cl_hw, cl_hw->mask_num_antennas);
+
+       /* Print calibration errors counters */
+       cl_calib_print_errors(cl_hw);
+
+       memset(errors, 0, sizeof(*errors));
+
+       return 0;
+}
+
+int cl_calib_validate_ants(struct cl_hw *cl_hw)
+{
+       struct cl_tcv_conf *conf = cl_hw->conf;
+       u8 ant = 0;
+       int ret = 0;
+
+       for (ant = 0; ant < cl_hw->num_antennas; ant++) {
+               if (conf->ci_calib_ant_tx[ant] < cl_hw->first_ant ||
+                   conf->ci_calib_ant_tx[ant] > cl_hw->last_ant) {
+                       CL_DBG_ERROR(cl_hw,
+                                    "TX: Antenna [%u] value is out of boundaries [%u].\n"
+                                    "Minimum value allowed is: %u\n"
+                                    "Maximum value allowed is: %u\n",
+                                    ant, conf->ci_calib_ant_tx[ant], cl_hw->first_ant,
+                                    cl_hw->last_ant);
+                       ret = -1;
+               }
+
+               if (conf->ci_calib_ant_rx[ant] < cl_hw->first_ant ||
+                   conf->ci_calib_ant_rx[ant] > cl_hw->last_ant) {
+                       CL_DBG_ERROR(cl_hw,
+                                    "RX: Antenna [%u] value is out of boundaries [%u]."
+                                    "Minimum value allowed is: %u\n"
+                                    "Maximum value allowed is: %u\n",
+                                    ant, conf->ci_calib_ant_tx[ant], cl_hw->first_ant,
+                                    cl_hw->last_ant);
+                       ret = -1;
+               }
+       }
+
+       return ret;
+}
+
+void cl_calib_iq_get_tone_vector(u8 bw, u16 *tone_vector)
+{
+       u8 tone = 0;
+
+       for (tone = 0; tone < IQ_NUM_TONES_REQ; tone++)
+               tone_vector[tone] = cpu_to_le16((u16)tone_vector_arr[bw][tone]);
+}
+
+static int cl_calib_print_dcoc(struct cl_hw *cl_hw)
+{
+       struct cl_calib_db *calib_db = &cl_hw->chip->calib_db;
+       struct cl_dcoc_calib *dcoc_calib;
+       u8 lna = 0;
+       u8 ant = 0;
+       u8 channel_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+       u8 bw = cl_hw->bw;
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+       int len = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, PAGE_SIZE - len,
+                       "DCOC:\n"
+                       "LNA GAIN   ANTENNA   I    Q\n"
+                       "----------------------------\n");
+
+       for (lna = 0; lna < DCOC_LNA_GAIN_NUM; lna++) {
+               ant_for_each(ant) {
+                       dcoc_calib =
+                               &calib_db->dcoc[tcv_idx][channel_idx][bw][sx][ant][lna];
+
+                       len += snprintf(buf + len, PAGE_SIZE - len,
+                                       "%-11u%-10u%-5d%-5d\n", lna,
+                                       ant, dcoc_calib->i, dcoc_calib->q);
+               }
+       }
+
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+static int cl_calib_print_lolc(struct cl_hw *cl_hw)
+{
+       struct cl_calib_db *calib_db = &cl_hw->chip->calib_db;
+       u32 lolc_calib;
+       u8 ant = 0;
+       u8 channel_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+       u8 bw = cl_hw->bw;
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+       int len = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, PAGE_SIZE - len,
+                       "LOLC:\n"
+                       "ANTENNA   I     Q\n"
+                       "---------------------\n");
+
+       ant_for_each(ant) {
+               lolc_calib = calib_db->iq_tx_lolc[tcv_idx][channel_idx][bw][sx][ant];
+
+               len += snprintf(buf + len, PAGE_SIZE - len,
+                               "%-10u%-6d%-6d\n",
+                               ant, CAST_S12_TO_S32(lolc_calib & U12_BIT_MASK),
+                               CAST_S12_TO_S32((lolc_calib >> 2) & U12_BIT_MASK));
+       }
+
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+static int cl_calib_print_iq(struct cl_hw *cl_hw)
+{
+       struct cl_calib_db *calib_db = &cl_hw->chip->calib_db;
+       struct cl_iq_calib *iq;
+       u8 ant = 0;
+       u8 channel_idx = cl_calib_center_freq_to_idx(cl_hw, cl_hw->center_freq);
+       u8 tcv_idx = cl_hw->tcv_idx;
+       u8 sx = tcv_idx;
+       u8 bw = cl_hw->bw;
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+       int len = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, PAGE_SIZE - len,
+                       "IQ TX:\n"
+                       "ANTENNA COEF0      COEF1      COEF2      GAIN\n"
+                       "---------------------------------------------------\n");
+
+       ant_for_each(ant) {
+               iq = &calib_db->iq_tx[tcv_idx][channel_idx][bw][sx][ant];
+
+               len += snprintf(buf + len, PAGE_SIZE - len,
+                               "%-7u 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                               ant, iq->coef0, iq->coef1, iq->coef2, iq->gain);
+       }
+
+       len += snprintf(buf + len, PAGE_SIZE - len,
+                       "IQ RX:\n"
+                       "ANTENNA COEF0      COEF1      COEF2      GAIN\n"
+                       "---------------------------------------------------\n");
+
+       ant_for_each(ant) {
+               iq = &calib_db->iq_rx[tcv_idx][channel_idx][bw][sx][ant];
+
+               len += snprintf(buf + len, PAGE_SIZE - len,
+                               "%-7u 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                               ant, iq->coef0, iq->coef1, iq->coef2, iq->gain);
+       }
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+static int cl_calib_common_cli_help(struct cl_hw *cl_hw)
+{
+       char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       int err = 0;
+
+       if (!buf)
+               return -ENOMEM;
+
+       snprintf(buf, PAGE_SIZE,
+                "calib usage:\n"
+                "-d : Print DCOC coefficients\n"
+                "-i : Print IQ coefficients\n"
+                "-l : Print LOLC coefficients\n");
+
+       err = cl_vendor_reply(cl_hw, buf, strlen(buf));
+       kfree(buf);
+
+       return err;
+}
+
+int cl_calib_cli(struct cl_hw *cl_hw, struct cli_params *cli_params)
+{
+       switch (cli_params->option) {
+       case 'd':
+               return cl_calib_print_dcoc(cl_hw);
+       case 'i':
+               return cl_calib_print_iq(cl_hw);
+       case 'l':
+               return cl_calib_print_lolc(cl_hw);
+       case '?':
+               return cl_calib_common_cli_help(cl_hw);
+       default:
+               cl_dbg_err(cl_hw, "Illegal option (%c) - try '?' for help\n",
+                          cli_params->option);
+               return 0;
+       }
+}
--
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:03 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 ` viktor.barna [this message]
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 ` [RFC v1 180/256] cl8k: add sounding.c viktor.barna
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-29-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.