b/drivers/net/wireless/ath/ath10k/core.c
@@ -26,6 +26,7 @@
#include "testmode.h"
#include "wmi-ops.h"
#include "coredump.h"
+#include "pci.h"
unsigned int ath10k_debug_mask;
EXPORT_SYMBOL(ath10k_debug_mask);
@@ -1958,6 +1959,33 @@ static int ath10k_download_cal_nvmem(struct
ath10k *ar, const char *cell_name)
size_t len;
int ret;
+ /* devm_nvmem_cell_get() will get a cell first from the OF
+ * DT node representing the given device with nvmem-cell-name
+ * "calibration", and from the global lookup table as a fallback,
+ * and an ath9k device could be either a pci one or a platform one.
+ *
+ * If the OF DT node is not compatible with the real device, the
+ * calibration data got from the node should not be applied.
+ *
+ * dev_is_pci(ar->dev) && ( no OF node || caldata not from node
+ * || not compatible ) -> do not use caldata .
+ *
+ * !dev_is_pci(ar->dev) -> always use caldata .
+ *
+ * The judgement for compatibility differs with ath9k for many
+ * DT using "qcom,ath10k" as compatibility string.
+ */
+ if (dev_is_pci(ar->dev) &&
+ (!ar->dev->of_node ||
+ (of_property_match_string(ar->dev->of_node,
+ "nvmem-cell-names",
+ cell_name) < 0) ||
+ !of_device_is_compatible(ar->dev->of_node,
+ "qcom,ath10k") ||
+ !of_pci_node_match_device(ar->dev->of_node,
+ &ath10k_pci_driver)))
+ return ERR_PTR(-ENOENT);
+
cell = devm_nvmem_cell_get(ar->dev, cell_name);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);
b/drivers/net/wireless/ath/ath10k/pci.c
@@ -3780,7 +3780,7 @@ static SIMPLE_DEV_PM_OPS(ath10k_pci_pm_ops,
ath10k_pci_pm_suspend,
ath10k_pci_pm_resume);
-static struct pci_driver ath10k_pci_driver = {
+struct pci_driver ath10k_pci_driver = {
.name = "ath10k_pci",
.id_table = ath10k_pci_id_table,
.probe = ath10k_pci_probe,
b/drivers/net/wireless/ath/ath10k/pci.h
@@ -209,6 +209,8 @@ static inline struct ath10k_pci
*ath10k_pci_priv(struct ath10k *ar)
#define DIAG_ACCESS_CE_TIMEOUT_US 10000 /* 10 ms */
#define DIAG_ACCESS_CE_WAIT_US 50
+extern struct pci_driver ath10k_pci_driver;
+
void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value);
void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val);
void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val);
Loading calibration data from an OF device tree node not declared compatible with the device (e.g. a PCI device with calibration data from corresponding DT node gets replaced, so the newly installed device become incompatible with the node) or driver may lead to fatal result, e.g. kernel panic. The driver should check whether the DT node corresponding to the device compatible with it, and load calibration data only from compatible node. Signed-off-by: Edward Chow <equu@openmail.cc> --- drivers/net/wireless/ath/ath10k/core.c | 28 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/pci.c | 2 +- drivers/net/wireless/ath/ath10k/pci.h | 2 ++ 3 files changed, 31 insertions(+), 1 deletion(-)