* [PATCH] PCI: Add ID@path device format for pci= parameters
@ 2026-09-19 20:56 Ben Cressey
2026-09-19 21:05 ` sashiko-bot
2026-09-23 14:54 ` Wei Wang
0 siblings, 2 replies; 3+ messages in thread
From: Ben Cressey @ 2026-09-19 20:56 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Randy Dunlap, Bjorn Helgaas
Cc: linux-doc, linux-kernel, linux-pci, Krzysztof Wilczyński,
Logan Gunthorpe, Alex Williamson, Wei Wang, Jason Gunthorpe,
Anthony Vardaro (Anthropic), Ben Cressey
The <pci_dev> grammar shared by pci=resource_alignment=,
pci=disable_acs_redir= and pci=config_acs= names a device either by
address, with an optional path, or by ID. When one command line serves
more than one platform, neither form limits an entry to the intended
device: an address applies to whatever occupies it on each platform, and
an ID applies to every instance, such as all Downstream Ports of a
switch rather than the one that needs different ACS settings.
Accept pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>, where
<path> is the address format, and match only when both halves match. An
entry written for one platform is then inert on another where that
address holds a different device. For example,
pci=config_acs=xx111x1@pci:10b5:8749@0000:80:02.0/00.0/08.0
configures ACS on the Downstream Port at that path only if it is a
PEX 8749 port, and matches nothing on a system where 0000:80:02.0 leads
to some other device.
The path goes last since pci_dev_str_match_path() consumes up to the
next ';'. The <order>@ and <flags>@ prefixes of resource_alignment and
config_acs are stripped before pci_dev_str_match() is called, so the
callers are unchanged.
Reviewed-by: Anthony Vardaro (Anthropic) <me@anthonyvardaro.com>
Signed-off-by: Ben Cressey <ben@cressey.dev>
Assisted-by: LLM
---
This touches pci_dev_str_match(), as does 3/6 of Wei Wang's "PCI: Add
support for ACS Enhanced Capability" series, currently at v9:
https://lore.kernel.org/r/SI2PR01MB4393F337A792CB3258C2E073DCB62@SI2PR01MB4393.apcprd01.prod.exchangelabs.com
On current -rc this patch applies as is. If it is applied after that
3/6, the early return for a path that does not match needs to become
"ret = 0; goto out;" so the shared exit still checks and skips the
delimiter. I can respin on that base if preferred.
A pci:<IDs> entry with three or five fields is accepted by the existing
sscanf() and so bypasses the @<path> check; that predates this patch and
is rejected once that same 3/6, "PCI: Consolidate delimiter handling
into pci_dev_str_match()", is applied.
A backport of this change to a 6.18.y based tree was tested on two
server models from different vendors, both with PCIe switches whose
downstream ports share one vendor and device ID, and one boot of each
machine was examined with one command line that held config_acs entries
in the new form for both models. On each machine only the ports named
by its own entries were configured, and the bits those entries set read
back as requested, while the ports with the same vendor and device ID
at a path that only the other model's entries name were not configured.
---
Documentation/admin-guide/kernel-parameters.txt | 10 +++++++++-
drivers/pci/pci.c | 18 ++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 33cd30996e47e..3e4c618427a27 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5042,6 +5042,7 @@ Kernel parameters
[<domain>:]<bus>:<dev>.<func>[/<dev>.<func>]*
pci:<vendor>:<device>[:<subvendor>:<subdevice>]
+ pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>
Note: the first format specifies a PCI
bus/device/function address which may change
@@ -5056,7 +5057,14 @@ Kernel parameters
renumbering issues). The second format
selects devices using IDs from the
configuration space which may match multiple
- devices in the system.
+ devices in the system. The third format
+ combines the first two: the device must
+ match the IDs and also be at the address
+ given by <path>, which takes the first
+ format. This allows an entry written for a
+ device on one system to have no effect on
+ another system where the same address is
+ occupied by a different device.
earlydump dump PCI config space before the kernel
changes anything
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b2879a6be5f80..ebce05e604b88 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -343,6 +343,7 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
*
* [<domain>:]<bus>:<device>.<func>[/<device>.<func>]*
* pci:<vendor>:<device>[:<subvendor>:<subdevice>]
+ * pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>
*
* The first format specifies a PCI bus/device/function address which
* may change if new hardware is inserted, if motherboard firmware changes,
@@ -359,6 +360,12 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
* legacy reasons and convenience so users don't have to specify
* FFFFFFFFs on the command line.)
*
+ * The third format combines the first two: the device must match the IDs
+ * and also be at the address given by <path>, which takes the first
+ * format. This allows a parameter written for a device at a known
+ * address on one system to have no effect on another system where that
+ * address is occupied by a different device.
+ *
* Returns 1 if the string matches the device, 0 if it does not and
* a negative error code if the string cannot be parsed.
*/
@@ -385,6 +392,17 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
p += count;
+ /* Third format: the device must also be at <path> */
+ if (*p == '@') {
+ ret = pci_dev_str_match_path(dev, p + 1, &p);
+ if (ret < 0)
+ return ret;
+ if (!ret) {
+ *endptr = p;
+ return 0;
+ }
+ }
+
if ((!vendor || vendor == dev->vendor) &&
(!device || device == dev->device) &&
(!subsystem_vendor ||
---
base-commit: fd73f4a6659897191fa0d40695fe370925dd3780
change-id: 20260919-pci-idpath-selector-2847a8afe92c
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] PCI: Add ID@path device format for pci= parameters
2026-09-19 20:56 [PATCH] PCI: Add ID@path device format for pci= parameters Ben Cressey
@ 2026-09-19 21:05 ` sashiko-bot
2026-09-23 14:54 ` Wei Wang
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-09-19 21:05 UTC (permalink / raw)
To: Ben Cressey; +Cc: linux-pci
> The <pci_dev> grammar shared by pci=resource_alignment=,
> pci=disable_acs_redir= and pci=config_acs= names a device either by
> address, with an optional path, or by ID. When one command line serves
> more than one platform, neither form limits an entry to the intended
> device: an address applies to whatever occupies it on each platform, and
> an ID applies to every instance, such as all Downstream Ports of a
> switch rather than the one that needs different ACS settings.
>
> Accept pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>, where
> <path> is the address format, and match only when both halves match. An
> entry written for one platform is then inert on another where that
> address holds a different device. For example,
>
> pci=config_acs=xx111x1@pci:10b5:8749@0000:80:02.0/00.0/08.0
>
> configures ACS on the Downstream Port at that path only if it is a
> PEX 8749 port, and matches nothing on a system where 0000:80:02.0 leads
> to some other device.
>
> The path goes last since pci_dev_str_match_path() consumes up to the
> next ';'. The <order>@ and <flags>@ prefixes of resource_alignment and
> config_acs are stripped before pci_dev_str_match() is called, so the
> callers are unchanged.
>
> Reviewed-by: Anthony Vardaro (Anthropic) <me@anthonyvardaro.com>
> Signed-off-by: Ben Cressey <ben@cressey.dev>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260919-pci-idpath-selector-v1-1-5881de83f248@cressey.dev?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] PCI: Add ID@path device format for pci= parameters
2026-09-19 20:56 [PATCH] PCI: Add ID@path device format for pci= parameters Ben Cressey
2026-09-19 21:05 ` sashiko-bot
@ 2026-09-23 14:54 ` Wei Wang
1 sibling, 0 replies; 3+ messages in thread
From: Wei Wang @ 2026-09-23 14:54 UTC (permalink / raw)
To: Ben Cressey, Jonathan Corbet, Shuah Khan, Randy Dunlap,
Bjorn Helgaas
Cc: linux-doc, linux-kernel, linux-pci, Krzysztof Wilczyński,
Logan Gunthorpe, Alex Williamson, Jason Gunthorpe,
Anthony Vardaro (Anthropic)
On 9/20/26 4:56 AM, Ben Cressey wrote:
> The <pci_dev> grammar shared by pci=resource_alignment=,
> pci=disable_acs_redir= and pci=config_acs= names a device either by
> address, with an optional path, or by ID. When one command line serves
> more than one platform, neither form limits an entry to the intended
> device: an address applies to whatever occupies it on each platform, and
> an ID applies to every instance, such as all Downstream Ports of a
> switch rather than the one that needs different ACS settings.
>
> Accept pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>, where
> <path> is the address format, and match only when both halves match. An
> entry written for one platform is then inert on another where that
> address holds a different device. For example,
>
> pci=config_acs=xx111x1@pci:10b5:8749@0000:80:02.0/00.0/08.0
>
> configures ACS on the Downstream Port at that path only if it is a
> PEX 8749 port, and matches nothing on a system where 0000:80:02.0 leads
> to some other device.
>
> The path goes last since pci_dev_str_match_path() consumes up to the
> next ';'. The <order>@ and <flags>@ prefixes of resource_alignment and
> config_acs are stripped before pci_dev_str_match() is called, so the
> callers are unchanged.
>
> Reviewed-by: Anthony Vardaro (Anthropic) <me@anthonyvardaro.com>
> Signed-off-by: Ben Cressey <ben@cressey.dev>
> Assisted-by: LLM
> ---
> This touches pci_dev_str_match(), as does 3/6 of Wei Wang's "PCI: Add
> support for ACS Enhanced Capability" series, currently at v9:
> https://lore.kernel.org/r/SI2PR01MB4393F337A792CB3258C2E073DCB62@SI2PR01MB4393.apcprd01.prod.exchangelabs.com
> On current -rc this patch applies as is. If it is applied after that
> 3/6, the early return for a path that does not match needs to become
> "ret = 0; goto out;" so the shared exit still checks and skips the
> delimiter. I can respin on that base if preferred.
>
> A pci:<IDs> entry with three or five fields is accepted by the existing
> sscanf() and so bypasses the @<path> check; that predates this patch and
> is rejected once that same 3/6, "PCI: Consolidate delimiter handling
> into pci_dev_str_match()", is applied.
>
> A backport of this change to a 6.18.y based tree was tested on two
> server models from different vendors, both with PCIe switches whose
> downstream ports share one vendor and device ID, and one boot of each
> machine was examined with one command line that held config_acs entries
> in the new form for both models. On each machine only the ports named
> by its own entries were configured, and the bits those entries set read
> back as requested, while the ports with the same vendor and device ID
> at a path that only the other model's entries name were not configured.
> ---
> Documentation/admin-guide/kernel-parameters.txt | 10 +++++++++-
> drivers/pci/pci.c | 18 ++++++++++++++++++
> 2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 33cd30996e47e..3e4c618427a27 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -5042,6 +5042,7 @@ Kernel parameters
>
> [<domain>:]<bus>:<dev>.<func>[/<dev>.<func>]*
> pci:<vendor>:<device>[:<subvendor>:<subdevice>]
> + pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>
>
> Note: the first format specifies a PCI
> bus/device/function address which may change
> @@ -5056,7 +5057,14 @@ Kernel parameters
> renumbering issues). The second format
> selects devices using IDs from the
> configuration space which may match multiple
> - devices in the system.
> + devices in the system. The third format
> + combines the first two: the device must
> + match the IDs and also be at the address
> + given by <path>, which takes the first
> + format. This allows an entry written for a
> + device on one system to have no effect on
> + another system where the same address is
> + occupied by a different device.
>
> earlydump dump PCI config space before the kernel
> changes anything
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index b2879a6be5f80..ebce05e604b88 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -343,6 +343,7 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
> *
> * [<domain>:]<bus>:<device>.<func>[/<device>.<func>]*
> * pci:<vendor>:<device>[:<subvendor>:<subdevice>]
> + * pci:<vendor>:<device>[:<subvendor>:<subdevice>]@<path>
> *
> * The first format specifies a PCI bus/device/function address which
> * may change if new hardware is inserted, if motherboard firmware changes,
> @@ -359,6 +360,12 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
> * legacy reasons and convenience so users don't have to specify
> * FFFFFFFFs on the command line.)
> *
> + * The third format combines the first two: the device must match the IDs
> + * and also be at the address given by <path>, which takes the first
> + * format. This allows a parameter written for a device at a known
> + * address on one system to have no effect on another system where that
> + * address is occupied by a different device.
> + *
> * Returns 1 if the string matches the device, 0 if it does not and
> * a negative error code if the string cannot be parsed.
> */
> @@ -385,6 +392,17 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
>
> p += count;
>
> + /* Third format: the device must also be at <path> */
> + if (*p == '@') {
> + ret = pci_dev_str_match_path(dev, p + 1, &p);
> + if (ret < 0)
> + return ret;
> + if (!ret) {
> + *endptr = p;
> + return 0;
> + }
> + }
> +
How about checking the path only for devices whose IDs match, i.e. moving
this under the ID comparison below?
That avoids walking the path (and its kmemdup_nul allocation) for devices that can't
match anyway.
Note that the devices whose IDs don't match would then no longer go through
pci_dev_str_match_path(), which is what currently advances p past the
path. So need to skip it explicitly, otherwise *endptr is left at
'@' and the caller will stop parsing the remaining entries, e.g. adding
else if (*p == '@') {
p = strchrnul(p, ';');
}
> if ((!vendor || vendor == dev->vendor) &&
> (!device || device == dev->device) &&
> (!subsystem_vendor ||
>
> ---
> base-commit: fd73f4a6659897191fa0d40695fe370925dd3780
> change-id: 20260919-pci-idpath-selector-2847a8afe92c
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-23 14:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19 20:56 [PATCH] PCI: Add ID@path device format for pci= parameters Ben Cressey
2026-09-19 21:05 ` sashiko-bot
2026-09-23 14:54 ` Wei Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox