On Mon, Jan 11, 2021 at 09:02:39PM +0100, Hinko Kocevar wrote: > Attached are the messages. > > Thanks! Thank you. It kind of looks like the frequent ext capabilty lookup might just be really slow for some reason. Could you try the following patch and let me know if this improves the CPU lockup? --- diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5c59365092fa..8a61a9365c28 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -106,6 +106,7 @@ void pci_pm_init(struct pci_dev *dev); void pci_ea_init(struct pci_dev *dev); void pci_msi_init(struct pci_dev *dev); void pci_msix_init(struct pci_dev *dev); +void pci_vc_init(struct pci_dev *dev); void pci_allocate_cap_save_buffers(struct pci_dev *dev); void pci_free_cap_save_buffers(struct pci_dev *dev); bool pci_bridge_d3_possible(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 953f15abc850..56992a42bac6 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2401,6 +2401,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_aer_init(dev); /* Advanced Error Reporting */ pci_dpc_init(dev); /* Downstream Port Containment */ pci_rcec_init(dev); /* Root Complex Event Collector */ + pci_vc_init(dev); /* Virtual Channel */ pcie_report_downtraining(dev); diff --git a/drivers/pci/vc.c b/drivers/pci/vc.c index 5fc59ac31145..76ac118b9b5d 100644 --- a/drivers/pci/vc.c +++ b/drivers/pci/vc.c @@ -357,7 +357,7 @@ int pci_save_vc_state(struct pci_dev *dev) int pos, ret; struct pci_cap_saved_state *save_state; - pos = pci_find_ext_capability(dev, vc_caps[i].id); + pos = dev->vc_caps[i]; if (!pos) continue; @@ -394,9 +394,12 @@ void pci_restore_vc_state(struct pci_dev *dev) int pos; struct pci_cap_saved_state *save_state; - pos = pci_find_ext_capability(dev, vc_caps[i].id); + pos = dev->vc_caps[i]; + if (!pos) + continue; + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); - if (!save_state || !pos) + if (!save_state) continue; pci_vc_do_save_buffer(dev, pos, save_state, false); @@ -415,7 +418,7 @@ void pci_allocate_vc_save_buffers(struct pci_dev *dev) int i; for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { - int len, pos = pci_find_ext_capability(dev, vc_caps[i].id); + int len, pos = dev->vc_caps[i]; if (!pos) continue; @@ -426,3 +429,11 @@ void pci_allocate_vc_save_buffers(struct pci_dev *dev) vc_caps[i].name); } } + +void pci_vc_init(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(vc_caps); i++) + dev->vc_caps[i] = pci_find_ext_capability(dev, vc_caps[i].id); +} diff --git a/include/linux/pci.h b/include/linux/pci.h index b32126d26997..7a3aa7e4d6f8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -501,6 +501,7 @@ struct pci_dev { struct pci_p2pdma *p2pdma; #endif u16 acs_cap; /* ACS Capability offset */ + u16 vc_caps[3]; /* Virtual Channel capability offsets */ phys_addr_t rom; /* Physical address if not from BAR */ size_t romlen; /* Length if not from BAR */ char *driver_override; /* Driver name to force a match */ --