b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -35,6 +35,7 @@ struct ath_node;
struct ath_vif;
extern struct ieee80211_ops ath9k_ops;
+extern struct pci_driver ath_pci_driver;
extern int ath9k_modparam_nohwcrypt;
extern int ath9k_led_blink;
extern bool is_ath9k_unloaded;
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/pci.h>
#include <linux/nvmem-consumer.h>
#include <linux/relay.h>
#include <linux/dmi.h>
@@ -577,6 +578,31 @@ static int ath9k_nvmem_request_eeprom(struct
ath_softc *sc)
size_t len;
int err;
+ /* 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(sc->dev) && ( no OF node || caldata not from node
+ * || not compatible ) -> do not use caldata .
+ *
+ * !dev_is_pci(sc->dev) -> always use caldata .
+ */
+ if (dev_is_pci(sc->dev) &&
+ (!sc->dev->of_node ||
+ !of_property_match_string(sc->dev->of_node,
+ "nvmem-cell-names",
+ "calibration") ||
+ !of_pci_node_match_driver(sc->dev->of_node,
+ &ath_pci_driver)))
+ /* follow the "just return 0;" convention as
+ * noted below.
+ */
+ return 0;
+
cell = devm_nvmem_cell_get(sc->dev, "calibration");
if (IS_ERR(cell)) {
err = PTR_ERR(cell);
b/drivers/net/wireless/ath/ath9k/pci.c
@@ -1074,7 +1074,7 @@ static SIMPLE_DEV_PM_OPS(ath9k_pm_ops,
ath_pci_suspend, ath_pci_resume);
MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
-static struct pci_driver ath_pci_driver = {
+struct pci_driver ath_pci_driver = {
.name = "ath9k",
.id_table = ath_pci_id_table,
.probe = ath_pci_probe,
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/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 26 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/pci.c | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-)