diff options
author | Christian Lamparter <chunkeey@gmail.com> | 2021-08-21 00:32:31 +0200 |
---|---|---|
committer | Christian Lamparter <chunkeey@gmail.com> | 2021-11-06 16:40:48 +0100 |
commit | d91318662d5c290ce97bfb18c84e4cddc514f33a (patch) | |
tree | 84a5b39f6652d88c44f8f3a478f654ed02838e36 /package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch | |
parent | 30b0bd69fd57d6179d1d8825710d3bf2a40bd98b (diff) | |
download | upstream-d91318662d5c290ce97bfb18c84e4cddc514f33a.tar.gz upstream-d91318662d5c290ce97bfb18c84e4cddc514f33a.tar.bz2 upstream-d91318662d5c290ce97bfb18c84e4cddc514f33a.zip |
ath9k: nvmem for ath9k caldata
With "getting WIFI MAC from NVMEM" working on ath79 on 5.10,
the next logical step I think is to utilize nvmem subsystem
to also get the calibration data from there.
This will tremendously speed up the wifi bring-up, since
we no longer need the userspace helper for the simple
devices that can just load them from there.
included with this patch is a package/mac80211/refresh.
Tested on: WNDR3700v2, TP-Link Archer C7v2
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Diffstat (limited to 'package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch')
-rw-r--r-- | package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch b/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch new file mode 100644 index 0000000000..a250d2318e --- /dev/null +++ b/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch @@ -0,0 +1,154 @@ +From dab16ef495dbb3cabb355b6c80f0771a4a25e35d Mon Sep 17 00:00:00 2001 +From: Christian Lamparter <chunkeey@gmail.com> +Date: Fri, 20 Aug 2021 22:44:52 +0200 +Subject: [PATCH] ath9k: fetch calibration data via nvmem subsystem + +On most embedded ath9k devices (like range extenders, +routers, accesspoints, ...) the calibration data is +stored in a MTD partitions named "ART", or "caldata"/ +"calibration". + +Ever since commit +4b361cfa8624 ("mtd: core: add OTP nvmem provider support") +all MTD partitions are all automatically available through +the nvmem subsystem. This allows drivers like ath9k to read +the necessary data without needing any userspace helpers +that would do this extraction. + +Signed-off-by: Christian Lamparter <chunkeey@gmail.com> +--- + +includes: + +From 57671351379b2051cfb07fc14e0bead9916a0880 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Mon, 11 Oct 2021 18:18:01 +0300 +Subject: ath9k: fix an IS_ERR() vs NULL check + +The devm_kmemdup() function doesn't return error pointers, it returns +NULL on error. + +Fixes: eb3a97a69be8 ("ath9k: fetch calibration data via nvmem subsystem") +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +Link: https://lore.kernel.org/r/20211011123533.GA15188@kili + +--- + +--- a/drivers/net/wireless/ath/ath9k/eeprom.c ++++ b/drivers/net/wireless/ath/ath9k/eeprom.c +@@ -135,13 +135,23 @@ static bool ath9k_hw_nvram_read_firmware + offset, data); + } + ++static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset, ++ u16 *data) ++{ ++ return ath9k_hw_nvram_read_array(ah->nvmem_blob, ++ ah->nvmem_blob_len / sizeof(u16), ++ offset, data); ++} ++ + bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) + { + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_platform_data *pdata = ah->dev->platform_data; + bool ret; + +- if (ah->eeprom_blob) ++ if (ah->nvmem_blob) ++ ret = ath9k_hw_nvram_read_nvmem(ah, off, data); ++ else if (ah->eeprom_blob) + ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data); + else if (pdata && !pdata->use_eeprom) + ret = ath9k_hw_nvram_read_pdata(pdata, off, data); +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -988,6 +988,8 @@ struct ath_hw { + bool disable_5ghz; + + const struct firmware *eeprom_blob; ++ u16 *nvmem_blob; /* devres managed */ ++ size_t nvmem_blob_len; + + struct ath_dynack dynack; + +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -22,6 +22,7 @@ + #include <linux/module.h> + #include <linux/of.h> + #include <linux/of_net.h> ++#include <linux/nvmem-consumer.h> + #include <linux/relay.h> + #include <linux/dmi.h> + #include <net/ieee80211_radiotap.h> +@@ -568,6 +569,57 @@ static void ath9k_eeprom_release(struct + release_firmware(sc->sc_ah->eeprom_blob); + } + ++static int ath9k_nvmem_request_eeprom(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ struct nvmem_cell *cell; ++ void *buf; ++ size_t len; ++ int err; ++ ++ cell = devm_nvmem_cell_get(sc->dev, "calibration"); ++ if (IS_ERR(cell)) { ++ err = PTR_ERR(cell); ++ ++ /* nvmem cell might not be defined, or the nvmem ++ * subsystem isn't included. In this case, follow ++ * the established "just return 0;" convention of ++ * ath9k_init_platform to say: ++ * "All good. Nothing to see here. Please go on." ++ */ ++ if (err == -ENOENT || err == -EOPNOTSUPP) ++ return 0; ++ ++ return err; ++ } ++ ++ buf = nvmem_cell_read(cell, &len); ++ if (IS_ERR(buf)) ++ return PTR_ERR(buf); ++ ++ /* run basic sanity checks on the returned nvram cell length. ++ * That length has to be a multiple of a "u16" (i.e.: & 1). ++ * Furthermore, it has to be more than "let's say" 512 bytes ++ * but less than the maximum of AR9300_EEPROM_SIZE (16kb). ++ */ ++ if (((len & 1) == 1) || (len < 512) || (len >= AR9300_EEPROM_SIZE)) { ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ /* devres manages the calibration values release on shutdown */ ++ ah->nvmem_blob = (u16 *)devm_kmemdup(sc->dev, buf, len, GFP_KERNEL); ++ kfree(buf); ++ if (!ah->nvmem_blob) ++ return -ENOMEM; ++ ++ ah->nvmem_blob_len = len; ++ ah->ah_flags &= ~AH_USE_EEPROM; ++ ah->ah_flags |= AH_NO_EEP_SWAP; ++ ++ return 0; ++} ++ + static int ath9k_init_platform(struct ath_softc *sc) + { + struct ath9k_platform_data *pdata = sc->dev->platform_data; +@@ -710,6 +762,10 @@ static int ath9k_init_softc(u16 devid, s + if (ret) + return ret; + ++ ret = ath9k_nvmem_request_eeprom(sc); ++ if (ret) ++ return ret; ++ + if (ath9k_led_active_high != -1) + ah->config.led_active_high = ath9k_led_active_high == 1; + |