aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/ath9k/600-v5.16-ath9k-fetch-calibration-data-via-nvmem-subsystem.patch
diff options
context:
space:
mode:
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.patch154
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;
+