Re: [PATCH v6 00/11] PCI: Drop duplicated tracking of a pci_dev's bound driver
From: Bjorn Helgaas <helgaas@kernel.org>
Date: 2021-10-13 11:34:03
Also in:
linux-pci, linux-perf-users, linux-scsi, linux-usb, linux-wireless, linuxppc-dev, lkml, netdev, xen-devel
On Wed, Oct 13, 2021 at 12:26:42PM +0300, Andy Shevchenko wrote:
On Wed, Oct 13, 2021 at 2:33 AM Bjorn Helgaas [off-list ref] wrote:quoted
On Mon, Oct 04, 2021 at 02:59:24PM +0200, Uwe Kleine-König wrote:quoted
I split some of the bigger patches apart so they only touched one driver or subsystem at a time. I also updated to_pci_driver() so it returns NULL when given NULL, which makes some of the validations quite a bit simpler, especially in the PM code in pci-driver.c.It's a bit unusual. Other to_*_dev() are not NULL-aware IIRC.
It is a little unusual. I only found three of 77 that are NULL-aware:
to_moxtet_driver()
to_siox_driver()
to_spi_driver()
It seems worthwhile to me because it makes the patch and the resulting
code significantly cleaner. Here's one example without the NULL
check:
@@ -493,12 +493,15 @@ static void pci_device_remove(struct device *dev)
static void pci_device_shutdown(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
pm_runtime_resume(dev);
- if (drv && drv->shutdown)
- drv->shutdown(pci_dev);
+ if (pci_dev->dev.driver) {
+ struct pci_driver *drv = to_pci_driver(pci_dev->dev.driver);
+
+ if (drv->shutdown)
+ drv->shutdown(pci_dev);
+ }
static void pci_device_shutdown(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
pm_runtime_resume(dev);
if (pci_dev->dev.driver) {
struct pci_driver *drv = to_pci_driver(pci_dev->dev.driver);
if (drv->shutdown)
drv->shutdown(pci_dev);
}
and here's the same thing with the NULL check:
@@ -493,7 +493,7 @@ static void pci_device_remove(struct device *dev)
static void pci_device_shutdown(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct pci_driver *drv = to_pci_driver(dev->driver);
static void pci_device_shutdown(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *drv = to_pci_driver(dev->driver);
pm_runtime_resume(dev);
if (drv && drv->shutdown)
drv->shutdown(pci_dev);
quoted
static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short device) { + struct pci_driver *drv = to_pci_driver(pdev->dev.driver); const struct pci_device_id *id; if (pdev->vendor == vendor && pdev->device == device) return true;quoted
+ for (id = drv ? drv->id_table : NULL; id && id->vendor; id++) + if (id->vendor == vendor && id->device == device)quoted
+ break;return true;quoted
return id && id->vendor;return false;
Good cleanup for a follow-up patch, but doesn't seem directly related
to the objective here. The current patch is:
@@ -80,7 +80,7 @@ static struct resource video_rom_resource = {
*/
static bool match_id(struct pci_dev *pdev, unsigned short vendor, unsigned short device)
{
- struct pci_driver *drv = pdev->driver;
+ struct pci_driver *drv = to_pci_driver(pdev->dev.driver);
const struct pci_device_id *id;
if (pdev->vendor == vendor && pdev->device == device)
quoted
device_lock(&vf_dev->dev); - if (vf_dev->dev.driver) { + if (to_pci_driver(vf_dev->dev.driver)) {Hmm...
Yeah, it could be either of: if (to_pci_driver(vf_dev->dev.driver)) if (vf_dev->dev.driver) I went back and forth on that and went with to_pci_driver() on the theory that we were testing the pci_driver * before and the patch is more of a mechanical change and easier to review if we test the pci_driver * after.
quoted
+ if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0quoted
+ && pci_dev->current_state != PCI_UNKNOWN) {Can we keep && on the previous line?
I think this is in pci_legacy_suspend(), and I didn't touch that line. It shows up in the interdiff because without the NULL check in to_pci_driver(), we had to indent this code another level. With the NULL check, we don't need that extra indentation.
quoted
+ pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, + "PCI PM: Device state not saved by %pS\n", + drv->suspend); }...quoted
+ return drv && drv->resume ? + drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev);One line?
I don't think I touched that line.
quoted
+ struct pci_driver *drv = to_pci_driver(dev->dev.driver); const struct pci_error_handlers *err_handler = - dev->dev.driver ? to_pci_driver(dev->dev.driver)->err_handler : NULL; + drv ? drv->err_handler : NULL;Isn't dev->driver == to_pci_driver(dev->dev.driver)?
Yes, I think so, but not sure what you're getting at here, can you elaborate?
quoted
device_lock(&dev->dev); + pdrv = to_pci_driver(dev->dev.driver); if (!pci_dev_set_io_state(dev, state) || - !dev->dev.driver || - !(pdrv = to_pci_driver(dev->dev.driver))->err_handler ||quoted
+ !pdrv || + !pdrv->err_handler ||One line now?quoted
!pdrv->err_handler->error_detected) {Or this and the previous line?
Could, but the "dev->driver" to "to_pci_driver(dev->dev.driver)" changes are the heart of this patch, and I don't like to clutter it with unrelated changes.
quoted
- result = PCI_ERS_RESULT_NONE; pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn); if (!pcidev || !pcidev->dev.driver) { dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); pci_dev_put(pcidev); - return result; + return PCI_ERS_RESULT_NONE; } pdrv = to_pci_driver(pcidev->dev.driver);What about splitting the conditional to two with clear error message in each and use pci_err() in the second one?
Could possibly be cleaned up. Felt like feature creep so I didn't.
quoted
default: dev_err(&pdev->xdev->dev, - "bad request in aer recovery " - "operation!\n"); + "bad request in AER recovery operation!\n");Stray change? Or is it in a separate patch in your tree?
Could be skipped. The string now fits on one line so I combined it to make it more greppable. Bjorn