diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2021-11-10 12:03:34 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2021-11-11 13:36:22 -0600 |
commit | e0217c5ba10d7bf640f038b2feae58e630f2f958 (patch) | |
tree | d7899667bdfeea595319549c90a184ecf5849490 /drivers/pci/pci.c | |
parent | 68da4e0eaaab421f228eac57cbe7505b136464af (diff) |
Revert "PCI: Use to_pci_driver() instead of pci_dev->driver"
This reverts commit 2a4d9408c9e8b6f6fc150c66f3fef755c9e20d4a.
Robert reported a NULL pointer dereference caused by the PCI core
(local_pci_probe()) calling the i2c_designware_pci driver's
.runtime_resume() method before the .probe() method. i2c_dw_pci_resume()
depends on initialization done by i2c_dw_pci_probe().
Prior to 2a4d9408c9e8 ("PCI: Use to_pci_driver() instead of
pci_dev->driver"), pci_pm_runtime_resume() avoided calling the
.runtime_resume() method because pci_dev->driver had not been set yet.
2a4d9408c9e8 and b5f9c644eb1b ("PCI: Remove struct pci_dev->driver"),
removed pci_dev->driver, replacing it by device->driver, which *has* been
set by this time, so pci_pm_runtime_resume() called the .runtime_resume()
method when it previously had not.
Fixes: 2a4d9408c9e8 ("PCI: Use to_pci_driver() instead of pci_dev->driver")
Link: https://lore.kernel.org/linux-i2c/CAP145pgdrdiMAT7=-iB1DMgA7t_bMqTcJL4N0=6u8kNY3EU0dw@mail.gmail.com/
Reported-by: Robert Święcki <robert@swiecki.net>
Tested-by: Robert Święcki <robert@swiecki.net>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 17 |
1 files changed, 8 insertions, 9 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b88db815ee01..40012d13c3c4 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5123,14 +5123,13 @@ EXPORT_SYMBOL_GPL(pci_dev_unlock); static void pci_dev_save_and_disable(struct pci_dev *dev) { - struct pci_driver *drv = to_pci_driver(dev->dev.driver); const struct pci_error_handlers *err_handler = - drv ? drv->err_handler : NULL; + dev->driver ? dev->driver->err_handler : NULL; /* - * drv->err_handler->reset_prepare() is protected against races - * with ->remove() by the device lock, which must be held by the - * caller. + * dev->driver->err_handler->reset_prepare() is protected against + * races with ->remove() by the device lock, which must be held by + * the caller. */ if (err_handler && err_handler->reset_prepare) err_handler->reset_prepare(dev); @@ -5155,15 +5154,15 @@ static void pci_dev_save_and_disable(struct pci_dev *dev) static void pci_dev_restore(struct pci_dev *dev) { - struct pci_driver *drv = to_pci_driver(dev->dev.driver); const struct pci_error_handlers *err_handler = - drv ? drv->err_handler : NULL; + dev->driver ? dev->driver->err_handler : NULL; pci_restore_state(dev); /* - * drv->err_handler->reset_done() is protected against races with - * ->remove() by the device lock, which must be held by the caller. + * dev->driver->err_handler->reset_done() is protected against + * races with ->remove() by the device lock, which must be held by + * the caller. */ if (err_handler && err_handler->reset_done) err_handler->reset_done(dev); |