* [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability
@ 2026-02-16 2:26 Wei Wang
2026-02-16 2:26 ` [PATCH v5 1/6] PCI: Validate ACS enable flags against device-specific ACS capabilities Wei Wang
` (5 more replies)
0 siblings, 6 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
This patchset improves the core ACS implementation and adds support for
the Access Control Services (ACS) Enhanced Capability, introduced with
PCIe Gen 5.
Improvements to the core ACS implementation include:
- Validating ACS enable flags against device-specific capabilities rather
than generic kernel masks. This ensures only supported features are
enabled while safely ignoring attempts to disable unsupported bits.
- Consolidating delimiter parsing into pci_dev_str_match() and returning
-ENODEV when no further entries can be parsed. This removes duplicated
logic in callers.
- Refactoring ACS parameter handling by splitting the intertwined
disable_acs_redir and config_acs param logic into dedicated functions.
This improves maintainability and robustness while optimizing parsing
with better validation and readability.
- Updating the config_acs kernel parameter documentation to include an
example of multi-device configuration with distinct settings and
advising users to quote the parameter to avoid bootloader parsing
issues with the semicolon separator.
Support for the ACS Enhanced Capability is built on top of this improved
implementation. This capability provides additional access control
features that improve device isolation — particularly important in
virtualization scenarios where devices are passed through to different
virtual machines (VMs). Strong isolation is critical to ensure security
between devices assigned to different VMs and the host.
In Linux, device grouping assumes that devices in separate IOMMU groups
are properly isolated. To uphold this assumption, the enhanced ACS
controls are enabled by default on hardware that supports the PCI_ACS_ECAP
capability. As with other basic ACS access controls, these new controls
can be configured via the config_acs= boot parameter.
Support for checking the enhanced ACS controls on Root and Downstream
Ports has been added to pci_acs_enabled(). On devices that support
PCI_ACS_ECAP, these controls must be properly enabled. To maintain
compatibility with legacy devices that lack PCI_ACS_ECAP support,
pci_acs_enabled() simply skips the check.
v4->v5 changes:
- Added significant refactoring of the core ACS implementation (Patches
1-4) to improve validation, safety, and readability;
- For USP and DSP Memory Target Access Control, added masks and enum
values for the encodings and explicitly rejected the reserved encoding
(0b11);
- In pci_acs_ecap_enabled(), removed the use of 'is_dsp' variable.
v4 Link: https://lore.kernel.org/all/SI2PR01MB43932C799AE9111C7D2C319FDC65A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v3->v4 changes:
- In pci_acs_ecap_enabled(): Check the pcie type for
PCI_EXP_TYPE_DOWNSTREAM explicitly.
v3 Link: https://lore.kernel.org/all/SI2PR01MB439325B4E44D5A39F34A4015DC9AA@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v2->v3 changes:
- Drop the warning when a device has no support for the enhanced
capability.
v2 Link: https://lore.kernel.org/all/SI2PR01MB4393B836EA4FEDD1823483BADC94A@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
v1->v2 changes:
- Enabled all enhanced ACS controls by default, rather than just Unclaimed
Request Redirect (which addressed the primary issue we encountered).
- Added checks for enhanced ACS controls on Root and Downstream Ports in
pci_acs_enabled() to ensure proper enablement when grouping devices or
enabling features such as IOMMU PASID.
v1 Link: https://lore.kernel.org/all/SI2PR01MB43931A911357962A5E986FFEDC8CA@SI2PR01MB4393.apcprd01.prod.exchangelabs.com/
Thanks to Jason Gunthorpe and Jonathan Cameron for reviewing the patchset.
Wei Wang (6):
PCI: Validate ACS enable flags against device-specific ACS
capabilities
Documentation/kernel-parameters: Add multi-device config_acs example
PCI: Consolidate delimiter handling into pci_dev_str_match()
PCI: Refactor disable_acs_redir and config_acs param handling
PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP
PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled()
.../admin-guide/kernel-parameters.txt | 32 ++-
drivers/pci/pci.c | 271 ++++++++++++------
include/uapi/linux/pci_regs.h | 13 +
3 files changed, 221 insertions(+), 95 deletions(-)
base-commit: 635c467cc14ebdffab3f77610217c1dacaf88e8c
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 1/6] PCI: Validate ACS enable flags against device-specific ACS capabilities
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 2/6] Documentation/kernel-parameters: Add multi-device config_acs example Wei Wang
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
The ACS flag validation used the kernel's full set of ACS control bits,
which allowed users to request ACS features that the device does not
support. These unsupported bits would be silently ignored by hardware.
Validate the requested enable flags against dev->acs_capabilities so
that only device-supported ACS bits are accepted. Accordingly, move the
check after the device is matched, since the enable bits apply only to
the matched device.
Also change the validation to apply only to bits being enabled, since
attempting to disable unsupported features does not cause functional
issues.
Finally, improve the error message to report which invalid bits were
requested.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
---
drivers/pci/pci.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f3244630bfd0..8973658441ec 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -941,12 +941,6 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps,
}
}
- if (mask & ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | PCI_ACS_CR |
- PCI_ACS_UF | PCI_ACS_EC | PCI_ACS_DT)) {
- pci_err(dev, "Invalid ACS flags specified\n");
- return;
- }
-
ret = pci_dev_str_match(dev, p, &p);
if (ret < 0) {
pr_info_once("PCI: Can't parse ACS command line parameter\n");
@@ -969,6 +963,12 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps,
if (!pci_dev_specific_disable_acs_redir(dev))
return;
+ if (flags & ~dev->acs_capabilities) {
+ pci_err(dev, "Invalid ACS enable flags specified: %#06x\n",
+ (u16)(flags & ~dev->acs_capabilities));
+ return;
+ }
+
pci_dbg(dev, "ACS mask = %#06x\n", mask);
pci_dbg(dev, "ACS flags = %#06x\n", flags);
pci_dbg(dev, "ACS control = %#06x\n", caps->ctrl);
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 2/6] Documentation/kernel-parameters: Add multi-device config_acs example
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
2026-02-16 2:26 ` [PATCH v5 1/6] PCI: Validate ACS enable flags against device-specific ACS capabilities Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match() Wei Wang
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
The config_acs parameter allows configuring ACS settings for multiple PCI
devices by separating entries with semicolons. The current documentation
only illustrates applying one configuration pattern to all devices, but
does not show how to specify multiple devices with different ACS settings
in a single parameter. Add an example demonstrating multi-device usage
with distinct ACS configurations.
Some bootloaders interpret ';' as a command separator, which can cause
the parameter to be split as multiple commands. Document that the entire
parameter may need to be quoted to avoid bootloader parsing issues. This
avoids confusing bootloader errors such as ‘can't find command <BDF>’
when passing multiple device entries.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
---
Documentation/admin-guide/kernel-parameters.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cb850e5290c2..bfd13197658f 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5293,15 +5293,20 @@ Kernel parameters
'1' – force enabled
'x' – unchanged
For example,
- pci=config_acs=10x@pci:0:0
+ - pci=config_acs=10x@pci:0:0
would configure all devices that support
ACS to enable P2P Request Redirect, disable
Translation Blocking, and leave Source
Validation unchanged from whatever power-up
or firmware set it to.
-
Note: this may remove isolation between devices
and may put more devices in an IOMMU group.
+ - 'pci=config_acs=10x@0000:04:00.0;1x101@0000:84:00.0'
+ configures two devices with different ACS settings.
+ Note: Some bootloaders interpret ';' as a command
+ separator. If so, quote the entire parameter to
+ ensure it is passed to the kernel unchanged.
+
force_floating [S390] Force usage of floating interrupts.
nomio [S390] Do not use MIO instructions.
norid [S390] ignore the RID field and force use of
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
2026-02-16 2:26 ` [PATCH v5 1/6] PCI: Validate ACS enable flags against device-specific ACS capabilities Wei Wang
2026-02-16 2:26 ` [PATCH v5 2/6] Documentation/kernel-parameters: Add multi-device config_acs example Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
2026-02-19 7:12 ` Dan Carpenter
2026-02-16 2:26 ` [PATCH v5 4/6] PCI: Refactor disable_acs_redir and config_acs param handling Wei Wang
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
Callers of pci_dev_str_match() manually checked for the ';' or ','
delimiter and advanced the parameter pointer past it. Move this common
logic into pci_dev_str_match() so callers no longer need to duplicate it.
When no delimiter is found (end of parameter list or malformed entry),
pci_dev_str_match() now returns -ENODEV to indicate that no further entries
can be parsed, preserving the previous caller behavior of stopping parsing.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
---
drivers/pci/pci.c | 43 +++++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8973658441ec..0f0b384e782f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -344,7 +344,7 @@ static int pci_dev_str_match_path(struct pci_dev *dev, const char *path,
* pci_dev_str_match - test if a string matches a device
* @dev: the PCI device to test
* @p: string to match the device against
- * @endptr: pointer to the string after the match
+ * @endptr: pointer to the string after the match, with the delimiter skipped
*
* Test if a string (typically from a kernel parameter) matches a specified
* PCI device. The string may be of one of the following formats:
@@ -384,8 +384,10 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
&subsystem_vendor, &subsystem_device, &count);
if (ret != 4) {
ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count);
- if (ret != 2)
- return -EINVAL;
+ if (ret != 2) {
+ ret = -EINVAL;
+ goto not_found;
+ }
subsystem_vendor = 0;
subsystem_device = 0;
@@ -407,16 +409,28 @@ static int pci_dev_str_match(struct pci_dev *dev, const char *p,
*/
ret = pci_dev_str_match_path(dev, p, &p);
if (ret < 0)
- return ret;
+ goto not_found;
else if (ret)
goto found;
}
- *endptr = p;
- return 0;
+not_found:
+ if (ret < 0)
+ pr_err("PCI: Can't parse parameter: %s\n", p);
+
+ if (*p != ';' && *p != ',') {
+ /*
+ * End of param or invalid format. Return -ENODEV so the caller
+ * stops parsing.
+ */
+ return -ENODEV;
+ }
+
+ *endptr = p + 1;
+ return ret;
found:
- *endptr = p;
+ *endptr = *p == '\0' ? p : p + 1;
return 1;
}
@@ -943,18 +957,11 @@ static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps,
ret = pci_dev_str_match(dev, p, &p);
if (ret < 0) {
- pr_info_once("PCI: Can't parse ACS command line parameter\n");
break;
} else if (ret == 1) {
/* Found a match */
break;
}
-
- if (*p != ';' && *p != ',') {
- /* End of param or invalid format */
- break;
- }
- p++;
}
if (ret != 1)
@@ -6382,16 +6389,8 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
align = 1ULL << align_order;
break;
} else if (ret < 0) {
- pr_err("PCI: Can't parse resource_alignment parameter: %s\n",
- p);
break;
}
-
- if (*p != ';' && *p != ',') {
- /* End of param or invalid format */
- break;
- }
- p++;
}
out:
spin_unlock(&resource_alignment_lock);
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 4/6] PCI: Refactor disable_acs_redir and config_acs param handling
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
` (2 preceding siblings ...)
2026-02-16 2:26 ` [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match() Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP Wei Wang
2026-02-16 2:26 ` [PATCH v5 6/6] PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled() Wei Wang
5 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
The current implementation mixes disable_acs_redir and config_acs param
processing inside __pci_config_acs(), using acs_mask==0 as an implicit
signal to switch into config_acs_param mode. The intertwined logic is
hard to follow and easy to break:
- The acs_mask==0 special case is non-obvious and obscures which code
paths apply to which parameter.
- The interleaved logic is fragile; changes intended for one parameter
can unintentionally affect the other. For example,
pci_dev_specific_disable_acs_redir() is invoked on the common path
even though it should apply only to disable_acs_redir.
Split the two behaviors into dedicated functions,
pci_param_disable_acs_redir() and pci_param_config_acs(), making the
control flow explicit and easier to maintain.
The new pci_param_config_acs() implementation also improves on the
original logic:
- It searches for the matching device first and parses ACS flags only
for the matched device, avoiding unnecessary work.
- A switch statement replaces multiple if/else blocks, improving
readability.
- Bounds checking (max_shift) prevents overrunning the device’s ACS
capability bits.
- Variable names (enabled_bits, disabled_bits) more clearly express
their roles compared to the previous mask/flags pair.
- Error messages are simplified to reduce dmesg noise.
This refactor separates concerns, improves robustness, and makes future
extensions to ACS parameter handling safer and easier to review.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
---
drivers/pci/pci.c | 168 +++++++++++++++++++++++++++-------------------
1 file changed, 98 insertions(+), 70 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0f0b384e782f..4b32fbbcacb6 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -907,87 +907,117 @@ struct pci_acs {
u16 fw_ctrl;
};
-static void __pci_config_acs(struct pci_dev *dev, struct pci_acs *caps,
- const char *p, const u16 acs_mask, const u16 acs_flags)
+static bool pci_dev_match_disable_acs_redir(struct pci_dev *dev, const char *p)
{
- u16 flags = acs_flags;
- u16 mask = acs_mask;
- char *delimit;
int ret = 0;
- if (!p)
- return;
-
while (*p) {
- if (!acs_mask) {
- /* Check for ACS flags */
- delimit = strstr(p, "@");
- if (delimit) {
- int end;
- u32 shift = 0;
-
- end = delimit - p - 1;
- mask = 0;
- flags = 0;
-
- while (end > -1) {
- if (*(p + end) == '0') {
- mask |= 1 << shift;
- shift++;
- end--;
- } else if (*(p + end) == '1') {
- mask |= 1 << shift;
- flags |= 1 << shift;
- shift++;
- end--;
- } else if ((*(p + end) == 'x') || (*(p + end) == 'X')) {
- shift++;
- end--;
- } else {
- pci_err(dev, "Invalid ACS flags... Ignoring\n");
- return;
- }
- }
- p = delimit + 1;
- } else {
- pci_err(dev, "ACS Flags missing\n");
- return;
- }
- }
-
ret = pci_dev_str_match(dev, p, &p);
- if (ret < 0) {
+ if (ret == 1)
+ return true;
+ else if (ret < 0)
break;
- } else if (ret == 1) {
- /* Found a match */
- break;
- }
}
- if (ret != 1)
+ return false;
+}
+
+static void pci_param_disable_acs_redir(struct pci_dev *dev,
+ struct pci_acs *caps)
+{
+ u16 acs_redir_mask = PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC;
+
+ if (!disable_acs_redir_param ||
+ !pci_dev_match_disable_acs_redir(dev, disable_acs_redir_param) ||
+ !pci_dev_specific_disable_acs_redir(dev))
return;
- if (!pci_dev_specific_disable_acs_redir(dev))
- return;
+ caps->ctrl = caps->fw_ctrl & ~acs_redir_mask;
+}
- if (flags & ~dev->acs_capabilities) {
- pci_err(dev, "Invalid ACS enable flags specified: %#06x\n",
- (u16)(flags & ~dev->acs_capabilities));
- return;
- }
-
- pci_dbg(dev, "ACS mask = %#06x\n", mask);
- pci_dbg(dev, "ACS flags = %#06x\n", flags);
- pci_dbg(dev, "ACS control = %#06x\n", caps->ctrl);
- pci_dbg(dev, "ACS fw_ctrl = %#06x\n", caps->fw_ctrl);
+static const char *pci_dev_match_config_acs(struct pci_dev *dev, const char *p)
+{
+ const char *seg;
+ int ret;
/*
- * For mask bits that are 0, copy them from the firmware setting
- * and apply flags for all the mask bits that are 1.
+ * Example: 11101010x@0000:01:00.0;101x@0000:02:00.0;1@0000:03:00.0
+ * Three segments delimited via ';'. @seg always points to the start
+ * of a segment and p advances to the start of the device id (BDF)
+ * after '@'. Upon match, return the start of the matching segment.
*/
- caps->ctrl = (caps->fw_ctrl & ~mask) | (flags & mask);
+ while (*p) {
+ seg = p;
+ p = strchr(seg, '@');
+ /* If malformed string, stop parsing. */
+ if (!p || p == seg)
+ break;
- pci_info(dev, "Configured ACS to %#06x\n", caps->ctrl);
+ p++;
+ /* pci_dev_str_match() updates p to the next segment. */
+ ret = pci_dev_str_match(dev, p, &p);
+ if (ret == 1)
+ return seg;
+ else if (ret < 0)
+ break;
+ }
+
+ return NULL;
+}
+
+static void pci_param_config_acs(struct pci_dev *dev, struct pci_acs *caps)
+{
+ u16 shift = 0, max_shift = fls(dev->acs_capabilities) - 1;
+ u16 enabled_bits = 0, disabled_bits = 0;
+ const char *p, *seg;
+
+ if (!config_acs_param)
+ return;
+
+ seg = pci_dev_match_config_acs(dev, config_acs_param);
+ if (!seg)
+ return;
+
+ p = strchr(seg, '@');
+ /* Parse bitstring backwards from '@' */
+ while (p > seg) {
+ if (shift > max_shift) {
+ pci_err(dev, "ACS flag bit %d exceed range %d\n",
+ shift, max_shift);
+ return;
+ }
+
+ switch (*--p) {
+ case '1':
+ enabled_bits |= BIT(shift);
+ break;
+ case '0':
+ disabled_bits |= BIT(shift);
+ break;
+ case 'x':
+ case 'X':
+ /* Skip this bit */
+ break;
+ default:
+ pci_err(dev, "Invalid ACS flag character '%c'\n", *p);
+ return;
+ }
+ shift++;
+ }
+
+ if (enabled_bits & ~dev->acs_capabilities) {
+ pci_err(dev, "Invalid ACS enable flags specified: %#06x\n",
+ (u16)(enabled_bits & ~dev->acs_capabilities));
+ return;
+ }
+
+ pci_dbg(dev, "ACS enabled: %#06x, disabled: %#06x\n",
+ enabled_bits, disabled_bits);
+
+ caps->ctrl = (caps->fw_ctrl | enabled_bits) & ~disabled_bits;
+
+ pci_info(dev, "Configured ACS to %#06x (FW default: %#06x)\n",
+ caps->ctrl, caps->fw_ctrl);
}
/**
@@ -1044,10 +1074,8 @@ void pci_enable_acs(struct pci_dev *dev)
* Always apply caps from the command line, even if there is no iommu.
* Trust that the admin has a reason to change the ACS settings.
*/
- __pci_config_acs(dev, &caps, disable_acs_redir_param,
- PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC,
- ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC));
- __pci_config_acs(dev, &caps, config_acs_param, 0, 0);
+ pci_param_disable_acs_redir(dev, &caps);
+ pci_param_config_acs(dev, &caps);
pci_write_config_word(dev, pos + PCI_ACS_CTRL, caps.ctrl);
}
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
` (3 preceding siblings ...)
2026-02-16 2:26 ` [PATCH v5 4/6] PCI: Refactor disable_acs_redir and config_acs param handling Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
2026-02-16 2:34 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 6/6] PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled() Wei Wang
5 siblings, 1 reply; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
The ACS Enhanced Capability introduces several new access controls to
improve device isolation. These new controls are particularly important
for device passthrough in virtualization scenarios.
For example, a DMA transaction from a device may target a guest physical
address that lies within the memory aperture of the switch's upstream
port, but not within any memory aperture or BAR space of a downstream
port. In such cases, the switch would generate an Unsupported Request (UR)
response to the device, which is undesirable. Enabling Unclaimed Request
Redirect Control ensures that these DMA requests are forwarded upstream
instead of being rejected.
The ACS DSP and USP Memory Target Access Control and ACS I/O Request
Blocking features similarly enhance device isolation. Device grouping in
Linux assumes that devices are properly isolated. Therefore, enable these
controls by default if PCI_ACS_ECAP is supported by the hardware. As with
other basic ACS access controls, these new controls can be configured via
the "config_acs=" boot parameter.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
.../admin-guide/kernel-parameters.txt | 23 +++++++++++++------
drivers/pci/pci.c | 10 ++++++++
include/uapi/linux/pci_regs.h | 13 +++++++++++
3 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index bfd13197658f..f8444fea9914 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5281,13 +5281,22 @@ Kernel parameters
flags.
ACS Flags is defined as follows:
- bit-0 : ACS Source Validation
- bit-1 : ACS Translation Blocking
- bit-2 : ACS P2P Request Redirect
- bit-3 : ACS P2P Completion Redirect
- bit-4 : ACS Upstream Forwarding
- bit-5 : ACS P2P Egress Control
- bit-6 : ACS Direct Translated P2P
+ bit-0 : ACS Source Validation
+ bit-1 : ACS Translation Blocking
+ bit-2 : ACS P2P Request Redirect
+ bit-3 : ACS P2P Completion Redirect
+ bit-4 : ACS Upstream Forwarding
+ bit-5 : ACS P2P Egress Control
+ bit-6 : ACS Direct Translated P2P
+ bit-7 : ACS I/O Request Blocking
+ bit-9:8 : ACS DSP Memory Target Access Ctrl
+ 00 : Direct Request access enabled
+ 01 : Request blocking enabled
+ 10 : Request redirect enabled
+ 11 : Reserved
+ bit-11:10 : ACS USP Memory Target Access Ctrl
+ Same encoding as bit-9:8
+ bit-12 : ACS Unclaimed Request Redirect Ctrl
Each bit can be marked as:
'0' – force disabled
'1' – force enabled
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 4b32fbbcacb6..c34780a5f886 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1039,6 +1039,16 @@ static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps)
/* Upstream Forwarding */
caps->ctrl |= (dev->acs_capabilities & PCI_ACS_UF);
+ /*
+ * Redirect Unclaimed Request Redirect Control, I/O Request Blocking,
+ * and Downstream and Upstream Port Memory Target Access Redirect.
+ */
+ if (dev->acs_capabilities & PCI_ACS_ECAP) {
+ caps->ctrl |= PCI_ACS_URRC | PCI_ACS_IB;
+ FIELD_MODIFY(PCI_ACS_DMAC_MASK, &caps->ctrl, PCI_ACS_MAC_RR);
+ FIELD_MODIFY(PCI_ACS_UMAC_MASK, &caps->ctrl, PCI_ACS_MAC_RR);
+ }
+
/* Enable Translation Blocking for external devices and noats */
if (pci_ats_disabled() || dev->external_facing || dev->untrusted)
caps->ctrl |= (dev->acs_capabilities & PCI_ACS_TB);
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index ec1c54b5a310..dcff29eb839b 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1016,6 +1016,7 @@
/* Access Control Service */
#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
+#define PCI_ACS_ECAP 0x0080 /* ACS Enhanced Capability */
#define PCI_ACS_SV 0x0001 /* Source Validation */
#define PCI_ACS_TB 0x0002 /* Translation Blocking */
#define PCI_ACS_RR 0x0004 /* P2P Request Redirect */
@@ -1023,10 +1024,22 @@
#define PCI_ACS_UF 0x0010 /* Upstream Forwarding */
#define PCI_ACS_EC 0x0020 /* P2P Egress Control */
#define PCI_ACS_DT 0x0040 /* Direct Translated P2P */
+#define PCI_ACS_IB 0x0080 /* I/O Request Blocking */
+#define PCI_ACS_DMAC_MASK 0x0300 /* DSP Memory Target Access Control */
+#define PCI_ACS_UMAC_MASK 0x0C00 /* USP Memory Target Access Control */
+#define PCI_ACS_URRC 0x1000 /* Unclaimed Request Redirect Ctrl */
#define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */
#define PCI_ACS_CTRL 0x06 /* ACS Control Register */
#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
+/* Encodings for DSP and USP Memory Target Access Control */
+enum {
+ PCI_ACS_MAC_DA = 0x0, /* Direct request access */
+ PCI_ACS_MAC_RB = 0x1, /* Request blocking */
+ PCI_ACS_MAC_RR = 0x2, /* Request redirect */
+ PCI_ACS_MAC_RSVD = 0x3, /* Reserved */
+};
+
/* SATA capability */
#define PCI_SATA_REGS 4 /* SATA REGs specifier */
#define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 6/6] PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled()
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
` (4 preceding siblings ...)
2026-02-16 2:26 ` [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP Wei Wang
@ 2026-02-16 2:26 ` Wei Wang
5 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:26 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci, wei.w.wang
The enhanced ACS controls introduced by PCIe Gen 5 ensures better device
isolation. On devices that support the PCI_ACS_ECAP capability, the
controls are required to be enabled properly:
- ACS I/O Request Blocking needs to be enabled to avoid unintended
upstream I/O requests.
- ACS DSP and USP Memory Target Access Control needs to be set with
Request Redirect or Request Blocking to ensure the Downstream and
Upstream Port memory resource ranges are not accessed by upstream
memory requests.
- ACS Unclaimed Request Redirect needs to be enabled to ensure accesses to
areas that lies within a Switch's Upstream Port memory apertures but not
within any Downstream Port memory apertures get redirected.
To maintain compatibility with legacy devices that lack PCI_ACS_ECAP
support, pci_acs_enabled() skips checking for the capability.
Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
---
drivers/pci/pci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c34780a5f886..50400f646539 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3560,6 +3560,53 @@ void pci_configure_ari(struct pci_dev *dev)
}
}
+static bool pci_dev_has_memory_bars(struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ if (pci_resource_flags(pdev, i) & IORESOURCE_MEM)
+ return true;
+ }
+
+ return false;
+}
+
+static bool pci_acs_ecap_enabled(struct pci_dev *pdev, u16 ctrl)
+{
+ /*
+ * For ACS DSP/USP Memory Target Access Control, either Request
+ * Redirect or Request Blocking must be enabled to enforce isolation.
+ * According to PCIe spec 7.0, the DSP Memory Target Access is
+ * applicable to both Root Ports and Switch Downstream Ports that have
+ * applicable Memory BAR space to protect. So if the device does not
+ * have a Memory BAR, it skips the check.
+ */
+ if (pci_dev_has_memory_bars(pdev) &&
+ FIELD_GET(PCI_ACS_DMAC_MASK, ctrl) != PCI_ACS_MAC_RB &&
+ FIELD_GET(PCI_ACS_DMAC_MASK, ctrl) != PCI_ACS_MAC_RR)
+ return false;
+
+ if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) {
+ /*
+ * The USP Memory Target Access is only applicable to
+ * downstream ports that have applicable Memory BAR space in
+ * the Switch Upstream Port to protect.
+ */
+ if (pci_dev_has_memory_bars(pci_upstream_bridge(pdev)) &&
+ FIELD_GET(PCI_ACS_UMAC_MASK, ctrl) != PCI_ACS_MAC_RB &&
+ FIELD_GET(PCI_ACS_UMAC_MASK, ctrl) != PCI_ACS_MAC_RR)
+ return false;
+
+ /* PCI_ACS_URRC is applicable to Downstream Ports only. */
+ if (!(ctrl & PCI_ACS_URRC))
+ return false;
+ }
+
+ /* PCI_ACS_IB is applicable to both Root and Downstream Ports. */
+ return !!(ctrl & PCI_ACS_IB);
+}
+
static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
{
int pos;
@@ -3577,6 +3624,19 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
acs_flags &= (pdev->acs_capabilities | PCI_ACS_EC);
pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
+
+ if (acs_flags & PCI_ACS_ECAP &&
+ pdev->acs_capabilities & PCI_ACS_ECAP) {
+ if (!pci_acs_ecap_enabled(pdev, ctrl))
+ return false;
+ /*
+ * The check for the required controls in PCI_ACS_ECAP has
+ * passed. Clear the ECAP flag and continue to check the
+ * basic ACS controls.
+ */
+ acs_flags &= ~PCI_ACS_ECAP;
+ }
+
return (ctrl & acs_flags) == acs_flags;
}
@@ -3635,6 +3695,8 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
*/
case PCI_EXP_TYPE_DOWNSTREAM:
case PCI_EXP_TYPE_ROOT_PORT:
+ /* PCI_ACS_ECAP applies to Root and Downstream Ports only */
+ acs_flags |= PCI_ACS_ECAP;
return pci_acs_flags_enabled(pdev, acs_flags);
/*
* PCIe 3.0, 6.12.1.2 specifies ACS capabilities that should be
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP
2026-02-16 2:26 ` [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP Wei Wang
@ 2026-02-16 2:34 ` Wei Wang
0 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-16 2:34 UTC (permalink / raw)
To: bhelgaas, jgg, jonathan.cameron, akpm, bp, rdunlap, alex, kevin.tian
Cc: linux-kernel, linux-pci
On 2/16/26 10:26 AM, Wei Wang wrote:
> The ACS Enhanced Capability introduces several new access controls to
> improve device isolation. These new controls are particularly important
> for device passthrough in virtualization scenarios.
>
> For example, a DMA transaction from a device may target a guest physical
> address that lies within the memory aperture of the switch's upstream
> port, but not within any memory aperture or BAR space of a downstream
> port. In such cases, the switch would generate an Unsupported Request (UR)
> response to the device, which is undesirable. Enabling Unclaimed Request
> Redirect Control ensures that these DMA requests are forwarded upstream
> instead of being rejected.
>
> The ACS DSP and USP Memory Target Access Control and ACS I/O Request
> Blocking features similarly enhance device isolation. Device grouping in
> Linux assumes that devices are properly isolated. Therefore, enable these
> controls by default if PCI_ACS_ECAP is supported by the hardware. As with
> other basic ACS access controls, these new controls can be configured via
> the "config_acs=" boot parameter.
>
> Signed-off-by: Wei Wang <wei.w.wang@hotmail.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Hi Jason,
I kept your Reviewed-by, but this version includes some changes
(added masks and enum values for the encodings) after your review.
Please let me know if you have any comments on the updates, thanks.
> ---
> .../admin-guide/kernel-parameters.txt | 23 +++++++++++++------
> drivers/pci/pci.c | 10 ++++++++
> include/uapi/linux/pci_regs.h | 13 +++++++++++
> 3 files changed, 39 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index bfd13197658f..f8444fea9914 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -5281,13 +5281,22 @@ Kernel parameters
> flags.
>
> ACS Flags is defined as follows:
> - bit-0 : ACS Source Validation
> - bit-1 : ACS Translation Blocking
> - bit-2 : ACS P2P Request Redirect
> - bit-3 : ACS P2P Completion Redirect
> - bit-4 : ACS Upstream Forwarding
> - bit-5 : ACS P2P Egress Control
> - bit-6 : ACS Direct Translated P2P
> + bit-0 : ACS Source Validation
> + bit-1 : ACS Translation Blocking
> + bit-2 : ACS P2P Request Redirect
> + bit-3 : ACS P2P Completion Redirect
> + bit-4 : ACS Upstream Forwarding
> + bit-5 : ACS P2P Egress Control
> + bit-6 : ACS Direct Translated P2P
> + bit-7 : ACS I/O Request Blocking
> + bit-9:8 : ACS DSP Memory Target Access Ctrl
> + 00 : Direct Request access enabled
> + 01 : Request blocking enabled
> + 10 : Request redirect enabled
> + 11 : Reserved
> + bit-11:10 : ACS USP Memory Target Access Ctrl
> + Same encoding as bit-9:8
> + bit-12 : ACS Unclaimed Request Redirect Ctrl
> Each bit can be marked as:
> '0' – force disabled
> '1' – force enabled
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 4b32fbbcacb6..c34780a5f886 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1039,6 +1039,16 @@ static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps)
> /* Upstream Forwarding */
> caps->ctrl |= (dev->acs_capabilities & PCI_ACS_UF);
>
> + /*
> + * Redirect Unclaimed Request Redirect Control, I/O Request Blocking,
> + * and Downstream and Upstream Port Memory Target Access Redirect.
> + */
> + if (dev->acs_capabilities & PCI_ACS_ECAP) {
> + caps->ctrl |= PCI_ACS_URRC | PCI_ACS_IB;
> + FIELD_MODIFY(PCI_ACS_DMAC_MASK, &caps->ctrl, PCI_ACS_MAC_RR);
> + FIELD_MODIFY(PCI_ACS_UMAC_MASK, &caps->ctrl, PCI_ACS_MAC_RR);
> + }
> +
> /* Enable Translation Blocking for external devices and noats */
> if (pci_ats_disabled() || dev->external_facing || dev->untrusted)
> caps->ctrl |= (dev->acs_capabilities & PCI_ACS_TB);
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index ec1c54b5a310..dcff29eb839b 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -1016,6 +1016,7 @@
>
> /* Access Control Service */
> #define PCI_ACS_CAP 0x04 /* ACS Capability Register */
> +#define PCI_ACS_ECAP 0x0080 /* ACS Enhanced Capability */
> #define PCI_ACS_SV 0x0001 /* Source Validation */
> #define PCI_ACS_TB 0x0002 /* Translation Blocking */
> #define PCI_ACS_RR 0x0004 /* P2P Request Redirect */
> @@ -1023,10 +1024,22 @@
> #define PCI_ACS_UF 0x0010 /* Upstream Forwarding */
> #define PCI_ACS_EC 0x0020 /* P2P Egress Control */
> #define PCI_ACS_DT 0x0040 /* Direct Translated P2P */
> +#define PCI_ACS_IB 0x0080 /* I/O Request Blocking */
> +#define PCI_ACS_DMAC_MASK 0x0300 /* DSP Memory Target Access Control */
> +#define PCI_ACS_UMAC_MASK 0x0C00 /* USP Memory Target Access Control */
> +#define PCI_ACS_URRC 0x1000 /* Unclaimed Request Redirect Ctrl */
> #define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */
> #define PCI_ACS_CTRL 0x06 /* ACS Control Register */
> #define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
>
> +/* Encodings for DSP and USP Memory Target Access Control */
> +enum {
> + PCI_ACS_MAC_DA = 0x0, /* Direct request access */
> + PCI_ACS_MAC_RB = 0x1, /* Request blocking */
> + PCI_ACS_MAC_RR = 0x2, /* Request redirect */
> + PCI_ACS_MAC_RSVD = 0x3, /* Reserved */
> +};
> +
> /* SATA capability */
> #define PCI_SATA_REGS 4 /* SATA REGs specifier */
> #define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
2026-02-16 2:26 ` [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match() Wei Wang
@ 2026-02-19 7:12 ` Dan Carpenter
2026-02-19 14:39 ` Wei Wang
0 siblings, 1 reply; 10+ messages in thread
From: Dan Carpenter @ 2026-02-19 7:12 UTC (permalink / raw)
To: oe-kbuild, Wei Wang, bhelgaas, jgg, jonathan.cameron, akpm, bp,
rdunlap, alex, kevin.tian
Cc: lkp, oe-kbuild-all, linux-kernel, linux-pci, wei.w.wang
Hi Wei,
kernel test robot noticed the following build warnings:
url: https://github.com/intel-lab-lkp/linux/commits/Wei-Wang/PCI-Validate-ACS-enable-flags-against-device-specific-ACS-capabilities/20260216-103055
base: 635c467cc14ebdffab3f77610217c1dacaf88e8c
patch link: https://lore.kernel.org/r/SI2PR01MB439352E0D54243099CAAA118DC6CA%40SI2PR01MB4393.apcprd01.prod.exchangelabs.com
patch subject: [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
config: x86_64-randconfig-r072-20260216 (https://download.01.org/0day-ci/archive/20260216/202602161621.2nyGIEhM-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
smatch version: v0.5.0-8994-gd50c5a4c
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>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202602161621.2nyGIEhM-lkp@intel.com/
smatch warnings:
drivers/pci/pci.c:430 pci_dev_str_match() warn: sscanf doesn't return error codes
vim +430 drivers/pci/pci.c
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 343 /**
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 344 * pci_dev_str_match - test if a string matches a device
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 345 * @dev: the PCI device to test
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 346 * @p: string to match the device against
40549484c434de Wei Wang 2026-02-16 347 * @endptr: pointer to the string after the match, with the delimiter skipped
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 348 *
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 349 * Test if a string (typically from a kernel parameter) matches a specified
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 350 * PCI device. The string may be of one of the following formats:
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 351 *
45db33709ccc73 Logan Gunthorpe 2018-07-30 352 * [<domain>:]<bus>:<device>.<func>[/<device>.<func>]*
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 353 * pci:<vendor>:<device>[:<subvendor>:<subdevice>]
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 354 *
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 355 * The first format specifies a PCI bus/device/function address which
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 356 * may change if new hardware is inserted, if motherboard firmware changes,
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 357 * or due to changes caused in kernel parameters. If the domain is
45db33709ccc73 Logan Gunthorpe 2018-07-30 358 * left unspecified, it is taken to be 0. In order to be robust against
45db33709ccc73 Logan Gunthorpe 2018-07-30 359 * bus renumbering issues, a path of PCI device/function numbers may be used
45db33709ccc73 Logan Gunthorpe 2018-07-30 360 * to address the specific device. The path for a device can be determined
45db33709ccc73 Logan Gunthorpe 2018-07-30 361 * through the use of 'lspci -t'.
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 362 *
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 363 * The second format matches devices using IDs in the configuration
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 364 * space which may match multiple devices in the system. A value of 0
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 365 * for any field will match all devices. (Note: this differs from
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 366 * in-kernel code that uses PCI_ANY_ID which is ~0; this is for
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 367 * legacy reasons and convenience so users don't have to specify
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 368 * FFFFFFFFs on the command line.)
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 369 *
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 370 * Returns 1 if the string matches the device, 0 if it does not and
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 371 * a negative error code if the string cannot be parsed.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 372 */
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 373 static int pci_dev_str_match(struct pci_dev *dev, const char *p,
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 374 const char **endptr)
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 375 {
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 376 int ret;
45db33709ccc73 Logan Gunthorpe 2018-07-30 377 int count;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 378 unsigned short vendor, device, subsystem_vendor, subsystem_device;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 379
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 380 if (strncmp(p, "pci:", 4) == 0) {
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 381 /* PCI vendor/device (subvendor/subdevice) IDs are specified */
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 382 p += 4;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 383 ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device,
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 384 &subsystem_vendor, &subsystem_device, &count);
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 385 if (ret != 4) {
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 386 ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count);
40549484c434de Wei Wang 2026-02-16 387 if (ret != 2) {
40549484c434de Wei Wang 2026-02-16 388 ret = -EINVAL;
40549484c434de Wei Wang 2026-02-16 389 goto not_found;
40549484c434de Wei Wang 2026-02-16 390 }
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 391
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 392 subsystem_vendor = 0;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 393 subsystem_device = 0;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 394 }
At this point ret is either 2 or 4.
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 395
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 396 p += count;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 397
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 398 if ((!vendor || vendor == dev->vendor) &&
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 399 (!device || device == dev->device) &&
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 400 (!subsystem_vendor ||
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 401 subsystem_vendor == dev->subsystem_vendor) &&
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 402 (!subsystem_device ||
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 403 subsystem_device == dev->subsystem_device))
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 404 goto found;
No imagine that we don't goto found.
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 405 } else {
45db33709ccc73 Logan Gunthorpe 2018-07-30 406 /*
45db33709ccc73 Logan Gunthorpe 2018-07-30 407 * PCI Bus, Device, Function IDs are specified
45db33709ccc73 Logan Gunthorpe 2018-07-30 408 * (optionally, may include a path of devfns following it)
45db33709ccc73 Logan Gunthorpe 2018-07-30 409 */
45db33709ccc73 Logan Gunthorpe 2018-07-30 410 ret = pci_dev_str_match_path(dev, p, &p);
45db33709ccc73 Logan Gunthorpe 2018-07-30 411 if (ret < 0)
40549484c434de Wei Wang 2026-02-16 412 goto not_found;
45db33709ccc73 Logan Gunthorpe 2018-07-30 413 else if (ret)
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 414 goto found;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 415 }
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 416
40549484c434de Wei Wang 2026-02-16 417 not_found:
40549484c434de Wei Wang 2026-02-16 418 if (ret < 0)
40549484c434de Wei Wang 2026-02-16 419 pr_err("PCI: Can't parse parameter: %s\n", p);
40549484c434de Wei Wang 2026-02-16 420
40549484c434de Wei Wang 2026-02-16 421 if (*p != ';' && *p != ',') {
40549484c434de Wei Wang 2026-02-16 422 /*
40549484c434de Wei Wang 2026-02-16 423 * End of param or invalid format. Return -ENODEV so the caller
40549484c434de Wei Wang 2026-02-16 424 * stops parsing.
40549484c434de Wei Wang 2026-02-16 425 */
40549484c434de Wei Wang 2026-02-16 426 return -ENODEV;
40549484c434de Wei Wang 2026-02-16 427 }
40549484c434de Wei Wang 2026-02-16 428
40549484c434de Wei Wang 2026-02-16 429 *endptr = p + 1;
40549484c434de Wei Wang 2026-02-16 @430 return ret;
It should return 0 here but instead it returns 2 or 4.
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 431
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 432 found:
40549484c434de Wei Wang 2026-02-16 433 *endptr = *p == '\0' ? p : p + 1;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 434 return 1;
07d8d7e57c28ca Logan Gunthorpe 2018-07-30 435 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
2026-02-19 7:12 ` Dan Carpenter
@ 2026-02-19 14:39 ` Wei Wang
0 siblings, 0 replies; 10+ messages in thread
From: Wei Wang @ 2026-02-19 14:39 UTC (permalink / raw)
To: Dan Carpenter, oe-kbuild, bhelgaas, jgg, jonathan.cameron, akpm,
bp, rdunlap, alex, kevin.tian
Cc: lkp, oe-kbuild-all, linux-kernel, linux-pci
On 2/19/26 3:12 PM, Dan Carpenter wrote:
> Hi Wei,
>
> kernel test robot noticed the following build warnings:
>
> url: https://github.com/intel-lab-lkp/linux/commits/Wei-Wang/PCI-Validate-ACS-enable-flags-against-device-specific-ACS-capabilities/20260216-103055
> base: 635c467cc14ebdffab3f77610217c1dacaf88e8c
> patch link: https://lore.kernel.org/r/SI2PR01MB439352E0D54243099CAAA118DC6CA%40SI2PR01MB4393.apcprd01.prod.exchangelabs.com
> patch subject: [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match()
> config: x86_64-randconfig-r072-20260216 (https://download.01.org/0day-ci/archive/20260216/202602161621.2nyGIEhM-lkp@intel.com/config)
> compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
> smatch version: v0.5.0-8994-gd50c5a4c
>
> 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>
> | Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> | Closes: https://lore.kernel.org/r/202602161621.2nyGIEhM-lkp@intel.com/
>
> smatch warnings:
> drivers/pci/pci.c:430 pci_dev_str_match() warn: sscanf doesn't return error codes
>
> vim +430 drivers/pci/pci.c
>
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 343 /**
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 344 * pci_dev_str_match - test if a string matches a device
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 345 * @dev: the PCI device to test
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 346 * @p: string to match the device against
> 40549484c434de Wei Wang 2026-02-16 347 * @endptr: pointer to the string after the match, with the delimiter skipped
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 348 *
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 349 * Test if a string (typically from a kernel parameter) matches a specified
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 350 * PCI device. The string may be of one of the following formats:
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 351 *
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 352 * [<domain>:]<bus>:<device>.<func>[/<device>.<func>]*
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 353 * pci:<vendor>:<device>[:<subvendor>:<subdevice>]
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 354 *
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 355 * The first format specifies a PCI bus/device/function address which
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 356 * may change if new hardware is inserted, if motherboard firmware changes,
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 357 * or due to changes caused in kernel parameters. If the domain is
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 358 * left unspecified, it is taken to be 0. In order to be robust against
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 359 * bus renumbering issues, a path of PCI device/function numbers may be used
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 360 * to address the specific device. The path for a device can be determined
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 361 * through the use of 'lspci -t'.
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 362 *
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 363 * The second format matches devices using IDs in the configuration
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 364 * space which may match multiple devices in the system. A value of 0
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 365 * for any field will match all devices. (Note: this differs from
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 366 * in-kernel code that uses PCI_ANY_ID which is ~0; this is for
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 367 * legacy reasons and convenience so users don't have to specify
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 368 * FFFFFFFFs on the command line.)
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 369 *
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 370 * Returns 1 if the string matches the device, 0 if it does not and
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 371 * a negative error code if the string cannot be parsed.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 372 */
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 373 static int pci_dev_str_match(struct pci_dev *dev, const char *p,
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 374 const char **endptr)
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 375 {
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 376 int ret;
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 377 int count;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 378 unsigned short vendor, device, subsystem_vendor, subsystem_device;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 379
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 380 if (strncmp(p, "pci:", 4) == 0) {
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 381 /* PCI vendor/device (subvendor/subdevice) IDs are specified */
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 382 p += 4;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 383 ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device,
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 384 &subsystem_vendor, &subsystem_device, &count);
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 385 if (ret != 4) {
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 386 ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count);
> 40549484c434de Wei Wang 2026-02-16 387 if (ret != 2) {
> 40549484c434de Wei Wang 2026-02-16 388 ret = -EINVAL;
> 40549484c434de Wei Wang 2026-02-16 389 goto not_found;
> 40549484c434de Wei Wang 2026-02-16 390 }
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 391
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 392 subsystem_vendor = 0;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 393 subsystem_device = 0;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 394 }
>
> At this point ret is either 2 or 4.
>
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 395
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 396 p += count;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 397
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 398 if ((!vendor || vendor == dev->vendor) &&
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 399 (!device || device == dev->device) &&
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 400 (!subsystem_vendor ||
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 401 subsystem_vendor == dev->subsystem_vendor) &&
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 402 (!subsystem_device ||
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 403 subsystem_device == dev->subsystem_device))
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 404 goto found;
>
> No imagine that we don't goto found.
Thanks for catching this. This doesn’t cause a functional issue because
current callers only check for ret == 1 or ret < 0, so values like 2 or
4 are effectively treated as 0.
I think we can set "ret = 0" here, then..(see below)
>
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 405 } else {
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 406 /*
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 407 * PCI Bus, Device, Function IDs are specified
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 408 * (optionally, may include a path of devfns following it)
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 409 */
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 410 ret = pci_dev_str_match_path(dev, p, &p);
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 411 if (ret < 0)
> 40549484c434de Wei Wang 2026-02-16 412 goto not_found;
> 45db33709ccc73 Logan Gunthorpe 2018-07-30 413 else if (ret)
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 414 goto found;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 415 }
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 416
> 40549484c434de Wei Wang 2026-02-16 417 not_found:
> 40549484c434de Wei Wang 2026-02-16 418 if (ret < 0)
> 40549484c434de Wei Wang 2026-02-16 419 pr_err("PCI: Can't parse parameter: %s\n", p);
> 40549484c434de Wei Wang 2026-02-16 420
> 40549484c434de Wei Wang 2026-02-16 421 if (*p != ';' && *p != ',') {
> 40549484c434de Wei Wang 2026-02-16 422 /*
> 40549484c434de Wei Wang 2026-02-16 423 * End of param or invalid format. Return -ENODEV so the caller
> 40549484c434de Wei Wang 2026-02-16 424 * stops parsing.
> 40549484c434de Wei Wang 2026-02-16 425 */
> 40549484c434de Wei Wang 2026-02-16 426 return -ENODEV;
> 40549484c434de Wei Wang 2026-02-16 427 }
> 40549484c434de Wei Wang 2026-02-16 428
> 40549484c434de Wei Wang 2026-02-16 429 *endptr = p + 1;
> 40549484c434de Wei Wang 2026-02-16 @430 return ret;
>
> It should return 0 here but instead it returns 2 or 4.
.."ret=0" will be returned.
I changed this to "return ret" because in the earlier branch we set
ret=-EINVAL and expect that value to be returned:
if (ret != 2) {
ret = -EINVAL;
goto not_found;
}
>
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 431
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 432 found:
> 40549484c434de Wei Wang 2026-02-16 433 *endptr = *p == '\0' ? p : p + 1;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 434 return 1;
> 07d8d7e57c28ca Logan Gunthorpe 2018-07-30 435 }
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-02-19 14:40 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-16 2:26 [PATCH v5 0/6] PCI: Add support for ACS Enhanced Capability Wei Wang
2026-02-16 2:26 ` [PATCH v5 1/6] PCI: Validate ACS enable flags against device-specific ACS capabilities Wei Wang
2026-02-16 2:26 ` [PATCH v5 2/6] Documentation/kernel-parameters: Add multi-device config_acs example Wei Wang
2026-02-16 2:26 ` [PATCH v5 3/6] PCI: Consolidate delimiter handling into pci_dev_str_match() Wei Wang
2026-02-19 7:12 ` Dan Carpenter
2026-02-19 14:39 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 4/6] PCI: Refactor disable_acs_redir and config_acs param handling Wei Wang
2026-02-16 2:26 ` [PATCH v5 5/6] PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP Wei Wang
2026-02-16 2:34 ` Wei Wang
2026-02-16 2:26 ` [PATCH v5 6/6] PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled() Wei Wang
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®