* [PATCH v3 0/5] Verify devices transition from D3cold to D0
@ 2024-07-12 18:12 superm1
2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw)
To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg
Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER,
Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
Gary has reported that when a dock is plugged into a system at the same
time the autosuspend delay has tripped that the USB4 stack malfunctions.
Messages show up like this:
```
thunderbolt 0000:e5:00.6: ring_interrupt_active: interrupt for TX ring 0 is already enabled
```
Furthermore the USB4 router is non-functional at this point.
Those messages happen because the device is still in D3cold at the time
that the PCI core handed control back to the USB4 connection manager
(thunderbolt).
The issue is that it takes time for a device to enter D3cold and do a
conventional reset, and then more time for it to exit D3cold.
This appears not to be a new problem; previously there were very similar
reports from Ryzen XHCI controllers. Quirks were added for those.
Furthermore; adding extra logging it's apparent that other PCI devices
in the system can take more than 10ms to recover from D3cold as well.
This series add a wait into pci_power_up() specifically for D3cold exit and
then drops the quirks that were previously used for the Ryzen XHCI controllers.
v2->v3:
* Add an enum for reset types and pass that instead.
v1->v2:
* Add a fix for a suspend problem
Mario Limonciello (5):
PCI: Use an enum for reset type in pci_dev_wait()
PCI: Check PCI_PM_CTRL instead of PCI_COMMAND in pci_dev_wait()
PCI: Verify functions currently in D3cold have entered D0
PCI: Allow Ryzen XHCI controllers into D3cold and drop delays
PCI: Drop Radeon quirk for Macbook Pro 8.2
drivers/pci/pci-driver.c | 2 +-
drivers/pci/pci.c | 68 +++++++++++++++++++++++++++----------
drivers/pci/pci.h | 12 ++++++-
drivers/pci/pcie/dpc.c | 2 +-
drivers/pci/quirks.c | 25 --------------
drivers/usb/host/xhci-pci.c | 11 ------
6 files changed, 63 insertions(+), 57 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 @ 2024-07-12 18:12 ` superm1 2024-07-13 8:38 ` kernel test robot 2024-07-15 12:36 ` Ilpo Järvinen 2024-07-12 18:12 ` [PATCH v3 2/5] PCI: Check PCI_PM_CTRL instead of PCI_COMMAND " superm1 ` (3 subsequent siblings) 4 siblings, 2 replies; 8+ messages in thread From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw) To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello, Ilpo Järvinen From: Mario Limonciello <mario.limonciello@amd.com> A string is passed to all callers of pci_dev_wait() which is utilized to demonstrate what kind of reset happened when there was a problem. This doesn't allow making the behavior for different reset types conditional though. Lay some plumbing to allow making comparisons of reset types with integers instead. No functional changes. Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/pci/pci-driver.c | 2 +- drivers/pci/pci.c | 29 +++++++++++++++++++---------- drivers/pci/pci.h | 11 ++++++++++- drivers/pci/pcie/dpc.c | 2 +- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index af2996d0d17ff..ff97d08741df7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -572,7 +572,7 @@ static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) { int ret; - ret = pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); + ret = pci_bridge_wait_for_secondary_bus(pci_dev, PCI_DEV_WAIT_RESUME); if (ret) { /* * The downstream link failed to come up, so mark the diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 35fb1f17a589c..115361a08d9e3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -181,6 +181,15 @@ static int __init pcie_port_pm_setup(char *str) } __setup("pcie_port_pm=", pcie_port_pm_setup); +const char * const pci_reset_types[] = { + "FLR", + "AF_FLR", + "PM D3HOT->D0", + "bus reset", + "resume", + "DPC", +}; + /** * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children * @bus: pointer to PCI bus structure to search @@ -1250,7 +1259,7 @@ void pci_resume_bus(struct pci_bus *bus) pci_walk_bus(bus, pci_resume_one, NULL); } -static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) +static int pci_dev_wait(struct pci_dev *dev, enum pci_reset_type reset_type, int timeout) { int delay = 1; bool retrain = false; @@ -1288,7 +1297,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) if (delay > timeout) { pci_warn(dev, "not ready %dms after %s; giving up\n", - delay - 1, reset_type); + delay - 1, pci_reset_types[reset_type]); return -ENOTTY; } @@ -1301,7 +1310,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) } } pci_info(dev, "not ready %dms after %s; waiting\n", - delay - 1, reset_type); + delay - 1, pci_reset_types[reset_type]); } msleep(delay); @@ -1310,10 +1319,10 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) if (delay > PCI_RESET_WAIT) pci_info(dev, "ready %dms after %s\n", delay - 1, - reset_type); + pci_reset_types[reset_type]); else pci_dbg(dev, "ready %dms after %s\n", delay - 1, - reset_type); + pci_reset_types[reset_type]); return 0; } @@ -4465,7 +4474,7 @@ int pcie_flr(struct pci_dev *dev) */ msleep(100); - return pci_dev_wait(dev, "FLR", PCIE_RESET_READY_POLL_MS); + return pci_dev_wait(dev, PCI_DEV_WAIT_FLR, PCIE_RESET_READY_POLL_MS); } EXPORT_SYMBOL_GPL(pcie_flr); @@ -4532,7 +4541,7 @@ static int pci_af_flr(struct pci_dev *dev, bool probe) */ msleep(100); - return pci_dev_wait(dev, "AF_FLR", PCIE_RESET_READY_POLL_MS); + return pci_dev_wait(dev, PCI_DEV_WAIT_AF_FLR, PCIE_RESET_READY_POLL_MS); } /** @@ -4577,7 +4586,7 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); pci_dev_d3_sleep(dev); - return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); + return pci_dev_wait(dev, PCI_DEV_WAIT_D3HOT_D0, PCIE_RESET_READY_POLL_MS); } /** @@ -4751,7 +4760,7 @@ static int pci_bus_max_d3cold_delay(const struct pci_bus *bus) * Return 0 on success or -ENOTTY if the first device on the secondary bus * failed to become accessible. */ -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, enum pci_reset_type reset_type) { struct pci_dev *child; int delay; @@ -4885,7 +4894,7 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { pcibios_reset_secondary_bus(dev); - return pci_bridge_wait_for_secondary_bus(dev, "bus reset"); + return pci_bridge_wait_for_secondary_bus(dev, PCI_DEV_WAIT_BUS_RESET); } EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fd44565c47562..88f54d22118dc 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -4,6 +4,15 @@ #include <linux/pci.h> +enum pci_reset_type { + PCI_DEV_WAIT_FLR, + PCI_DEV_WAIT_AF_FLR, + PCI_DEV_WAIT_D3HOT_D0, + PCI_DEV_WAIT_BUS_RESET, + PCI_DEV_WAIT_RESUME, + PCI_DEV_WAIT_DPC, +}; + /* Number of possible devfns: 0.0 to 1f.7 inclusive */ #define MAX_NR_DEVFNS 256 @@ -94,7 +103,7 @@ void pci_msi_init(struct pci_dev *dev); void pci_msix_init(struct pci_dev *dev); bool pci_bridge_d3_possible(struct pci_dev *dev); void pci_bridge_d3_update(struct pci_dev *dev); -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type); +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, enum pci_reset_type reset_type); static inline void pci_wakeup_event(struct pci_dev *dev) { diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index a668820696dc0..306efc399e503 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -174,7 +174,7 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); - if (pci_bridge_wait_for_secondary_bus(pdev, "DPC")) { + if (pci_bridge_wait_for_secondary_bus(pdev, PCI_DEV_WAIT_DPC)) { clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); ret = PCI_ERS_RESULT_DISCONNECT; } else { -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() 2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1 @ 2024-07-13 8:38 ` kernel test robot 2024-07-15 12:36 ` Ilpo Järvinen 1 sibling, 0 replies; 8+ messages in thread From: kernel test robot @ 2024-07-13 8:38 UTC (permalink / raw) To: superm1, Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: oe-kbuild-all, open list : PCI SUBSYSTEM, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello, Ilpo Järvinen Hi, kernel test robot noticed the following build warnings: [auto build test WARNING on usb/usb-testing] [also build test WARNING on usb/usb-next usb/usb-linus westeri-thunderbolt/next linus/master v6.10-rc7 next-20240712] [cannot apply to pci/next pci/for-linus] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/superm1-kernel-org/PCI-Use-an-enum-for-reset-type-in-pci_dev_wait/20240713-022018 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing patch link: https://lore.kernel.org/r/20240712181246.811044-2-superm1%40kernel.org patch subject: [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() config: x86_64-randconfig-121-20240713 (https://download.01.org/0day-ci/archive/20240713/202407131650.S68TetNP-lkp@intel.com/config) compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240713/202407131650.S68TetNP-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202407131650.S68TetNP-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/pci/pci.c:184:12: sparse: sparse: symbol 'pci_reset_types' was not declared. Should it be static? drivers/pci/pci.c:1208:36: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_power_t [usertype] current_state @@ got int @@ drivers/pci/pci.c:1208:36: sparse: expected restricted pci_power_t [usertype] current_state drivers/pci/pci.c:1208:36: sparse: got int drivers/pci/pci.c:1367:15: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_power_t [assigned] [usertype] state @@ got int @@ drivers/pci/pci.c:1367:15: sparse: expected restricted pci_power_t [assigned] [usertype] state drivers/pci/pci.c:1367:15: sparse: got int drivers/pci/pci.c:1369:50: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1369:69: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1422:28: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_power_t [usertype] current_state @@ got int @@ drivers/pci/pci.c:1422:28: sparse: expected restricted pci_power_t [usertype] current_state drivers/pci/pci.c:1422:28: sparse: got int drivers/pci/pci.c:1512:16: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1512:35: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1512:52: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1512:70: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1534:15: sparse: sparse: invalid assignment: |= drivers/pci/pci.c:1534:15: sparse: left side has type unsigned short drivers/pci/pci.c:1534:15: sparse: right side has type restricted pci_power_t drivers/pci/pci.c:1546:28: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted pci_power_t [usertype] current_state @@ got int @@ drivers/pci/pci.c:1546:28: sparse: expected restricted pci_power_t [usertype] current_state drivers/pci/pci.c:1546:28: sparse: got int drivers/pci/pci.c:1563:13: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1563:21: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1565:18: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1565:26: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1588:13: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1588:22: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:1920:38: sparse: sparse: array of flexible structures drivers/pci/pci.c:2370:44: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2689:60: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2690:30: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2861:20: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2861:38: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2884:49: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:2884:67: sparse: sparse: restricted pci_power_t degrades to integer drivers/pci/pci.c:4580:13: sparse: sparse: invalid assignment: |= drivers/pci/pci.c:4580:13: sparse: left side has type unsigned short drivers/pci/pci.c:4580:13: sparse: right side has type restricted pci_power_t drivers/pci/pci.c:4585:13: sparse: sparse: invalid assignment: |= drivers/pci/pci.c:4585:13: sparse: left side has type unsigned short drivers/pci/pci.c:4585:13: sparse: right side has type restricted pci_power_t drivers/pci/pci.c: note: in included file (through include/linux/resource_ext.h, include/linux/acpi.h): include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true drivers/pci/pci.c:1163:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted pci_power_t [usertype] @@ drivers/pci/pci.c:1163:24: sparse: expected int drivers/pci/pci.c:1163:24: sparse: got restricted pci_power_t [usertype] drivers/pci/pci.c:1163:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted pci_power_t [usertype] @@ drivers/pci/pci.c:1163:24: sparse: expected int drivers/pci/pci.c:1163:24: sparse: got restricted pci_power_t [usertype] vim +/pci_reset_types +184 drivers/pci/pci.c 183 > 184 const char * const pci_reset_types[] = { 185 "FLR", 186 "AF_FLR", 187 "PM D3HOT->D0", 188 "bus reset", 189 "resume", 190 "DPC", 191 }; 192 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() 2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1 2024-07-13 8:38 ` kernel test robot @ 2024-07-15 12:36 ` Ilpo Järvinen 1 sibling, 0 replies; 8+ messages in thread From: Ilpo Järvinen @ 2024-07-15 12:36 UTC (permalink / raw) To: superm1 Cc: Bjorn Helgaas, Mathias Nyman, Mika Westerberg, open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello [-- Attachment #1: Type: text/plain, Size: 6765 bytes --] On Fri, 12 Jul 2024, superm1@kernel.org wrote: > From: Mario Limonciello <mario.limonciello@amd.com> > > A string is passed to all callers of pci_dev_wait() which is utilized > to demonstrate what kind of reset happened when there was a problem. > > This doesn't allow making the behavior for different reset types > conditional though. Lay some plumbing to allow making comparisons of > reset types with integers instead. No functional changes. > > Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> > Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> > --- > drivers/pci/pci-driver.c | 2 +- > drivers/pci/pci.c | 29 +++++++++++++++++++---------- > drivers/pci/pci.h | 11 ++++++++++- > drivers/pci/pcie/dpc.c | 2 +- > 4 files changed, 31 insertions(+), 13 deletions(-) > > diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c > index af2996d0d17ff..ff97d08741df7 100644 > --- a/drivers/pci/pci-driver.c > +++ b/drivers/pci/pci-driver.c > @@ -572,7 +572,7 @@ static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) > { > int ret; > > - ret = pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); > + ret = pci_bridge_wait_for_secondary_bus(pci_dev, PCI_DEV_WAIT_RESUME); > if (ret) { > /* > * The downstream link failed to come up, so mark the > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 35fb1f17a589c..115361a08d9e3 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -181,6 +181,15 @@ static int __init pcie_port_pm_setup(char *str) > } > __setup("pcie_port_pm=", pcie_port_pm_setup); > > +const char * const pci_reset_types[] = { Sparse is not happy about this and expects static as it is not defined by any header (LKP seems to also have caught this). > + "FLR", > + "AF_FLR", > + "PM D3HOT->D0", > + "bus reset", > + "resume", > + "DPC", Perhaps the index-based array initialization format would be beneficial here. -- i. > +}; > + > /** > * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children > * @bus: pointer to PCI bus structure to search > @@ -1250,7 +1259,7 @@ void pci_resume_bus(struct pci_bus *bus) > pci_walk_bus(bus, pci_resume_one, NULL); > } > > -static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) > +static int pci_dev_wait(struct pci_dev *dev, enum pci_reset_type reset_type, int timeout) > { > int delay = 1; > bool retrain = false; > @@ -1288,7 +1297,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) > > if (delay > timeout) { > pci_warn(dev, "not ready %dms after %s; giving up\n", > - delay - 1, reset_type); > + delay - 1, pci_reset_types[reset_type]); > return -ENOTTY; > } > > @@ -1301,7 +1310,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) > } > } > pci_info(dev, "not ready %dms after %s; waiting\n", > - delay - 1, reset_type); > + delay - 1, pci_reset_types[reset_type]); > } > > msleep(delay); > @@ -1310,10 +1319,10 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) > > if (delay > PCI_RESET_WAIT) > pci_info(dev, "ready %dms after %s\n", delay - 1, > - reset_type); > + pci_reset_types[reset_type]); > else > pci_dbg(dev, "ready %dms after %s\n", delay - 1, > - reset_type); > + pci_reset_types[reset_type]); > > return 0; > } > @@ -4465,7 +4474,7 @@ int pcie_flr(struct pci_dev *dev) > */ > msleep(100); > > - return pci_dev_wait(dev, "FLR", PCIE_RESET_READY_POLL_MS); > + return pci_dev_wait(dev, PCI_DEV_WAIT_FLR, PCIE_RESET_READY_POLL_MS); > } > EXPORT_SYMBOL_GPL(pcie_flr); > > @@ -4532,7 +4541,7 @@ static int pci_af_flr(struct pci_dev *dev, bool probe) > */ > msleep(100); > > - return pci_dev_wait(dev, "AF_FLR", PCIE_RESET_READY_POLL_MS); > + return pci_dev_wait(dev, PCI_DEV_WAIT_AF_FLR, PCIE_RESET_READY_POLL_MS); > } > > /** > @@ -4577,7 +4586,7 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) > pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); > pci_dev_d3_sleep(dev); > > - return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); > + return pci_dev_wait(dev, PCI_DEV_WAIT_D3HOT_D0, PCIE_RESET_READY_POLL_MS); > } > > /** > @@ -4751,7 +4760,7 @@ static int pci_bus_max_d3cold_delay(const struct pci_bus *bus) > * Return 0 on success or -ENOTTY if the first device on the secondary bus > * failed to become accessible. > */ > -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) > +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, enum pci_reset_type reset_type) > { > struct pci_dev *child; > int delay; > @@ -4885,7 +4894,7 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) > { > pcibios_reset_secondary_bus(dev); > > - return pci_bridge_wait_for_secondary_bus(dev, "bus reset"); > + return pci_bridge_wait_for_secondary_bus(dev, PCI_DEV_WAIT_BUS_RESET); > } > EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); > > diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h > index fd44565c47562..88f54d22118dc 100644 > --- a/drivers/pci/pci.h > +++ b/drivers/pci/pci.h > @@ -4,6 +4,15 @@ > > #include <linux/pci.h> > > +enum pci_reset_type { > + PCI_DEV_WAIT_FLR, > + PCI_DEV_WAIT_AF_FLR, > + PCI_DEV_WAIT_D3HOT_D0, > + PCI_DEV_WAIT_BUS_RESET, > + PCI_DEV_WAIT_RESUME, > + PCI_DEV_WAIT_DPC, > +}; > + > /* Number of possible devfns: 0.0 to 1f.7 inclusive */ > #define MAX_NR_DEVFNS 256 > > @@ -94,7 +103,7 @@ void pci_msi_init(struct pci_dev *dev); > void pci_msix_init(struct pci_dev *dev); > bool pci_bridge_d3_possible(struct pci_dev *dev); > void pci_bridge_d3_update(struct pci_dev *dev); > -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type); > +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, enum pci_reset_type reset_type); > > static inline void pci_wakeup_event(struct pci_dev *dev) > { > diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c > index a668820696dc0..306efc399e503 100644 > --- a/drivers/pci/pcie/dpc.c > +++ b/drivers/pci/pcie/dpc.c > @@ -174,7 +174,7 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) > pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, > PCI_EXP_DPC_STATUS_TRIGGER); > > - if (pci_bridge_wait_for_secondary_bus(pdev, "DPC")) { > + if (pci_bridge_wait_for_secondary_bus(pdev, PCI_DEV_WAIT_DPC)) { > clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); > ret = PCI_ERS_RESULT_DISCONNECT; > } else { > ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 2/5] PCI: Check PCI_PM_CTRL instead of PCI_COMMAND in pci_dev_wait() 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1 @ 2024-07-12 18:12 ` superm1 2024-07-12 18:12 ` [PATCH v3 3/5] PCI: Verify functions currently in D3cold have entered D0 superm1 ` (2 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw) To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello From: Mario Limonciello <mario.limonciello@amd.com> A device that has gone through a reset may return a value in PCI_COMMAND but that doesn't mean it's finished transitioning to D0. On devices that support power management explicitly check PCI_PM_CTRL on everything but system resume to ensure the transition happened. Devices that don't support power management and system resume will continue to use PCI_COMMAND. Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/pci/pci.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 115361a08d9e3..658a139f74ab0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1279,21 +1279,33 @@ static int pci_dev_wait(struct pci_dev *dev, enum pci_reset_type reset_type, int * the read (except when CRS SV is enabled and the read was for the * Vendor ID; in that case it synthesizes 0x0001 data). * - * Wait for the device to return a non-CRS completion. Read the - * Command register instead of Vendor ID so we don't have to - * contend with the CRS SV value. + * Wait for the device to return a non-CRS completion. On devices + * that support PM control and on waits that aren't part of system + * resume read the PM control register to ensure the device has + * transitioned to D0. On devices that don't support PM control, + * or during system resume read the command register to instead of + * Vendor ID so we don't have to contend with the CRS SV value. */ for (;;) { - u32 id; - if (pci_dev_is_disconnected(dev)) { pci_dbg(dev, "disconnected; not waiting\n"); return -ENOTTY; } - pci_read_config_dword(dev, PCI_COMMAND, &id); - if (!PCI_POSSIBLE_ERROR(id)) - break; + if (dev->pm_cap && reset_type != PCI_DEV_WAIT_RESUME) { + u16 pmcsr; + + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + if (!PCI_POSSIBLE_ERROR(pmcsr) && + (pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D0) + break; + } else { + u32 id; + + pci_read_config_dword(dev, PCI_COMMAND, &id); + if (!PCI_POSSIBLE_ERROR(id)) + break; + } if (delay > timeout) { pci_warn(dev, "not ready %dms after %s; giving up\n", -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/5] PCI: Verify functions currently in D3cold have entered D0 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1 2024-07-12 18:12 ` [PATCH v3 2/5] PCI: Check PCI_PM_CTRL instead of PCI_COMMAND " superm1 @ 2024-07-12 18:12 ` superm1 2024-07-12 18:12 ` [PATCH v3 4/5] PCI: Allow Ryzen XHCI controllers into D3cold and drop delays superm1 2024-07-12 18:12 ` [PATCH v3 5/5] PCI: Drop Radeon quirk for Macbook Pro 8.2 superm1 4 siblings, 0 replies; 8+ messages in thread From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw) To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello, Ilpo Järvinen From: Mario Limonciello <mario.limonciello@amd.com> It is reported that USB4 routers and downstream devices may behave incorrectly if a dock cable is plugged in at approximately the time that the autosuspend_delay is configured. In this situation the device has attempted to enter D3cold, but didn't finish D3cold entry when the PCI core tried to transition it back to D0. Empirically measuring this situation an "aborted" D3cold exit takes ~60ms and a "normal" D3cold exit takes ~6ms. The PCI-PM 1.2 spec specifies that the restore time for functions in D3cold is either 'Full context restore or boot latency'. As PCIe r6.0 sec 5.8 specifies that the device will have gone through a conventional reset, it may take some time for the device to be ready. Wait up to 1 sec as specified in PCIe r6.0 sec 6.6.1 for a device in D3cold to return to D0. Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/pci/pci.c | 11 +++++++++++ drivers/pci/pci.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 658a139f74ab0..14dab7bc64ba4 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1396,6 +1396,17 @@ int pci_power_up(struct pci_dev *dev) else if (state == PCI_D2) udelay(PCI_PM_D2_DELAY); + /* + * D3cold -> D0 will have gone through a conventional reset and may need + * time to be ready. + */ + if (dev->current_state == PCI_D3cold) { + int ret; + + ret = pci_dev_wait(dev, PCI_DEV_WAIT_D3COLD_D0, PCI_RESET_WAIT); + if (ret) + return ret; + } end: dev->current_state = PCI_D0; if (need_restore) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 88f54d22118dc..9482539b9830a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -11,6 +11,7 @@ enum pci_reset_type { PCI_DEV_WAIT_BUS_RESET, PCI_DEV_WAIT_RESUME, PCI_DEV_WAIT_DPC, + PCI_DEV_WAIT_D3COLD_D0, }; /* Number of possible devfns: 0.0 to 1f.7 inclusive */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 4/5] PCI: Allow Ryzen XHCI controllers into D3cold and drop delays 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 ` (2 preceding siblings ...) 2024-07-12 18:12 ` [PATCH v3 3/5] PCI: Verify functions currently in D3cold have entered D0 superm1 @ 2024-07-12 18:12 ` superm1 2024-07-12 18:12 ` [PATCH v3 5/5] PCI: Drop Radeon quirk for Macbook Pro 8.2 superm1 4 siblings, 0 replies; 8+ messages in thread From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw) To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello From: Mario Limonciello <mario.limonciello@amd.com> As the PCI core now has a delay after D3cold exit, the Ryzen XHCI controllers that were quirked to not use D3cold and to add a delay on D3hot no longer need these quirks. Drop both the PCI and XHCI sets of quirks. Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/pci/quirks.c | 17 ----------------- drivers/usb/host/xhci-pci.c | 11 ----------- 2 files changed, 28 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 568410e64ce64..942d0fe12cb1a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2059,23 +2059,6 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_nvidia_hda_pm); -/* - * Ryzen5/7 XHCI controllers fail upon resume from runtime suspend or s2idle. - * https://bugzilla.kernel.org/show_bug.cgi?id=205587 - * - * The kernel attempts to transition these devices to D3cold, but that seems - * to be ineffective on the platforms in question; the PCI device appears to - * remain on in D3hot state. The D3hot-to-D0 transition then requires an - * extended delay in order to succeed. - */ -static void quirk_ryzen_xhci_d3hot(struct pci_dev *dev) -{ - quirk_d3hot_delay(dev, 20); -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e0, quirk_ryzen_xhci_d3hot); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e1, quirk_ryzen_xhci_d3hot); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1639, quirk_ryzen_xhci_d3hot); - #ifdef CONFIG_X86_IO_APIC static int dmi_disable_ioapicreroute(const struct dmi_system_id *d) { diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 05881153883ec..8eb7abf6be1ac 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -315,10 +315,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1))) xhci->quirks |= XHCI_U2_DISABLE_WAKE; - if (pdev->vendor == PCI_VENDOR_ID_AMD && - pdev->device == PCI_DEVICE_ID_AMD_RENOIR_XHCI) - xhci->quirks |= XHCI_BROKEN_D3COLD_S2I; - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_INTEL_HOST; @@ -750,13 +746,6 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) if (xhci->quirks & XHCI_COMP_MODE_QUIRK) pci_d3cold_disable(pdev); -#ifdef CONFIG_SUSPEND - /* d3cold is broken, but only when s2idle is used */ - if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE && - xhci->quirks & (XHCI_BROKEN_D3COLD_S2I)) - pci_d3cold_disable(pdev); -#endif - if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(hcd); -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 5/5] PCI: Drop Radeon quirk for Macbook Pro 8.2 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 ` (3 preceding siblings ...) 2024-07-12 18:12 ` [PATCH v3 4/5] PCI: Allow Ryzen XHCI controllers into D3cold and drop delays superm1 @ 2024-07-12 18:12 ` superm1 4 siblings, 0 replies; 8+ messages in thread From: superm1 @ 2024-07-12 18:12 UTC (permalink / raw) To: Bjorn Helgaas, Mathias Nyman, Mika Westerberg Cc: open list : PCI SUBSYSTEM, open list, open list : USB XHCI DRIVER, Daniel Drake, Gary Li, Greg Kroah-Hartman, Mario Limonciello From: Mario Limonciello <mario.limonciello@amd.com> commit 5938628c51a7 ("drm/radeon: make MacBook Pro d3_delay quirk more generic") introduced a generic quirk for Macbook Pro 8.2s that contain Radeon graphics to ensure that enough time had past when the device was powered on. As the PCI core now verifies the device is in D0 during power on this extra artificial delay is no longer necessary. Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/pci/quirks.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 942d0fe12cb1a..19be953c9f373 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2038,14 +2038,6 @@ static void quirk_d3hot_delay(struct pci_dev *dev, unsigned int delay) dev->d3hot_delay); } -static void quirk_radeon_pm(struct pci_dev *dev) -{ - if (dev->subsystem_vendor == PCI_VENDOR_ID_APPLE && - dev->subsystem_device == 0x00e2) - quirk_d3hot_delay(dev, 20); -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6741, quirk_radeon_pm); - /* * NVIDIA Ampere-based HDA controllers can wedge the whole device if a bus * reset is performed too soon after transition to D0, extend d3hot_delay -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-07-15 12:36 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-07-12 18:12 [PATCH v3 0/5] Verify devices transition from D3cold to D0 superm1 2024-07-12 18:12 ` [PATCH v3 1/5] PCI: Use an enum for reset type in pci_dev_wait() superm1 2024-07-13 8:38 ` kernel test robot 2024-07-15 12:36 ` Ilpo Järvinen 2024-07-12 18:12 ` [PATCH v3 2/5] PCI: Check PCI_PM_CTRL instead of PCI_COMMAND " superm1 2024-07-12 18:12 ` [PATCH v3 3/5] PCI: Verify functions currently in D3cold have entered D0 superm1 2024-07-12 18:12 ` [PATCH v3 4/5] PCI: Allow Ryzen XHCI controllers into D3cold and drop delays superm1 2024-07-12 18:12 ` [PATCH v3 5/5] PCI: Drop Radeon quirk for Macbook Pro 8.2 superm1
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).