* [PATCH 0/2] PCI: Avoid capability searches in save/restore state
@ 2025-02-08 5:03 Bjorn Helgaas
2025-02-08 5:03 ` [PATCH 1/2] PCI: Avoid pointless capability searches Bjorn Helgaas
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Bjorn Helgaas @ 2025-02-08 5:03 UTC (permalink / raw)
To: Alex Williamson, Christian König
Cc: linux-pci, linux-kernel, Bjorn Helgaas
From: Bjorn Helgaas <bhelgaas@google.com>
Reduce the number of times we search config space for PCI capabilities when
saving and restoring device state.
Bjorn Helgaas (2):
PCI: Avoid pointless capability searches
PCI: Cache offset of Resizable BAR capability
drivers/pci/pci.c | 36 +++++++++++++++++++++---------------
drivers/pci/pci.h | 1 +
drivers/pci/pcie/aspm.c | 15 ++++++++-------
drivers/pci/probe.c | 1 +
drivers/pci/vc.c | 22 +++++++++++-----------
include/linux/pci.h | 1 +
6 files changed, 43 insertions(+), 33 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/2] PCI: Avoid pointless capability searches 2025-02-08 5:03 [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas @ 2025-02-08 5:03 ` Bjorn Helgaas 2025-02-13 13:52 ` Ilpo Järvinen 2025-02-08 5:03 ` [PATCH 2/2] PCI: Cache offset of Resizable BAR capability Bjorn Helgaas 2025-02-12 22:35 ` [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas 2 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2025-02-08 5:03 UTC (permalink / raw) To: Alex Williamson, Christian König Cc: linux-pci, linux-kernel, Bjorn Helgaas From: Bjorn Helgaas <bhelgaas@google.com> Many of the save/restore functions in the pci_save_state() and pci_restore_state() paths depend on both a PCI capability of the device and a pci_cap_saved_state structure to hold the configuration data, and they skip the operation if either is missing. Look for the pci_cap_saved_state first so if we don't have one, we can skip searching for the device capability, which requires several slow config space accesses. Remove some error messages if the pci_cap_saved_state is not found so we don't complain about having no saved state for a capability the device doesn't have. We have already warned in pci_allocate_cap_save_buffers() if the capability is present but we were unable to allocate a buffer. Other than the message change, no functional change intended. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> --- drivers/pci/pci.c | 27 ++++++++++++++------------- drivers/pci/pcie/aspm.c | 15 ++++++++------- drivers/pci/vc.c | 22 +++++++++++----------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 869d204a70a3..503376bf7e75 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1686,10 +1686,8 @@ static int pci_save_pcie_state(struct pci_dev *dev) return 0; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); - if (!save_state) { - pci_err(dev, "buffer not found in %s\n", __func__); + if (!save_state) return -ENOMEM; - } cap = (u16 *)&save_state->cap.data[0]; pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]); @@ -1742,19 +1740,17 @@ static void pci_restore_pcie_state(struct pci_dev *dev) static int pci_save_pcix_state(struct pci_dev *dev) { - int pos; struct pci_cap_saved_state *save_state; + u8 pos; + + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); + if (!save_state) + return -ENOMEM; pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!pos) return 0; - save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); - if (!save_state) { - pci_err(dev, "buffer not found in %s\n", __func__); - return -ENOMEM; - } - pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->cap.data); @@ -1763,14 +1759,19 @@ static int pci_save_pcix_state(struct pci_dev *dev) static void pci_restore_pcix_state(struct pci_dev *dev) { - int i = 0, pos; struct pci_cap_saved_state *save_state; + u8 pos; + int i = 0; u16 *cap; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); - pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); - if (!save_state || !pos) + if (!save_state) return; + + pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); + if (!pos) + return; + cap = (u16 *)&save_state->cap.data[0]; pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index e0bc90597dca..007e4a082e6f 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -35,16 +35,14 @@ void pci_save_ltr_state(struct pci_dev *dev) if (!pci_is_pcie(dev)) return; + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); + if (!save_state) + return; + ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); if (!ltr) return; - save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); - if (!save_state) { - pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after resume\n"); - return; - } - /* Some broken devices only support dword access to LTR */ cap = &save_state->cap.data[0]; pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap); @@ -57,8 +55,11 @@ void pci_restore_ltr_state(struct pci_dev *dev) u32 *cap; save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); + if (!save_state) + return; + ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); - if (!save_state || !ltr) + if (!ltr) return; /* Some broken devices only support dword access to LTR */ diff --git a/drivers/pci/vc.c b/drivers/pci/vc.c index a4ff7f5f66dd..c39f3be518d4 100644 --- a/drivers/pci/vc.c +++ b/drivers/pci/vc.c @@ -355,20 +355,17 @@ int pci_save_vc_state(struct pci_dev *dev) int i; for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { - int pos, ret; struct pci_cap_saved_state *save_state; + int pos, ret; + + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); + if (!save_state) + return -ENOMEM; pos = pci_find_ext_capability(dev, vc_caps[i].id); if (!pos) continue; - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); - if (!save_state) { - pci_err(dev, "%s buffer not found in %s\n", - vc_caps[i].name, __func__); - return -ENOMEM; - } - ret = pci_vc_do_save_buffer(dev, pos, save_state, true); if (ret) { pci_err(dev, "%s save unsuccessful %s\n", @@ -392,12 +389,15 @@ void pci_restore_vc_state(struct pci_dev *dev) int i; for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { - int pos; struct pci_cap_saved_state *save_state; + int pos; + + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); + if (!save_state) + continue; pos = pci_find_ext_capability(dev, vc_caps[i].id); - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); - if (!save_state || !pos) + if (!pos) continue; pci_vc_do_save_buffer(dev, pos, save_state, false); -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] PCI: Avoid pointless capability searches 2025-02-08 5:03 ` [PATCH 1/2] PCI: Avoid pointless capability searches Bjorn Helgaas @ 2025-02-13 13:52 ` Ilpo Järvinen 2025-02-13 16:38 ` Bjorn Helgaas 0 siblings, 1 reply; 8+ messages in thread From: Ilpo Järvinen @ 2025-02-13 13:52 UTC (permalink / raw) To: Bjorn Helgaas Cc: Alex Williamson, Christian König, linux-pci, LKML, Bjorn Helgaas On Fri, 7 Feb 2025, Bjorn Helgaas wrote: > From: Bjorn Helgaas <bhelgaas@google.com> > > Many of the save/restore functions in the pci_save_state() and > pci_restore_state() paths depend on both a PCI capability of the device and > a pci_cap_saved_state structure to hold the configuration data, and they > skip the operation if either is missing. > > Look for the pci_cap_saved_state first so if we don't have one, we can skip > searching for the device capability, which requires several slow config > space accesses. > > Remove some error messages if the pci_cap_saved_state is not found so we > don't complain about having no saved state for a capability the device > doesn't have. We have already warned in pci_allocate_cap_save_buffers() if > the capability is present but we were unable to allocate a buffer. > > Other than the message change, no functional change intended. > > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> > --- > drivers/pci/pci.c | 27 ++++++++++++++------------- > drivers/pci/pcie/aspm.c | 15 ++++++++------- > drivers/pci/vc.c | 22 +++++++++++----------- > 3 files changed, 33 insertions(+), 31 deletions(-) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 869d204a70a3..503376bf7e75 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -1686,10 +1686,8 @@ static int pci_save_pcie_state(struct pci_dev *dev) > return 0; > > save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); > - if (!save_state) { > - pci_err(dev, "buffer not found in %s\n", __func__); > + if (!save_state) > return -ENOMEM; > - } > > cap = (u16 *)&save_state->cap.data[0]; > pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]); > @@ -1742,19 +1740,17 @@ static void pci_restore_pcie_state(struct pci_dev *dev) > > static int pci_save_pcix_state(struct pci_dev *dev) > { > - int pos; > struct pci_cap_saved_state *save_state; > + u8 pos; > + > + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); > + if (!save_state) > + return -ENOMEM; > > pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); > if (!pos) > return 0; > > - save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); > - if (!save_state) { > - pci_err(dev, "buffer not found in %s\n", __func__); > - return -ENOMEM; > - } > - > pci_read_config_word(dev, pos + PCI_X_CMD, > (u16 *)save_state->cap.data); > > @@ -1763,14 +1759,19 @@ static int pci_save_pcix_state(struct pci_dev *dev) > > static void pci_restore_pcix_state(struct pci_dev *dev) > { > - int i = 0, pos; > struct pci_cap_saved_state *save_state; > + u8 pos; > + int i = 0; > u16 *cap; > > save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); > - pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); > - if (!save_state || !pos) > + if (!save_state) > return; > + > + pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); > + if (!pos) > + return; > + > cap = (u16 *)&save_state->cap.data[0]; > > pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); > diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c > index e0bc90597dca..007e4a082e6f 100644 > --- a/drivers/pci/pcie/aspm.c > +++ b/drivers/pci/pcie/aspm.c > @@ -35,16 +35,14 @@ void pci_save_ltr_state(struct pci_dev *dev) > if (!pci_is_pcie(dev)) > return; > > + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); > + if (!save_state) > + return; > + > ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); > if (!ltr) > return; > > - save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); > - if (!save_state) { > - pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after resume\n"); > - return; > - } > - > /* Some broken devices only support dword access to LTR */ > cap = &save_state->cap.data[0]; > pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap); > @@ -57,8 +55,11 @@ void pci_restore_ltr_state(struct pci_dev *dev) > u32 *cap; > > save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); > + if (!save_state) > + return; > + > ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); > - if (!save_state || !ltr) > + if (!ltr) > return; > > /* Some broken devices only support dword access to LTR */ > diff --git a/drivers/pci/vc.c b/drivers/pci/vc.c > index a4ff7f5f66dd..c39f3be518d4 100644 > --- a/drivers/pci/vc.c > +++ b/drivers/pci/vc.c > @@ -355,20 +355,17 @@ int pci_save_vc_state(struct pci_dev *dev) > int i; > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > - int pos, ret; > struct pci_cap_saved_state *save_state; > + int pos, ret; > + > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > + if (!save_state) > + return -ENOMEM; > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > if (!pos) > continue; > > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > - if (!save_state) { > - pci_err(dev, "%s buffer not found in %s\n", > - vc_caps[i].name, __func__); > - return -ENOMEM; > - } I think this order change will cause a functional change because pci_allocate_vc_save_buffers() only allocated for those capabilities that are exist for dev. Thus, the loop will prematurely exit. > - > ret = pci_vc_do_save_buffer(dev, pos, save_state, true); > if (ret) { > pci_err(dev, "%s save unsuccessful %s\n", > @@ -392,12 +389,15 @@ void pci_restore_vc_state(struct pci_dev *dev) > int i; > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > - int pos; > struct pci_cap_saved_state *save_state; > + int pos; > + > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > + if (!save_state) > + continue; > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > - if (!save_state || !pos) > + if (!pos) > continue; > > pci_vc_do_save_buffer(dev, pos, save_state, false); > -- i. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] PCI: Avoid pointless capability searches 2025-02-13 13:52 ` Ilpo Järvinen @ 2025-02-13 16:38 ` Bjorn Helgaas 2025-02-14 14:20 ` Ilpo Järvinen 0 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2025-02-13 16:38 UTC (permalink / raw) To: Ilpo Järvinen Cc: Alex Williamson, Christian König, linux-pci, LKML, Bjorn Helgaas On Thu, Feb 13, 2025 at 03:52:05PM +0200, Ilpo Järvinen wrote: > On Fri, 7 Feb 2025, Bjorn Helgaas wrote: > > Many of the save/restore functions in the pci_save_state() and > > pci_restore_state() paths depend on both a PCI capability of the device and > > a pci_cap_saved_state structure to hold the configuration data, and they > > skip the operation if either is missing. > > > > Look for the pci_cap_saved_state first so if we don't have one, we can skip > > searching for the device capability, which requires several slow config > > space accesses. > > +++ b/drivers/pci/vc.c > > @@ -355,20 +355,17 @@ int pci_save_vc_state(struct pci_dev *dev) > > int i; > > > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > > - int pos, ret; > > struct pci_cap_saved_state *save_state; > > + int pos, ret; > > + > > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > + if (!save_state) > > + return -ENOMEM; > > > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > > if (!pos) > > continue; > > > > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > - if (!save_state) { > > - pci_err(dev, "%s buffer not found in %s\n", > > - vc_caps[i].name, __func__); > > - return -ENOMEM; > > - } > > I think this order change will cause a functional change because > pci_allocate_vc_save_buffers() only allocated for those capabilities that > are exist for dev. Thus, the loop will prematurely exit. Oof, thank you for catching this! I'll drop this for now. It would be nice to make pci_save_vc_state() parallel with pci_restore_vc_state() (and with most other pci_save_*_state() functions) and have it return void. But pci_save_state() returns the pci_save_vc_state() return value, and there are ~20 pci_save_state() callers that pay attention to that return value. I'm not convinced there's real value in pci_save_state() error returns, given that so few callers check it, but it definitely requires more analysis before removing it. > > ret = pci_vc_do_save_buffer(dev, pos, save_state, true); > > if (ret) { > > pci_err(dev, "%s save unsuccessful %s\n", > > @@ -392,12 +389,15 @@ void pci_restore_vc_state(struct pci_dev *dev) > > int i; > > > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > > - int pos; > > struct pci_cap_saved_state *save_state; > > + int pos; > > + > > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > + if (!save_state) > > + continue; > > > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > - if (!save_state || !pos) > > + if (!pos) > > continue; > > > > pci_vc_do_save_buffer(dev, pos, save_state, false); > > > > -- > i. > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] PCI: Avoid pointless capability searches 2025-02-13 16:38 ` Bjorn Helgaas @ 2025-02-14 14:20 ` Ilpo Järvinen 0 siblings, 0 replies; 8+ messages in thread From: Ilpo Järvinen @ 2025-02-14 14:20 UTC (permalink / raw) To: Bjorn Helgaas Cc: Alex Williamson, Christian König, linux-pci, LKML, Bjorn Helgaas [-- Attachment #1: Type: text/plain, Size: 3218 bytes --] On Thu, 13 Feb 2025, Bjorn Helgaas wrote: > On Thu, Feb 13, 2025 at 03:52:05PM +0200, Ilpo Järvinen wrote: > > On Fri, 7 Feb 2025, Bjorn Helgaas wrote: > > > Many of the save/restore functions in the pci_save_state() and > > > pci_restore_state() paths depend on both a PCI capability of the device and > > > a pci_cap_saved_state structure to hold the configuration data, and they > > > skip the operation if either is missing. > > > > > > Look for the pci_cap_saved_state first so if we don't have one, we can skip > > > searching for the device capability, which requires several slow config > > > space accesses. > > > > +++ b/drivers/pci/vc.c > > > @@ -355,20 +355,17 @@ int pci_save_vc_state(struct pci_dev *dev) > > > int i; > > > > > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > > > - int pos, ret; > > > struct pci_cap_saved_state *save_state; > > > + int pos, ret; > > > + > > > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > > + if (!save_state) > > > + return -ENOMEM; > > > > > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > > > if (!pos) > > > continue; > > > > > > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > > - if (!save_state) { > > > - pci_err(dev, "%s buffer not found in %s\n", > > > - vc_caps[i].name, __func__); > > > - return -ENOMEM; > > > - } > > > > I think this order change will cause a functional change because > > pci_allocate_vc_save_buffers() only allocated for those capabilities that > > are exist for dev. Thus, the loop will prematurely exit. > > Oof, thank you for catching this! I'll drop this for now. > > It would be nice to make pci_save_vc_state() parallel with > pci_restore_vc_state() (and with most other pci_save_*_state() > functions) and have it return void. But pci_save_state() returns the > pci_save_vc_state() return value, and there are ~20 pci_save_state() > callers that pay attention to that return value. > > I'm not convinced there's real value in pci_save_state() error > returns, given that so few callers check it, but it definitely > requires more analysis before removing it. Indeed, I also though that -ENOMEM even in the original is questionable. These are not the real sources of the failure but just secondary effect from the failure that occurred earlier in _pci_add_cap_save_buffer(). -- i. > > > ret = pci_vc_do_save_buffer(dev, pos, save_state, true); > > > if (ret) { > > > pci_err(dev, "%s save unsuccessful %s\n", > > > @@ -392,12 +389,15 @@ void pci_restore_vc_state(struct pci_dev *dev) > > > int i; > > > > > > for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { > > > - int pos; > > > struct pci_cap_saved_state *save_state; > > > + int pos; > > > + > > > + save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > > + if (!save_state) > > > + continue; > > > > > > pos = pci_find_ext_capability(dev, vc_caps[i].id); > > > - save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); > > > - if (!save_state || !pos) > > > + if (!pos) > > > continue; > > > > > > pci_vc_do_save_buffer(dev, pos, save_state, false); ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] PCI: Cache offset of Resizable BAR capability 2025-02-08 5:03 [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas 2025-02-08 5:03 ` [PATCH 1/2] PCI: Avoid pointless capability searches Bjorn Helgaas @ 2025-02-08 5:03 ` Bjorn Helgaas 2025-02-13 13:54 ` Ilpo Järvinen 2025-02-12 22:35 ` [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas 2 siblings, 1 reply; 8+ messages in thread From: Bjorn Helgaas @ 2025-02-08 5:03 UTC (permalink / raw) To: Alex Williamson, Christian König Cc: linux-pci, linux-kernel, Bjorn Helgaas From: Bjorn Helgaas <bhelgaas@google.com> Previously most resizable BAR interfaces (pci_rebar_get_possible_sizes(), pci_rebar_set_size(), etc) as well as pci_restore_state() searched config space for a Resizable BAR capability. Most devices don't have such a capability, so this is wasted effort, especially for pci_restore_state(). Search for a Resizable BAR capability once at enumeration-time and cache the offset so we don't have to search every time we need it. No functional change intended. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> --- drivers/pci/pci.c | 9 +++++++-- drivers/pci/pci.h | 1 + drivers/pci/probe.c | 1 + include/linux/pci.h | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 503376bf7e75..cf2632080a94 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1872,7 +1872,7 @@ static void pci_restore_rebar_state(struct pci_dev *pdev) unsigned int pos, nbars, i; u32 ctrl; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); + pos = pdev->rebar_cap; if (!pos) return; @@ -3719,6 +3719,11 @@ void pci_acs_init(struct pci_dev *dev) pci_enable_acs(dev); } +void pci_rebar_init(struct pci_dev *pdev) +{ + pdev->rebar_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); +} + /** * pci_rebar_find_pos - find position of resize ctrl reg for BAR * @pdev: PCI device @@ -3733,7 +3738,7 @@ static int pci_rebar_find_pos(struct pci_dev *pdev, int bar) unsigned int pos, nbars, i; u32 ctrl; - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); + pos = pdev->rebar_cap; if (!pos) return -ENOTSUPP; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 01e51db8d285..d7b46ddfd6d2 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -799,6 +799,7 @@ static inline int acpi_get_rc_resources(struct device *dev, const char *hid, } #endif +void pci_rebar_init(struct pci_dev *pdev); int pci_rebar_get_current_size(struct pci_dev *pdev, int bar); int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size); static inline u64 pci_rebar_size_to_bytes(int size) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b6536ed599c3..24dd3dcfd223 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2564,6 +2564,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_rcec_init(dev); /* Root Complex Event Collector */ pci_doe_init(dev); /* Data Object Exchange */ pci_tph_init(dev); /* TLP Processing Hints */ + pci_rebar_init(dev); /* Resizable BAR */ pcie_report_downtraining(dev); pci_init_reset_methods(dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 47b31ad724fa..9e5bbd996c83 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -353,6 +353,7 @@ struct pci_dev { struct pci_dev *rcec; /* Associated RCEC device */ #endif u32 devcap; /* PCIe Device Capabilities */ + u16 rebar_cap; /* Resizable BAR capability offset */ u8 pcie_cap; /* PCIe capability offset */ u8 msi_cap; /* MSI capability offset */ u8 msix_cap; /* MSI-X capability offset */ -- 2.34.1 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] PCI: Cache offset of Resizable BAR capability 2025-02-08 5:03 ` [PATCH 2/2] PCI: Cache offset of Resizable BAR capability Bjorn Helgaas @ 2025-02-13 13:54 ` Ilpo Järvinen 0 siblings, 0 replies; 8+ messages in thread From: Ilpo Järvinen @ 2025-02-13 13:54 UTC (permalink / raw) To: Bjorn Helgaas Cc: Alex Williamson, Christian König, linux-pci, linux-kernel, Bjorn Helgaas [-- Attachment #1: Type: text/plain, Size: 3498 bytes --] On Fri, 7 Feb 2025, Bjorn Helgaas wrote: > From: Bjorn Helgaas <bhelgaas@google.com> > > Previously most resizable BAR interfaces (pci_rebar_get_possible_sizes(), > pci_rebar_set_size(), etc) as well as pci_restore_state() searched config > space for a Resizable BAR capability. Most devices don't have such a > capability, so this is wasted effort, especially for pci_restore_state(). > > Search for a Resizable BAR capability once at enumeration-time and cache > the offset so we don't have to search every time we need it. No functional > change intended. > > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> > --- > drivers/pci/pci.c | 9 +++++++-- > drivers/pci/pci.h | 1 + > drivers/pci/probe.c | 1 + > include/linux/pci.h | 1 + > 4 files changed, 10 insertions(+), 2 deletions(-) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 503376bf7e75..cf2632080a94 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -1872,7 +1872,7 @@ static void pci_restore_rebar_state(struct pci_dev *pdev) > unsigned int pos, nbars, i; > u32 ctrl; > > - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); > + pos = pdev->rebar_cap; > if (!pos) > return; > > @@ -3719,6 +3719,11 @@ void pci_acs_init(struct pci_dev *dev) > pci_enable_acs(dev); > } > > +void pci_rebar_init(struct pci_dev *pdev) > +{ > + pdev->rebar_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); > +} > + > /** > * pci_rebar_find_pos - find position of resize ctrl reg for BAR > * @pdev: PCI device > @@ -3733,7 +3738,7 @@ static int pci_rebar_find_pos(struct pci_dev *pdev, int bar) > unsigned int pos, nbars, i; > u32 ctrl; > > - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); > + pos = pdev->rebar_cap; > if (!pos) > return -ENOTSUPP; > > diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h > index 01e51db8d285..d7b46ddfd6d2 100644 > --- a/drivers/pci/pci.h > +++ b/drivers/pci/pci.h > @@ -799,6 +799,7 @@ static inline int acpi_get_rc_resources(struct device *dev, const char *hid, > } > #endif > > +void pci_rebar_init(struct pci_dev *pdev); > int pci_rebar_get_current_size(struct pci_dev *pdev, int bar); > int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size); > static inline u64 pci_rebar_size_to_bytes(int size) > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c > index b6536ed599c3..24dd3dcfd223 100644 > --- a/drivers/pci/probe.c > +++ b/drivers/pci/probe.c > @@ -2564,6 +2564,7 @@ static void pci_init_capabilities(struct pci_dev *dev) > pci_rcec_init(dev); /* Root Complex Event Collector */ > pci_doe_init(dev); /* Data Object Exchange */ > pci_tph_init(dev); /* TLP Processing Hints */ > + pci_rebar_init(dev); /* Resizable BAR */ > > pcie_report_downtraining(dev); > pci_init_reset_methods(dev); > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 47b31ad724fa..9e5bbd996c83 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -353,6 +353,7 @@ struct pci_dev { > struct pci_dev *rcec; /* Associated RCEC device */ > #endif > u32 devcap; /* PCIe Device Capabilities */ > + u16 rebar_cap; /* Resizable BAR capability offset */ > u8 pcie_cap; /* PCIe capability offset */ > u8 msi_cap; /* MSI capability offset */ > u8 msix_cap; /* MSI-X capability offset */ Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -- i. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] PCI: Avoid capability searches in save/restore state 2025-02-08 5:03 [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas 2025-02-08 5:03 ` [PATCH 1/2] PCI: Avoid pointless capability searches Bjorn Helgaas 2025-02-08 5:03 ` [PATCH 2/2] PCI: Cache offset of Resizable BAR capability Bjorn Helgaas @ 2025-02-12 22:35 ` Bjorn Helgaas 2 siblings, 0 replies; 8+ messages in thread From: Bjorn Helgaas @ 2025-02-12 22:35 UTC (permalink / raw) To: Alex Williamson, Christian König Cc: linux-pci, linux-kernel, Bjorn Helgaas On Fri, Feb 07, 2025 at 11:03:27PM -0600, Bjorn Helgaas wrote: > From: Bjorn Helgaas <bhelgaas@google.com> > > Reduce the number of times we search config space for PCI capabilities when > saving and restoring device state. > > Bjorn Helgaas (2): > PCI: Avoid pointless capability searches > PCI: Cache offset of Resizable BAR capability > > drivers/pci/pci.c | 36 +++++++++++++++++++++--------------- > drivers/pci/pci.h | 1 + > drivers/pci/pcie/aspm.c | 15 ++++++++------- > drivers/pci/probe.c | 1 + > drivers/pci/vc.c | 22 +++++++++++----------- > include/linux/pci.h | 1 + > 6 files changed, 43 insertions(+), 33 deletions(-) Applied to pci/enumeration for v6.15, please speak up if you see a problem. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-02-14 14:20 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-02-08 5:03 [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas 2025-02-08 5:03 ` [PATCH 1/2] PCI: Avoid pointless capability searches Bjorn Helgaas 2025-02-13 13:52 ` Ilpo Järvinen 2025-02-13 16:38 ` Bjorn Helgaas 2025-02-14 14:20 ` Ilpo Järvinen 2025-02-08 5:03 ` [PATCH 2/2] PCI: Cache offset of Resizable BAR capability Bjorn Helgaas 2025-02-13 13:54 ` Ilpo Järvinen 2025-02-12 22:35 ` [PATCH 0/2] PCI: Avoid capability searches in save/restore state Bjorn Helgaas
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.