2021-10-17 20:04:25

by Christian Lamparter

[permalink] [raw]
Subject: [PATCH v1] ath10k: fetch (pre-)calibration data via nvmem subsystem

On most embedded ath10k devices (like range extenders,
routers, accesspoints, ...) the calibration data is
stored in a easily accessible MTD partitions named
"ART", "caldata", "calibration", etc...

Since commit 4b361cfa8624 ("mtd: core: add OTP nvmem provider support"):
MTD partitions and portions of them can be specified
as potential nvmem-cells which are accessible through
the nvmem subsystem.

This feature - together with an nvmem cell definition either
in the platform data or via device-tree allows drivers to get
the (pre-)calibration data which is required for initializing
the WIFI.

Tested with Netgear EX6150v2 (IPQ4018)

Cc: Robert Marko <[email protected]>
Cc: Thibaut Varène <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
---

This idea came up during the discussion of:
"ath10k: support bus and device specific API 1 BDF selection"

I do not have a device which has the boardfile data stored
by the manufracturer in flash. So this patch only deals with
the (pre-)calibration data. I'll see if I can get hold of a
suitable QCA9880 device to test it as well.

I placed the new nvmem code in front of the current "file" method
(firmware_request) because it made it easier for me to test it.
If needed I can be moved to a different place as well.
---
drivers/net/wireless/ath/ath10k/core.c | 64 +++++++++++++++++++++++++-
drivers/net/wireless/ath/ath10k/core.h | 6 +++
2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index c21e05549f61..3454d791ce76 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -12,6 +12,7 @@
#include <linux/dmi.h>
#include <linux/ctype.h>
#include <linux/pm_qos.h>
+#include <linux/nvmem-consumer.h>
#include <asm/byteorder.h>

#include "core.h"
@@ -935,7 +936,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
}

if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;
else
bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;
@@ -1726,7 +1728,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)

/* As of now pre-cal is valid for 10_4 variants */
if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||
- ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE)
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||
+ ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)
bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;

ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
@@ -1853,6 +1856,39 @@ static int ath10k_download_cal_eeprom(struct ath10k *ar)
return ret;
}

+static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
+{
+ struct nvmem_cell *cell;
+ void *buf;
+ size_t len;
+ int ret;
+
+ cell = devm_nvmem_cell_get(ar->dev, cell_name);
+ if (IS_ERR(cell)) {
+ ret = PTR_ERR(cell);
+ return ret;
+ }
+
+ buf = nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ if (ar->hw_params.cal_data_len != len) {
+ kfree(buf);
+ ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %ld != %d\n",
+ cell_name, len, ar->hw_params.cal_data_len);
+ return -EMSGSIZE;
+ }
+
+ ret = ath10k_download_board_data(ar, buf, len);
+ kfree(buf);
+ if (ret)
+ ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
+ cell_name, ret);
+
+ return ret;
+}
+
int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
struct ath10k_fw_file *fw_file)
{
@@ -2087,6 +2123,18 @@ static int ath10k_core_pre_cal_download(struct ath10k *ar)
{
int ret;

+ ret = ath10k_download_cal_nvmem(ar, "pre-calibration");
+ if (ret == 0) {
+ ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;
+ goto success;
+ } else if (ret == -EPROBE_DEFER) {
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",
+ ret);
+
ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
if (ret == 0) {
ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
@@ -2153,6 +2201,18 @@ static int ath10k_download_cal_data(struct ath10k *ar)
"pre cal download procedure failed, try cal file: %d\n",
ret);

+ ret = ath10k_download_cal_nvmem(ar, "calibration");
+ if (ret == 0) {
+ ar->cal_mode = ATH10K_CAL_MODE_NVMEM;
+ goto done;
+ } else if (ret == -EPROBE_DEFER) {
+ return ret;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot did not find a calibration nvmem-cell, try file next: %d\n",
+ ret);
+
ret = ath10k_download_cal_file(ar, ar->cal_file);
if (ret == 0) {
ar->cal_mode = ATH10K_CAL_MODE_FILE;
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 5aeff2d9f6cf..9f6680b3be0a 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -877,8 +877,10 @@ enum ath10k_cal_mode {
ATH10K_CAL_MODE_FILE,
ATH10K_CAL_MODE_OTP,
ATH10K_CAL_MODE_DT,
+ ATH10K_CAL_MODE_NVMEM,
ATH10K_PRE_CAL_MODE_FILE,
ATH10K_PRE_CAL_MODE_DT,
+ ATH10K_PRE_CAL_MODE_NVMEM,
ATH10K_CAL_MODE_EEPROM,
};

@@ -898,10 +900,14 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
return "otp";
case ATH10K_CAL_MODE_DT:
return "dt";
+ case ATH10K_CAL_MODE_NVMEM:
+ return "nvmem";
case ATH10K_PRE_CAL_MODE_FILE:
return "pre-cal-file";
case ATH10K_PRE_CAL_MODE_DT:
return "pre-cal-dt";
+ case ATH10K_PRE_CAL_MODE_NVMEM:
+ return "pre-cal-nvmem";
case ATH10K_CAL_MODE_EEPROM:
return "eeprom";
}
--
2.33.0


2021-10-18 03:26:35

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v1] ath10k: fetch (pre-)calibration data via nvmem subsystem

Hi Christian,

I love your patch! Perhaps something to improve:

[auto build test WARNING on kvalo-ath/ath-next]
[also build test WARNING on kvalo-wireless-drivers-next/master kvalo-wireless-drivers/master v5.15-rc5 next-20211015]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Christian-Lamparter/ath10k-fetch-pre-calibration-data-via-nvmem-subsystem/20211016-041140
base: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git ath-next
config: i386-randconfig-c001-20211015 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 6069a6a5049497a32a50a49661c2f4169078bdba)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/9a08dd8f5ae4d035f503db3a64ed4c6869b038e3
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Christian-Lamparter/ath10k-fetch-pre-calibration-data-via-nvmem-subsystem/20211016-041140
git checkout 9a08dd8f5ae4d035f503db3a64ed4c6869b038e3
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

>> drivers/net/wireless/ath/ath10k/core.c:1879:19: warning: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat]
cell_name, len, ar->hw_params.cal_data_len);
^~~
1 warning generated.


vim +1879 drivers/net/wireless/ath/ath10k/core.c

1858
1859 static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)
1860 {
1861 struct nvmem_cell *cell;
1862 void *buf;
1863 size_t len;
1864 int ret;
1865
1866 cell = devm_nvmem_cell_get(ar->dev, cell_name);
1867 if (IS_ERR(cell)) {
1868 ret = PTR_ERR(cell);
1869 return ret;
1870 }
1871
1872 buf = nvmem_cell_read(cell, &len);
1873 if (IS_ERR(buf))
1874 return PTR_ERR(buf);
1875
1876 if (ar->hw_params.cal_data_len != len) {
1877 kfree(buf);
1878 ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %ld != %d\n",
> 1879 cell_name, len, ar->hw_params.cal_data_len);
1880 return -EMSGSIZE;
1881 }
1882
1883 ret = ath10k_download_board_data(ar, buf, len);
1884 kfree(buf);
1885 if (ret)
1886 ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",
1887 cell_name, ret);
1888
1889 return ret;
1890 }
1891

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (3.08 kB)
.config.gz (41.13 kB)
Download all attachments