* [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities @ 2025-06-24 17:16 Sean Christopherson 2025-06-25 16:32 ` Vipin Sharma 2025-06-25 23:03 ` Bjorn Helgaas 0 siblings, 2 replies; 5+ messages in thread From: Sean Christopherson @ 2025-06-24 17:16 UTC (permalink / raw) To: Bjorn Helgaas Cc: linux-pci, linux-kernel, David Matlack, Vipin Sharma, Aaron Lewis, Sean Christopherson Query support for Immediate Readiness irrespective of whether or not the device supports PM capabilities, as nothing in the PCIe spec suggests that Immediate Readiness is in any way dependent on PM functionality. Opportunistically add a comment to explain why "errors" during PM setup are effectively ignored. Fixes: d6112f8def51 ("PCI: Add support for Immediate Readiness") Cc: David Matlack <dmatlack@google.com> Cc: Vipin Sharma <vipinsh@google.com> Cc: Aaron Lewis <aaronlewis@google.com> Signed-off-by: Sean Christopherson <seanjc@google.com> --- RFC as I'm not entirely sure this is useful/correct. Found by inspection when debugging a VFIO VF passthrough issue that turned out to be 907a7a2e5bf4 ("PCI/PM: Set up runtime PM even for devices without PCI PM"). The folks on the Cc list are looking at parallelizing VF assignment to avoid serializing the 100ms wait on FLR. I'm hoping we'll get lucky and the VFs in question do (or can) support PCI_STATUS_IMM_READY. drivers/pci/pci.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9e42090fb108..cd91adbf0269 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3198,33 +3198,22 @@ void pci_pm_power_up_and_verify_state(struct pci_dev *pci_dev) pci_update_current_state(pci_dev, PCI_D0); } -/** - * pci_pm_init - Initialize PM functions of given PCI device - * @dev: PCI device to handle. - */ -void pci_pm_init(struct pci_dev *dev) +static void __pci_pm_init(struct pci_dev *dev) { int pm; - u16 status; u16 pmc; - device_enable_async_suspend(&dev->dev); - dev->wakeup_prepared = false; - - dev->pm_cap = 0; - dev->pme_support = 0; - /* find PCI PM capability in list */ pm = pci_find_capability(dev, PCI_CAP_ID_PM); if (!pm) - goto poweron; + return; /* Check device's ability to generate PME# */ pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { pci_err(dev, "unsupported PM cap regs version (%u)\n", pmc & PCI_PM_CAP_VER_MASK); - goto poweron; + return; } dev->pm_cap = pm; @@ -3265,11 +3254,32 @@ void pci_pm_init(struct pci_dev *dev) /* Disable the PME# generation functionality */ pci_pme_active(dev, false); } +} + +/** + * pci_pm_init - Initialize PM functions of given PCI device + * @dev: PCI device to handle. + */ +void pci_pm_init(struct pci_dev *dev) +{ + u16 status; + + device_enable_async_suspend(&dev->dev); + dev->wakeup_prepared = false; + + dev->pm_cap = 0; + dev->pme_support = 0; + + /* + * Note, support for the PCI PM spec is optional for legacy PCI devices + * and for VFs. Continue on even if no PM capabilities are supported. + */ + __pci_pm_init(dev); pci_read_config_word(dev, PCI_STATUS, &status); if (status & PCI_STATUS_IMM_READY) dev->imm_ready = 1; -poweron: + pci_pm_power_up_and_verify_state(dev); pm_runtime_forbid(&dev->dev); pm_runtime_set_active(&dev->dev); base-commit: 86731a2a651e58953fc949573895f2fa6d456841 -- 2.50.0.714.g196bf9f422-goog ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities 2025-06-24 17:16 [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities Sean Christopherson @ 2025-06-25 16:32 ` Vipin Sharma 2025-06-25 23:03 ` Bjorn Helgaas 1 sibling, 0 replies; 5+ messages in thread From: Vipin Sharma @ 2025-06-25 16:32 UTC (permalink / raw) To: Sean Christopherson Cc: Bjorn Helgaas, linux-pci, linux-kernel, David Matlack, Aaron Lewis On 2025-06-24 10:16:37, Sean Christopherson wrote: > Query support for Immediate Readiness irrespective of whether or not the > device supports PM capabilities, as nothing in the PCIe spec suggests that > Immediate Readiness is in any way dependent on PM functionality. After reading spec I also arrived at the same conclusion, this can be done irrespective of PM functionality. For example, wait after FLR behavior which are done using PCI Express Capability is also covered by this Immediate Readiness bit. > > Opportunistically add a comment to explain why "errors" during PM setup > are effectively ignored. > > Fixes: d6112f8def51 ("PCI: Add support for Immediate Readiness") > Cc: David Matlack <dmatlack@google.com> > Cc: Vipin Sharma <vipinsh@google.com> > Cc: Aaron Lewis <aaronlewis@google.com> > Signed-off-by: Sean Christopherson <seanjc@google.com> > --- > > RFC as I'm not entirely sure this is useful/correct. > > Found by inspection when debugging a VFIO VF passthrough issue that turned out > to be 907a7a2e5bf4 ("PCI/PM: Set up runtime PM even for devices without PCI PM"). > > The folks on the Cc list are looking at parallelizing VF assignment to avoid > serializing the 100ms wait on FLR. I'm hoping we'll get lucky and the VFs in > question do (or can) support PCI_STATUS_IMM_READY. > > drivers/pci/pci.c | 40 +++++++++++++++++++++++++--------------- > 1 file changed, 25 insertions(+), 15 deletions(-) > > +void pci_pm_init(struct pci_dev *dev) > +{ > + u16 status; > + > + device_enable_async_suspend(&dev->dev); > + dev->wakeup_prepared = false; > + > + dev->pm_cap = 0; > + dev->pme_support = 0; > + > + /* > + * Note, support for the PCI PM spec is optional for legacy PCI devices > + * and for VFs. Continue on even if no PM capabilities are supported. > + */ > + __pci_pm_init(dev); > > pci_read_config_word(dev, PCI_STATUS, &status); > if (status & PCI_STATUS_IMM_READY) > dev->imm_ready = 1; I don't see a reason to keep it in pci_pm_init then. This should be moved out of this function, maybe in the caller or its own function. > -poweron: > + > pci_pm_power_up_and_verify_state(dev); > pm_runtime_forbid(&dev->dev); > pm_runtime_set_active(&dev->dev); > > base-commit: 86731a2a651e58953fc949573895f2fa6d456841 > -- > 2.50.0.714.g196bf9f422-goog > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities 2025-06-24 17:16 [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities Sean Christopherson 2025-06-25 16:32 ` Vipin Sharma @ 2025-06-25 23:03 ` Bjorn Helgaas 2025-06-26 22:17 ` Sean Christopherson 1 sibling, 1 reply; 5+ messages in thread From: Bjorn Helgaas @ 2025-06-25 23:03 UTC (permalink / raw) To: Sean Christopherson Cc: Bjorn Helgaas, linux-pci, linux-kernel, David Matlack, Vipin Sharma, Aaron Lewis On Tue, Jun 24, 2025 at 10:16:37AM -0700, Sean Christopherson wrote: > Query support for Immediate Readiness irrespective of whether or not the > device supports PM capabilities, as nothing in the PCIe spec suggests that > Immediate Readiness is in any way dependent on PM functionality. Huh, I forgot that we had support for Immediate Readiness at all. I agree, Immediate Readiness has nothing to do with PM except that we take advantage of it in a PM path, and I think pci_pm_init() was probably not the best place to put this. > Opportunistically add a comment to explain why "errors" during PM setup > are effectively ignored. > > Fixes: d6112f8def51 ("PCI: Add support for Immediate Readiness") > Cc: David Matlack <dmatlack@google.com> > Cc: Vipin Sharma <vipinsh@google.com> > Cc: Aaron Lewis <aaronlewis@google.com> > Signed-off-by: Sean Christopherson <seanjc@google.com> > --- > > RFC as I'm not entirely sure this is useful/correct. > > Found by inspection when debugging a VFIO VF passthrough issue that turned out > to be 907a7a2e5bf4 ("PCI/PM: Set up runtime PM even for devices without PCI PM"). > > The folks on the Cc list are looking at parallelizing VF assignment to avoid > serializing the 100ms wait on FLR. I'm hoping we'll get lucky and the VFs in > question do (or can) support PCI_STATUS_IMM_READY. > > drivers/pci/pci.c | 40 +++++++++++++++++++++++++--------------- > 1 file changed, 25 insertions(+), 15 deletions(-) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 9e42090fb108..cd91adbf0269 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -3198,33 +3198,22 @@ void pci_pm_power_up_and_verify_state(struct pci_dev *pci_dev) > pci_update_current_state(pci_dev, PCI_D0); > } > > -/** > - * pci_pm_init - Initialize PM functions of given PCI device > - * @dev: PCI device to handle. > - */ > -void pci_pm_init(struct pci_dev *dev) > +static void __pci_pm_init(struct pci_dev *dev) > { > int pm; > - u16 status; > u16 pmc; > > - device_enable_async_suspend(&dev->dev); > - dev->wakeup_prepared = false; > - > - dev->pm_cap = 0; > - dev->pme_support = 0; > - > /* find PCI PM capability in list */ > pm = pci_find_capability(dev, PCI_CAP_ID_PM); > if (!pm) > - goto poweron; > + return; > /* Check device's ability to generate PME# */ > pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); > > if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { > pci_err(dev, "unsupported PM cap regs version (%u)\n", > pmc & PCI_PM_CAP_VER_MASK); > - goto poweron; > + return; > } > > dev->pm_cap = pm; > @@ -3265,11 +3254,32 @@ void pci_pm_init(struct pci_dev *dev) > /* Disable the PME# generation functionality */ > pci_pme_active(dev, false); > } > +} > + > +/** > + * pci_pm_init - Initialize PM functions of given PCI device > + * @dev: PCI device to handle. > + */ > +void pci_pm_init(struct pci_dev *dev) > +{ > + u16 status; > + > + device_enable_async_suspend(&dev->dev); > + dev->wakeup_prepared = false; > + > + dev->pm_cap = 0; > + dev->pme_support = 0; > + > + /* > + * Note, support for the PCI PM spec is optional for legacy PCI devices > + * and for VFs. Continue on even if no PM capabilities are supported. > + */ > + __pci_pm_init(dev); > > pci_read_config_word(dev, PCI_STATUS, &status); > if (status & PCI_STATUS_IMM_READY) > dev->imm_ready = 1; I would rather just move this PCI_STATUS read to somewhere else. I don't think there's a great place to put it. We could put it in set_pcie_port_type(), which is sort of a grab bag of PCIe-related things. I don't know if it's necessarily even a PCIe-specific thing, but it would be unexpected if somebody made a conventional PCI device that set it, since the bit was reserved (and should be zero) in PCI r3.0 and defined in PCIe r4.0. Maybe we should put it in pci_setup_device() close to where we call pci_intx_mask_broken()? Both PCI_STATUS_IMM_READY and PCI_STATUS_CAP_LIST are read-only, and we currently read PCI_STATUS for every single pci_find_capability() call, which is kind of stupid. Maybe someday we can optimize that and read PCI_STATUS once for both PCI_STATUS_CAP_LIST and PCI_STATUS_IMM_READY. > -poweron: > + > pci_pm_power_up_and_verify_state(dev); > pm_runtime_forbid(&dev->dev); > pm_runtime_set_active(&dev->dev); > > base-commit: 86731a2a651e58953fc949573895f2fa6d456841 > -- > 2.50.0.714.g196bf9f422-goog > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities 2025-06-25 23:03 ` Bjorn Helgaas @ 2025-06-26 22:17 ` Sean Christopherson 2025-06-27 15:51 ` Bjorn Helgaas 0 siblings, 1 reply; 5+ messages in thread From: Sean Christopherson @ 2025-06-26 22:17 UTC (permalink / raw) To: Bjorn Helgaas Cc: Bjorn Helgaas, linux-pci, linux-kernel, David Matlack, Vipin Sharma, Aaron Lewis On Wed, Jun 25, 2025, Bjorn Helgaas wrote: > On Tue, Jun 24, 2025 at 10:16:37AM -0700, Sean Christopherson wrote: > > +void pci_pm_init(struct pci_dev *dev) > > +{ > > + u16 status; > > + > > + device_enable_async_suspend(&dev->dev); > > + dev->wakeup_prepared = false; > > + > > + dev->pm_cap = 0; > > + dev->pme_support = 0; > > + > > + /* > > + * Note, support for the PCI PM spec is optional for legacy PCI devices > > + * and for VFs. Continue on even if no PM capabilities are supported. > > + */ > > + __pci_pm_init(dev); > > > > pci_read_config_word(dev, PCI_STATUS, &status); > > if (status & PCI_STATUS_IMM_READY) > > dev->imm_ready = 1; > > I would rather just move this PCI_STATUS read to somewhere else. I > don't think there's a great place to put it. We could put it in > set_pcie_port_type(), which is sort of a grab bag of PCIe-related > things. > > I don't know if it's necessarily even a PCIe-specific thing, but it > would be unexpected if somebody made a conventional PCI device that > set it, since the bit was reserved (and should be zero) in PCI r3.0 > and defined in PCIe r4.0. > > Maybe we should put it in pci_setup_device() close to where we call > pci_intx_mask_broken()? Any reason not to throw it in pci_init_capabilities()? That has the advantage of minimizing the travel distance, e.g. to avoid introducing a goof similar to what happened with 4d4c10f763d7 ("PCI: Explicitly put devices into D0 when initializing"). E.g. something silly like this? Or maybe pci_misc_init() or so? diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9e42090fb108..4a1ba5c017cd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3205,7 +3205,6 @@ void pci_pm_power_up_and_verify_state(struct pci_dev *pci_dev) void pci_pm_init(struct pci_dev *dev) { int pm; - u16 status; u16 pmc; device_enable_async_suspend(&dev->dev); @@ -3266,9 +3265,6 @@ void pci_pm_init(struct pci_dev *dev) pci_pme_active(dev, false); } - pci_read_config_word(dev, PCI_STATUS, &status); - if (status & PCI_STATUS_IMM_READY) - dev->imm_ready = 1; poweron: pci_pm_power_up_and_verify_state(dev); pm_runtime_forbid(&dev->dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4b8693ec9e4c..d33b8af37247 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2595,6 +2595,15 @@ void pcie_report_downtraining(struct pci_dev *dev) __pcie_print_link_status(dev, false); } +static void pci_imm_ready_init(struct pci_dev *dev) +{ + u16 status; + + pci_read_config_word(dev, PCI_STATUS, &status); + if (status & PCI_STATUS_IMM_READY) + dev->imm_ready = 1; +} + static void pci_init_capabilities(struct pci_dev *dev) { pci_ea_init(dev); /* Enhanced Allocation */ @@ -2604,6 +2613,7 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Buffers for saving PCIe and PCI-X capabilities */ pci_allocate_cap_save_buffers(dev); + pci_imm_ready_init(dev); /* Immediate Ready */ pci_pm_init(dev); /* Power Management */ pci_vpd_init(dev); /* Vital Product Data */ pci_configure_ari(dev); /* Alternative Routing-ID Forwarding */ ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities 2025-06-26 22:17 ` Sean Christopherson @ 2025-06-27 15:51 ` Bjorn Helgaas 0 siblings, 0 replies; 5+ messages in thread From: Bjorn Helgaas @ 2025-06-27 15:51 UTC (permalink / raw) To: Sean Christopherson Cc: Bjorn Helgaas, linux-pci, linux-kernel, David Matlack, Vipin Sharma, Aaron Lewis On Thu, Jun 26, 2025 at 03:17:48PM -0700, Sean Christopherson wrote: > On Wed, Jun 25, 2025, Bjorn Helgaas wrote: > > On Tue, Jun 24, 2025 at 10:16:37AM -0700, Sean Christopherson wrote: > > > +void pci_pm_init(struct pci_dev *dev) > > > +{ > > > + u16 status; > > > + > > > + device_enable_async_suspend(&dev->dev); > > > + dev->wakeup_prepared = false; > > > + > > > + dev->pm_cap = 0; > > > + dev->pme_support = 0; > > > + > > > + /* > > > + * Note, support for the PCI PM spec is optional for legacy PCI devices > > > + * and for VFs. Continue on even if no PM capabilities are supported. > > > + */ > > > + __pci_pm_init(dev); > > > > > > pci_read_config_word(dev, PCI_STATUS, &status); > > > if (status & PCI_STATUS_IMM_READY) > > > dev->imm_ready = 1; > > > > I would rather just move this PCI_STATUS read to somewhere else. I > > don't think there's a great place to put it. We could put it in > > set_pcie_port_type(), which is sort of a grab bag of PCIe-related > > things. > > > > I don't know if it's necessarily even a PCIe-specific thing, but it > > would be unexpected if somebody made a conventional PCI device that > > set it, since the bit was reserved (and should be zero) in PCI r3.0 > > and defined in PCIe r4.0. > > > > Maybe we should put it in pci_setup_device() close to where we call > > pci_intx_mask_broken()? > > Any reason not to throw it in pci_init_capabilities()? That has the > advantage of minimizing the travel distance, e.g. to avoid > introducing a goof similar to what happened with 4d4c10f763d7 ("PCI: > Explicitly put devices into D0 when initializing"). The only reason I suggested doing it earlier was to enable a potential pci_find_capability() optimization. But this could easily be moved if/when that happens, so I think the patch below would be fine. > E.g. something silly like this? Or maybe pci_misc_init() or so? > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 9e42090fb108..4a1ba5c017cd 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -3205,7 +3205,6 @@ void pci_pm_power_up_and_verify_state(struct pci_dev *pci_dev) > void pci_pm_init(struct pci_dev *dev) > { > int pm; > - u16 status; > u16 pmc; > > device_enable_async_suspend(&dev->dev); > @@ -3266,9 +3265,6 @@ void pci_pm_init(struct pci_dev *dev) > pci_pme_active(dev, false); > } > > - pci_read_config_word(dev, PCI_STATUS, &status); > - if (status & PCI_STATUS_IMM_READY) > - dev->imm_ready = 1; > poweron: > pci_pm_power_up_and_verify_state(dev); > pm_runtime_forbid(&dev->dev); > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c > index 4b8693ec9e4c..d33b8af37247 100644 > --- a/drivers/pci/probe.c > +++ b/drivers/pci/probe.c > @@ -2595,6 +2595,15 @@ void pcie_report_downtraining(struct pci_dev *dev) > __pcie_print_link_status(dev, false); > } > > +static void pci_imm_ready_init(struct pci_dev *dev) > +{ > + u16 status; > + > + pci_read_config_word(dev, PCI_STATUS, &status); > + if (status & PCI_STATUS_IMM_READY) > + dev->imm_ready = 1; > +} > + > static void pci_init_capabilities(struct pci_dev *dev) > { > pci_ea_init(dev); /* Enhanced Allocation */ > @@ -2604,6 +2613,7 @@ static void pci_init_capabilities(struct pci_dev *dev) > /* Buffers for saving PCIe and PCI-X capabilities */ > pci_allocate_cap_save_buffers(dev); > > + pci_imm_ready_init(dev); /* Immediate Ready */ > pci_pm_init(dev); /* Power Management */ > pci_vpd_init(dev); /* Vital Product Data */ > pci_configure_ari(dev); /* Alternative Routing-ID Forwarding */ ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-06-27 15:51 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-24 17:16 [RFC PATCH] PCI: Support Immediate Readiness on devices without PM capabilities Sean Christopherson 2025-06-25 16:32 ` Vipin Sharma 2025-06-25 23:03 ` Bjorn Helgaas 2025-06-26 22:17 ` Sean Christopherson 2025-06-27 15:51 ` Bjorn Helgaas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).