From: David Matlack <dmatlack@google.com>
To: kexec@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-pci@vger.kernel.org
Cc: Adithya Jayachandran <ajayachandra@nvidia.com>,
Alexander Graf <graf@amazon.com>,
Alex Williamson <alex@shazbot.org>,
Bjorn Helgaas <bhelgaas@google.com>, Chris Li <chrisl@kernel.org>,
David Matlack <dmatlack@google.com>,
David Rientjes <rientjes@google.com>,
Jacob Pan <jacob.pan@linux.microsoft.com>,
Jason Gunthorpe <jgg@nvidia.com>,
Jonathan Corbet <corbet@lwn.net>,
Josh Hilke <jrhilke@google.com>,
Leon Romanovsky <leonro@nvidia.com>,
Lukas Wunner <lukas@wunner.de>, Mike Rapoport <rppt@kernel.org>,
Parav Pandit <parav@nvidia.com>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
Pranjal Shrivastava <praan@google.com>,
Pratyush Yadav <pratyush@kernel.org>,
Randy Dunlap <rdunlap@infradead.org>,
Saeed Mahameed <saeedm@nvidia.com>,
Samiullah Khawaja <skhawaja@google.com>,
Shuah Khan <skhan@linuxfoundation.org>,
Vipin Sharma <vipinsh@google.com>, William Tu <witu@nvidia.com>,
Yi Liu <yi.l.liu@intel.com>
Subject: [PATCH v9 08/13] PCI: Save and restore the ACS Control register
Date: Fri, 18 Sep 2026 20:06:34 +0000 [thread overview]
Message-ID: <20260918200640.887030-9-dmatlack@google.com> (raw)
In-Reply-To: <20260918200640.887030-1-dmatlack@google.com>
Save the ACS Control register in pci_save_state() and write it back
in pci_restore_state(), instead of recomputing the ACS controls from
scratch with pci_enable_acs().
This makes ACS symmetric with the rest of a device's saved state. Today
pci_save_state() ignores ACS entirely and pci_restore_state() re-enables
the ACS controls from the kernel's current ACS policy. As a result, a
device can come out of a reset with different ACS controls than it went
in with, e.g. any controls programmed outside of pci_enable_acs() are
silently dropped.
pci_enable_acs() runs when a driver binds to a device
(pci_dma_configure()), i.e. after pci_bus_add_device() has already saved
the device's state. Refresh the saved ACS Control register there as
well, otherwise a subsequent reset would revert ACS back to the
configuration left behind by firmware.
Devices that rely on device-specific quirks to enable an ACS equivalent
keep that configuration outside of the ACS Control register, so keep
configuring ACS from scratch for them. Do the same for devices that have
no saved ACS state at all.
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Assisted-by: Claude:claude-opus-5
Signed-off-by: David Matlack <dmatlack@google.com>
---
drivers/pci/pci.c | 66 +++++++++++++++++++++++++++++++++++++++++++-
drivers/pci/pci.h | 5 ++++
drivers/pci/quirks.c | 7 +++++
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b2879a6be5f8..dd25c01736b4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1021,6 +1021,55 @@ static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps)
caps->ctrl |= (dev->acs_capabilities & PCI_ACS_TB);
}
+/**
+ * pci_save_acs_state - save the ACS Control register
+ * @dev: the PCI device
+ *
+ * Record the ACS controls currently programmed in hardware so that
+ * pci_restore_acs_state() can reapply them after a reset.
+ */
+static void pci_save_acs_state(struct pci_dev *dev)
+{
+ struct pci_cap_saved_state *save_state;
+
+ if (!dev->acs_cap)
+ return;
+
+ save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_ACS);
+ if (!save_state)
+ return;
+
+ pci_read_config_word(dev, dev->acs_cap + PCI_ACS_CTRL,
+ (u16 *)&save_state->cap.data[0]);
+}
+
+/**
+ * pci_restore_acs_state - restore the ACS Control register
+ * @dev: the PCI device
+ */
+static void pci_restore_acs_state(struct pci_dev *dev)
+{
+ struct pci_cap_saved_state *save_state = NULL;
+
+ if (dev->acs_cap && !pci_need_dev_specific_enable_acs(dev))
+ save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_ACS);
+
+ /*
+ * Devices that rely on device-specific quirks to enable an ACS
+ * equivalent keep that configuration outside of the ACS Control
+ * register, so there is nothing useful to restore for them. Configure
+ * ACS from scratch instead, which also covers devices that have no
+ * saved ACS state at all.
+ */
+ if (!save_state) {
+ pci_enable_acs(dev);
+ return;
+ }
+
+ pci_write_config_word(dev, dev->acs_cap + PCI_ACS_CTRL,
+ *(u16 *)&save_state->cap.data[0]);
+}
+
/**
* pci_enable_acs - enable ACS if hardware support it
* @dev: the PCI device
@@ -1057,6 +1106,15 @@ void pci_enable_acs(struct pci_dev *dev)
__pci_config_acs(dev, &caps, config_acs_param, 0, 0);
pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl);
+
+ /*
+ * pci_enable_acs() runs when a driver binds to the device, i.e. after
+ * pci_bus_add_device() has already saved the device's state. Refresh
+ * the saved ACS Control register so that a subsequent reset restores
+ * the controls programmed here rather than the ones left behind by
+ * firmware.
+ */
+ pci_save_acs_state(dev);
}
/**
@@ -1800,6 +1858,7 @@ int pci_save_state(struct pci_dev *dev)
pci_save_aer_state(dev);
pci_save_ptm_state(dev);
pci_save_tph_state(dev);
+ pci_save_acs_state(dev);
return pci_save_vc_state(dev);
}
EXPORT_SYMBOL(pci_save_state);
@@ -1877,7 +1936,7 @@ void pci_restore_state(struct pci_dev *dev)
pci_restore_msi_state(dev);
/* Restore ACS and IOV configuration state */
- pci_enable_acs(dev);
+ pci_restore_acs_state(dev);
pci_restore_iov_state(dev);
dev->state_saved = false;
@@ -3532,6 +3591,11 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
if (error)
pci_err(dev, "unable to allocate suspend buffer for LTR\n");
+ error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_ACS,
+ sizeof(u16));
+ if (error)
+ pci_err(dev, "unable to allocate suspend buffer for ACS\n");
+
pci_allocate_vc_save_buffers(dev);
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index ba3c3fddddc2..037c1674f164 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1095,6 +1095,7 @@ void pci_acs_init(struct pci_dev *dev);
void pci_enable_acs(struct pci_dev *dev);
#ifdef CONFIG_PCI_QUIRKS
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
+bool pci_need_dev_specific_enable_acs(struct pci_dev *dev);
int pci_dev_specific_enable_acs(struct pci_dev *dev);
int pci_dev_specific_disable_acs_redir(struct pci_dev *dev);
void pci_disable_broken_acs_cap(struct pci_dev *pdev);
@@ -1105,6 +1106,10 @@ static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
{
return -ENOTTY;
}
+static inline bool pci_need_dev_specific_enable_acs(struct pci_dev *dev)
+{
+ return false;
+}
static inline int pci_dev_specific_enable_acs(struct pci_dev *dev)
{
return -ENOTTY;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7aee30734303..e500c202d2ec 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -5476,6 +5476,13 @@ static const struct pci_dev_acs_ops *pci_dev_acs_ops_get(struct pci_dev *dev)
return NULL;
}
+bool pci_need_dev_specific_enable_acs(struct pci_dev *dev)
+{
+ const struct pci_dev_acs_ops *p = pci_dev_acs_ops_get(dev);
+
+ return p && p->enable_acs;
+}
+
int pci_dev_specific_enable_acs(struct pci_dev *dev)
{
const struct pci_dev_acs_ops *p = pci_dev_acs_ops_get(dev);
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-18 20:07 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 20:06 [PATCH v9 00/13] PCI: liveupdate: PCI core support for Live Update David Matlack
2026-09-18 20:06 ` [PATCH v9 01/13] PCI: liveupdate: Set up FLB handler for the PCI core David Matlack
2026-09-18 20:15 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 02/13] PCI: liveupdate: Track outgoing preserved PCI devices David Matlack
2026-09-18 20:23 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 03/13] PCI: liveupdate: Track incoming " David Matlack
2026-09-18 20:20 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 04/13] PCI: liveupdate: Document driver binding responsibilities David Matlack
2026-09-18 20:09 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 05/13] PCI: liveupdate: Auto-preserve upstream bridges across Live Update David Matlack
2026-09-18 20:14 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 06/13] PCI: liveupdate: Preserve bus numbers during " David Matlack
2026-09-18 20:13 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 07/13] PCI: Refactor matching logic for pci_dev_acs_ops David Matlack
2026-09-18 20:13 ` sashiko-bot
2026-09-18 20:06 ` David Matlack [this message]
2026-09-18 20:15 ` [PATCH v9 08/13] PCI: Save and restore the ACS Control register sashiko-bot
2026-09-19 1:18 ` Alex Williamson
2026-09-18 20:06 ` [PATCH v9 09/13] PCI: liveupdate: Adopt ACS controls in incoming preserved devices David Matlack
2026-09-18 20:13 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 10/13] PCI: liveupdate: Adopt ARI Forwarding Enable on preserved bridges David Matlack
2026-09-18 20:19 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 11/13] PCI: liveupdate: Freeze preservation status during shutdown David Matlack
2026-09-18 20:19 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 12/13] PCI: liveupdate: Do not disable bus mastering on preserved devices during kexec David Matlack
2026-09-18 20:17 ` sashiko-bot
2026-09-18 20:06 ` [PATCH v9 13/13] Documentation: PCI: Add documentation for Live Update David Matlack
2026-09-18 20:14 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260918200640.887030-9-dmatlack@google.com \
--to=dmatlack@google.com \
--cc=ajayachandra@nvidia.com \
--cc=alex@shazbot.org \
--cc=bhelgaas@google.com \
--cc=chrisl@kernel.org \
--cc=corbet@lwn.net \
--cc=graf@amazon.com \
--cc=jacob.pan@linux.microsoft.com \
--cc=jgg@nvidia.com \
--cc=jrhilke@google.com \
--cc=kexec@lists.infradead.org \
--cc=leonro@nvidia.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-pci@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=parav@nvidia.com \
--cc=pasha.tatashin@soleen.com \
--cc=praan@google.com \
--cc=pratyush@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rientjes@google.com \
--cc=rppt@kernel.org \
--cc=saeedm@nvidia.com \
--cc=skhan@linuxfoundation.org \
--cc=skhawaja@google.com \
--cc=vipinsh@google.com \
--cc=witu@nvidia.com \
--cc=yi.l.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®