On Wed, 2023-06-07 at 09:49 +0200, Lukas Wunner wrote: > On Mon, Jun 05, 2023 at 08:35:45PM +0200, Johannes Berg wrote: > > @@ -3139,6 +3139,7 @@ void pci_pm_init(struct pci_dev *dev) > > u16 pmc; > > > > pm_runtime_forbid(&dev->dev); > > + pm_runtime_get_noresume(&dev->dev); > > pm_runtime_set_active(&dev->dev); > > pm_runtime_enable(&dev->dev); > > device_enable_async_suspend(&dev->dev); > > @@ -335,9 +336,12 @@ void pci_bus_add_device(struct pci_dev *dev) > > int retval; > > > > /* > > - * Can not put in pci_device_add yet because resources > > - * are not assigned yet for some devices. > > + * Allow runtime PM only here, since otherwise we may > > + * try to suspend a device that isn't fully configured > > + * yet, which causes problems. > > */ > > + pm_runtime_put_noidle(&dev->dev); > > + > > pcibios_bus_add_device(dev); > > pci_fixup_device(pci_fixup_final, dev); > > pci_create_sysfs_dev_files(dev); > > There seem to be many different callers that end up in pci_pm_init() > and pci_bus_add_device(). > > Is it guaranteed that the two functions are always called in order? > Do callers exist which only invoke the former but not the latter or > vice-versa? Can it happen that a caller of the former errors out, > so the latter is never called, leading to a runtime PM ref imbalance? I did ask myself that too, and honestly, I'm not entirely sure - need somebody more familiar to really understand that, I think. Most places elsewhere _do_ call both, and it feels like you have to call both if you want to do something with the device. However there are a few places that seem to call the first part and then remove the device again immediately after. That also seems harmless though. > It would be easier to ascertain correctness if you could find a > function at a higher level which (indirectly) calls both pci_pm_init() > and pci_bus_add_device() so that you can acquire and release the > runtimw PM ref in that single function. > Unfortunately, there isn't such a place, since the scanning is done by various bus walks. johannes