mbox series

[v2,0/6] PCI: Drop duplicated tracking of a pci_dev's bound driver

Message ID 20210803100150.1543597-1-u.kleine-koenig@pengutronix.de
Headers show
Series PCI: Drop duplicated tracking of a pci_dev's bound driver | expand

Message

Uwe Kleine-König Aug. 3, 2021, 10:01 a.m. UTC
Hello,

changes since v1 (https://lore.kernel.org/linux-pci/20210729203740.1377045-1-u.kleine-koenig@pengutronix.de):

- New patch to simplify drivers/pci/xen-pcifront.c, spotted and
  suggested by Boris Ostrovsky
- Fix a possible NULL pointer dereference I introduced in xen-pcifront.c
- A few whitespace improvements
- Add a commit log to patch #6 (formerly #5)

I also expanded the audience for patches #4 and #6 to allow affected
people to actually see the changes to their drivers.

Interdiff can be found below.

The idea is still the same: After a few cleanups (#1 - #3) a new macro
is introduced abstracting access to struct pci_dev->driver. All users
are then converted to use this and in the last patch the macro is
changed to make use of struct pci_dev::dev->driver to get rid of the
duplicated tracking.

Best regards
Uwe

Uwe Kleine-König (6):
  PCI: Simplify pci_device_remove()
  PCI: Drop useless check from pci_device_probe()
  xen/pci: Drop some checks that are always true
  PCI: Provide wrapper to access a pci_dev's bound driver
  PCI: Adapt all code locations to not use struct pci_dev::driver
    directly
  PCI: Drop duplicated tracking of a pci_dev's bound driver

 arch/powerpc/include/asm/ppc-pci.h            |  3 +-
 arch/powerpc/kernel/eeh_driver.c              | 12 ++--
 arch/x86/events/intel/uncore.c                |  2 +-
 arch/x86/kernel/probe_roms.c                  |  2 +-
 drivers/bcma/host_pci.c                       |  6 +-
 drivers/crypto/hisilicon/qm.c                 |  2 +-
 drivers/crypto/qat/qat_common/adf_aer.c       |  2 +-
 drivers/message/fusion/mptbase.c              |  4 +-
 drivers/misc/cxl/guest.c                      | 21 +++----
 drivers/misc/cxl/pci.c                        | 25 ++++----
 .../ethernet/hisilicon/hns3/hns3_ethtool.c    |  2 +-
 .../ethernet/marvell/prestera/prestera_pci.c  |  2 +-
 drivers/net/ethernet/mellanox/mlxsw/pci.c     |  2 +-
 .../ethernet/netronome/nfp/nfp_net_ethtool.c  |  2 +-
 drivers/pci/iov.c                             | 23 ++++---
 drivers/pci/pci-driver.c                      | 48 +++++++--------
 drivers/pci/pci.c                             | 10 ++--
 drivers/pci/pcie/err.c                        | 35 ++++++-----
 drivers/pci/xen-pcifront.c                    | 60 ++++++++-----------
 drivers/ssb/pcihost_wrapper.c                 |  7 ++-
 drivers/usb/host/xhci-pci.c                   |  3 +-
 include/linux/pci.h                           |  2 +-
 22 files changed, 145 insertions(+), 130 deletions(-)

Range-diff against v1:
1:  7d97605df363 = 1:  8ba6e9faa18c PCI: Simplify pci_device_remove()
2:  aec84c688d0f = 2:  d8a7dc52091f PCI: Drop useless check from pci_device_probe()
-:  ------------ > 3:  f4b78aa41776 xen/pci: Drop some checks that are always true
3:  e6f933f532c9 = 4:  50f3daa64170 PCI: Provide wrapper to access a pci_dev's bound driver
4:  d678a2924143 ! 5:  21cbd3f180a1 PCI: Adapt all code locations to not use struct pci_dev::driver directly
    @@ drivers/message/fusion/mptbase.c: mpt_device_driver_register(struct mpt_pci_driv
     -		id = ioc->pcidev->driver ?
     -		    ioc->pcidev->driver->id_table : NULL;
     +		struct pci_driver *pdrv = pci_driver_of_dev(ioc->pcidev);
    -+		id = pdrv ?  pdrv->id_table : NULL;
    ++		id = pdrv ? pdrv->id_table : NULL;
      		if (dd_cbfunc->probe)
      			dd_cbfunc->probe(ioc->pcidev, id);
      	 }
    @@ drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c: static void hns3_get_drvinfo
      	}
      
     -	strncpy(drvinfo->driver, h->pdev->driver->name,
    --		sizeof(drvinfo->driver));
    -+	strncpy(drvinfo->driver, pci_driver_of_dev(h->pdev)->name, sizeof(drvinfo->driver));
    ++	strncpy(drvinfo->driver, pci_driver_of_dev(h->pdev)->name,
    + 		sizeof(drvinfo->driver));
      	drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
      
    - 	strncpy(drvinfo->bus_info, pci_name(h->pdev),
     
      ## drivers/net/ethernet/marvell/prestera/prestera_pci.c ##
     @@ drivers/net/ethernet/marvell/prestera/prestera_pci.c: static int prestera_fw_load(struct prestera_fw *fw)
    @@ drivers/pci/xen-pcifront.c: static pci_ers_result_t pcifront_common_process(int
      
      	pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn);
     -	if (!pcidev || !pcidev->driver) {
    -+	pdrv = pci_driver_of_dev(pcidev);
    -+	if (!pcidev || !pdrv) {
    ++	if (!pcidev || !(pdrv = pci_driver_of_dev(pcidev))) {
      		dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
      		pci_dev_put(pcidev);
      		return result;
      	}
     -	pdrv = pcidev->driver;
      
    - 	if (pdrv) {
    - 		if (pdrv->err_handler && pdrv->err_handler->error_detected) {
    + 	if (pdrv->err_handler && pdrv->err_handler->error_detected) {
    + 		pci_dbg(pcidev, "trying to call AER service\n");
     
      ## drivers/ssb/pcihost_wrapper.c ##
     @@ drivers/ssb/pcihost_wrapper.c: static int ssb_pcihost_probe(struct pci_dev *dev,
    @@ drivers/ssb/pcihost_wrapper.c: static int ssb_pcihost_probe(struct pci_dev *dev,
      	name = dev_name(&dev->dev);
     -	if (dev->driver && dev->driver->name)
     -		name = dev->driver->name;
    -+	
    ++
     +	pdrv = pci_driver_of_dev(dev);
     +	if (pdrv && pdrv->name)
     +		name = pdrv->name;
5:  8c70ffd24380 ! 6:  02e6da6e5919 PCI: Drop duplicated tracking of a pci_dev's bound driver
    @@ Metadata
      ## Commit message ##
         PCI: Drop duplicated tracking of a pci_dev's bound driver
     
    +    Currently it's tracked twice which driver is bound to a given pci
    +    device. Now that all users of the pci specific one (struct
    +    pci_dev::driver) are updated to use an access macro
    +    (pci_driver_of_dev()), change the macro to use the information from the
    +    driver core and remove the driver member from struct pci_dev.
    +
         Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
     
      ## drivers/pci/pci-driver.c ##

base-commit: 2734d6c1b1a089fb593ef6a23d4b70903526fe0c

Comments

Boris Ostrovsky Aug. 3, 2021, 1:53 p.m. UTC | #1
On 8/3/21 6:01 AM, Uwe Kleine-König wrote:
> This prepares removing the driver member of struct pci_dev which holds the
> same information than struct pci_dev::dev->driver.
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  arch/powerpc/include/asm/ppc-pci.h            |  3 +-
>  arch/powerpc/kernel/eeh_driver.c              | 12 ++++---
>  arch/x86/events/intel/uncore.c                |  2 +-
>  arch/x86/kernel/probe_roms.c                  |  2 +-
>  drivers/bcma/host_pci.c                       |  6 ++--
>  drivers/crypto/hisilicon/qm.c                 |  2 +-
>  drivers/crypto/qat/qat_common/adf_aer.c       |  2 +-
>  drivers/message/fusion/mptbase.c              |  4 +--
>  drivers/misc/cxl/guest.c                      | 21 +++++------
>  drivers/misc/cxl/pci.c                        | 25 +++++++------
>  .../ethernet/hisilicon/hns3/hns3_ethtool.c    |  2 +-
>  .../ethernet/marvell/prestera/prestera_pci.c  |  2 +-
>  drivers/net/ethernet/mellanox/mlxsw/pci.c     |  2 +-
>  .../ethernet/netronome/nfp/nfp_net_ethtool.c  |  2 +-
>  drivers/pci/iov.c                             | 23 +++++++-----
>  drivers/pci/pci-driver.c                      | 28 ++++++++-------
>  drivers/pci/pci.c                             | 10 +++---
>  drivers/pci/pcie/err.c                        | 35 ++++++++++---------
>  drivers/pci/xen-pcifront.c                    |  3 +-
>  drivers/ssb/pcihost_wrapper.c                 |  7 ++--
>  drivers/usb/host/xhci-pci.c                   |  3 +-
>  21 files changed, 112 insertions(+), 84 deletions(-)


For Xen bits:

Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Andy Shevchenko Aug. 3, 2021, 2:37 p.m. UTC | #2
On Tue, Aug 03, 2021 at 12:01:48PM +0200, Uwe Kleine-König wrote:
> Which driver a device is bound to is available twice: In struct
> pci_dev::dev->driver and in struct pci_dev::driver. To get rid of the
> duplication introduce a wrapper to access struct pci_dev's driver
> member. Once all users are converted the wrapper can be changed to
> calculate the driver using pci_dev::dev->driver.

...

>  #define	to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
> +#define pci_driver_of_dev(pdev) ((pdev)->driver)

Seems like above is (mis)using TAB instead of space after #define. Not sure if
it's good to have them different.
Andrew Donnellan Aug. 5, 2021, 3:09 p.m. UTC | #3
On 3/8/21 8:01 pm, Uwe Kleine-König wrote:
> This prepares removing the driver member of struct pci_dev which holds the
> same information than struct pci_dev::dev->driver.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

cxl hunks look alright.

Acked-by: Andrew Donnellan <ajd@linux.ibm.com> # cxl
Bjorn Helgaas Aug. 5, 2021, 11:42 p.m. UTC | #4
On Tue, Aug 03, 2021 at 12:01:44PM +0200, Uwe Kleine-König wrote:
> Hello,
> 
> changes since v1 (https://lore.kernel.org/linux-pci/20210729203740.1377045-1-u.kleine-koenig@pengutronix.de):
> 
> - New patch to simplify drivers/pci/xen-pcifront.c, spotted and
>   suggested by Boris Ostrovsky
> - Fix a possible NULL pointer dereference I introduced in xen-pcifront.c
> - A few whitespace improvements
> - Add a commit log to patch #6 (formerly #5)
> 
> I also expanded the audience for patches #4 and #6 to allow affected
> people to actually see the changes to their drivers.
> 
> Interdiff can be found below.
> 
> The idea is still the same: After a few cleanups (#1 - #3) a new macro
> is introduced abstracting access to struct pci_dev->driver. All users
> are then converted to use this and in the last patch the macro is
> changed to make use of struct pci_dev::dev->driver to get rid of the
> duplicated tracking.

I love the idea of this series!

I looked at all the bus_type.probe() methods, it looks like pci_dev is
not the only offender here.  At least the following also have a driver
pointer in the device struct:

  parisc_device.driver
  acpi_device.driver
  dio_dev.driver
  hid_device.driver
  pci_dev.driver
  pnp_dev.driver
  rio_dev.driver
  zorro_dev.driver

Do you plan to do the same for all of them, or is there some reason
why they need the pointer and PCI doesn't?

In almost all cases, other buses define a "to_<bus>_driver()"
interface.  In fact, PCI already has a to_pci_driver().

This series adds pci_driver_of_dev(), which basically just means we
can do this:

  pdrv = pci_driver_of_dev(pdev);

instead of this:

  pdrv = to_pci_driver(pdev->dev.driver);

I don't see any other "<bus>_driver_of_dev()" interfaces, so I assume
other buses just live with the latter style?  I'd rather not be
different and have two ways to get the "struct pci_driver *" unless
there's a good reason.

Looking through the places that care about pci_dev.driver (the ones
updated by patch 5/6), many of them are ... a little dubious to begin
with.  A few need the "struct pci_error_handlers *err_handler"
pointer, so that's probably legitimate.  But many just need a name,
and should probably be using dev_driver_string() instead.

Bjorn