mbox series

[v5,0/3] PCI: of: Load extra data only from compatible DT nodes

Message ID 20230203104822.361415-1-equu@openmail.cc
Headers show
Series PCI: of: Load extra data only from compatible DT nodes | expand

Message

Mad Horse Feb. 3, 2023, 10:48 a.m. UTC
From: Edward Chow <equu@openmail.cc>

In order to solve the issue reported in
https://github.com/openwrt/openwrt/pull/11345 , this patchset attempt
to add mechanisms to ckeck whether an OF DT node is compatible to the
PCI device installed on the corresponding location or the driver for
it, and make ath9k and ath10k only load extra data from compatible
nodes.

V4 -> V5:
2, include <linux/pci.h> in ath9k/pci.c.

3, include <linux/pci.h> in ath10k/core.c.

Signed-off-by: Edward Chow <equu@openmail.cc>
Reported-by: kernel test robot <lkp@intel.com>

Edward Chow (3):
  PCI: of: Match pci devices or drivers against OF DT nodes
  wifi: ath9k: stop loading incompatible DT cal data
  wifi: ath10k: only load compatible DT cal data

 drivers/net/wireless/ath/ath10k/core.c |  30 +++
 drivers/net/wireless/ath/ath10k/pci.c  |   2 +-
 drivers/net/wireless/ath/ath10k/pci.h  |   2 +
 drivers/net/wireless/ath/ath9k/ath9k.h |   1 +
 drivers/net/wireless/ath/ath9k/init.c  |  27 +++
 drivers/net/wireless/ath/ath9k/pci.c   |   2 +-
 drivers/pci/of.c                       | 299 +++++++++++++++++++++++++
 drivers/pci/pci-driver.c               |   5 -
 drivers/pci/pci.h                      |  56 +++++
 include/linux/of_pci.h                 |  25 +++
 include/linux/pci.h                    |   6 +
 11 files changed, 448 insertions(+), 7 deletions(-)

Comments

Rob Herring (Arm) Feb. 3, 2023, 3:57 p.m. UTC | #1
On Fri, Feb 3, 2023 at 4:48 AM <equu@openmail.cc> wrote:
>
> From: Edward Chow <equu@openmail.cc>
>
> ath10k might also be sensitive to the issue reported on
> https://github.com/openwrt/openwrt/pull/11345 , loading calibration
> data from a device tree node declared incompatible.
>
> ath10k will first check whether the device tree node is compatible
> with it, using the functionality introduced with the first patch of
> this series, ("PCI: of: Match pci devices or drivers against OF DT
> nodes") and only proceed loading calibration data from compatible node.
>
> Signed-off-by: Edward Chow <equu@openmail.cc>
> Reported-by: kernel test robot <lkp@intel.com>
> ---
>  drivers/net/wireless/ath/ath10k/core.c | 30 ++++++++++++++++++++++++++
>  drivers/net/wireless/ath/ath10k/pci.c  |  2 +-
>  drivers/net/wireless/ath/ath10k/pci.h  |  2 ++
>  3 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
> index 5eb131ab916f..a776b06f49b5 100644
> --- a/drivers/net/wireless/ath/ath10k/core.c
> +++ b/drivers/net/wireless/ath/ath10k/core.c
> @@ -13,6 +13,8 @@
>  #include <linux/ctype.h>
>  #include <linux/pm_qos.h>
>  #include <linux/nvmem-consumer.h>
> +#include <linux/of_pci.h>
> +#include <linux/pci.h>
>  #include <asm/byteorder.h>
>
>  #include "core.h"
> @@ -26,6 +28,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 +1961,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 ath10k 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_driver(ar->dev->of_node,
> +                                      &ath10k_pci_driver)))
> +               return -ENOENT;

I think this can be done a bit cleaner and like other drivers. I see 2 options.

The first way is use VID/PID compatible strings and don't set the
of_node pointer if there is a mismatch.

If you must use "qcom,ath10k" (and 9k) only, then we should make
of_device_get_match_data() work on PCI drivers. This should just
require adding of_match_table ptr and it needs a data struct with a
flag saying use cal data or not.

Upon further thought, why can't you decide all this just on PCI
VID/PID? The giant switch statement in ath10k_pci_probe() could all
just be struct of driver_data from the PCI match table.

Rob
Rob Herring (Arm) Feb. 3, 2023, 6:45 p.m. UTC | #2
On Fri, Feb 3, 2023 at 11:15 AM <equu@openmail.cc> wrote:
>
> > I think this can be done a bit cleaner and like other drivers. I see 2 options.
> > The first way is use VID/PID compatible strings and don't set the
> > of_node pointer if there is a mismatch.
> Where should I do this? In pci_set_of_node() from drivers/pci/of.c?

Off the top of my head, I think so.

> > Upon further thought, why can't you decide all this just on PCI
> > VID/PID? The giant switch statement in ath10k_pci_probe() could all
> > just be struct of driver_data from the PCI match table.
>
> I cannot decide all this just on PCI VID/PID because PCI VID/PID cannot tell whether calibration data are stored in the device (like most expansion cards) or not (for example, in an NVRAM cell referenced by the device tree).
>

For a given VID/PID, you could have calibration data in DT that you
want to ignore sometimes and not other times (because the compatible
is wrong)?

Rob
Mad Horse Feb. 4, 2023, 4:26 a.m. UTC | #3
>
>>> Upon further thought, why can't you decide all this just on PCI
>>> VID/PID? The giant switch statement in ath10k_pci_probe() could all
>>> just be struct of driver_data from the PCI match table.
>> I cannot decide all this just on PCI VID/PID because PCI VID/PID cannot tell whether calibration data are stored in the device (like most expansion cards) or not (for example, in an NVRAM cell referenced by the device tree).
>>
> For a given VID/PID, you could have calibration data in DT that you
> want to ignore sometimes and not other times (because the compatible
> is wrong)?

Some devices will change their VID/PID after applied with calibration data (e.g. AR922X will do 168c:ff1d -> 168c:0029), but most device trees only record their post-calibration VID/PID in their compatibility string.

Should we match such device against their pre-calibration VID/PID only, and break all current device trees for them?

I think we could add these pre-calibration VID/PIDs to the ID-list of the PCI driver, but had better match compatibility strings against drivers, not devices.