* [PATCH 0/2] PCI/AER: Improve Error Source handling
@ 2026-11-03 9:45 Lukas Wunner
2026-11-03 9:45 ` [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source Lukas Wunner
2026-11-03 9:45 ` [PATCH 2/2] PCI/AER: Check validity of Error Source ID register Lukas Wunner
0 siblings, 2 replies; 7+ messages in thread
From: Lukas Wunner @ 2026-11-03 9:45 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci
Cc: Sourabh Jain, Oliver OHalloran, linuxppc-dev, Alex Deucher,
Sathyanarayanan Kuppuswamy, Keith Busch, Maciej Grochowski
While analyzing log output provided by Alex, I noticed that the AER driver
fails to find the error-signaling device if the Error Source ID register
contains an invalid, non-zero value. Patch [2/2] fixes that.
Also, a potential NULL pointer deref caught my eye in that portion of the
code which is fixed by patch [1/2]. I believe this is hard to trigger,
but the kernel should still handle it gracefully.
Lukas Wunner (2):
PCI/AER: Avoid NULL pointer deref on search for Error Source
PCI/AER: Check validity of Error Source ID register
drivers/pci/pci.h | 7 ++++++-
drivers/pci/pcie/aer.c | 35 ++++++++++++++++++++++++++---------
drivers/pci/pcie/rcec.c | 14 ++++++++++++++
3 files changed, 46 insertions(+), 10 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source
2026-11-03 9:45 [PATCH 0/2] PCI/AER: Improve Error Source handling Lukas Wunner
@ 2026-11-03 9:45 ` Lukas Wunner
2026-11-03 12:39 ` Ilpo Järvinen
2026-11-03 16:08 ` Kuppuswamy Sathyanarayanan
2026-11-03 9:45 ` [PATCH 2/2] PCI/AER: Check validity of Error Source ID register Lukas Wunner
1 sibling, 2 replies; 7+ messages in thread
From: Lukas Wunner @ 2026-11-03 9:45 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci
Cc: Sourabh Jain, Oliver OHalloran, linuxppc-dev, Alex Deucher,
Sathyanarayanan Kuppuswamy, Keith Busch, Maciej Grochowski
A Root Port's subordinate bus may be NULL if the PCI core runs out of bus
numbers on enumeration. Yet when the AER driver searches for the source
of an Error Message, it dereferences the subordinate pointer without
checking for NULL. Fix it.
Fixes: 28eb27cf0839 ("PCI AER: support invalid error source IDs")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: stable@vger.kernel.org # v2.6.31+
---
drivers/pci/pcie/aer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index db4f607f889c..d492c7ce01e1 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -1251,7 +1251,7 @@ static bool find_source_device(struct pci_dev *parent,
if (pci_pcie_type(parent) == PCI_EXP_TYPE_RC_EC)
pcie_walk_rcec(parent, find_device_iter, e_info);
- else
+ else if (parent->subordinate)
pci_walk_bus(parent->subordinate, find_device_iter, e_info);
if (!e_info->error_dev_num)
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] PCI/AER: Check validity of Error Source ID register
2026-11-03 9:45 [PATCH 0/2] PCI/AER: Improve Error Source handling Lukas Wunner
2026-11-03 9:45 ` [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source Lukas Wunner
@ 2026-11-03 9:45 ` Lukas Wunner
2026-11-03 12:57 ` Ilpo Järvinen
2026-11-03 16:15 ` Kuppuswamy Sathyanarayanan
1 sibling, 2 replies; 7+ messages in thread
From: Lukas Wunner @ 2026-11-03 9:45 UTC (permalink / raw)
To: Bjorn Helgaas, linux-pci
Cc: Sourabh Jain, Oliver OHalloran, linuxppc-dev, Alex Deucher,
Sathyanarayanan Kuppuswamy, Keith Busch, Maciej Grochowski
Certain Intel and AMD Root Ports are known to populate the Error Source ID
register with an invalid value. The AER driver seeks to recognize such
buggy silicon by assuming invalidity if the bus number is zero. It then
searches for the error-signaling device in the hierarchy below the Root
Port. This was introduced by commit 28eb27cf0839 ("PCI AER: support
invalid error source IDs").
Alex has provided dmesg output which shows an invalid Error Source ID with
a non-zero bus number. The AER driver's heuristic fails to recognize its
invalidity:
pcieport 0000:00:07.1: AER: Correctable Error message received from 0000:01:00.0 (no details found)
The Root Port at 0000:00:07.1 has subordinate bus 04, so an error source
on bus 01 is obviously invalid. The range of subordinate buses is cached
and checking against it is cheap.
Do that instead of relying on a heuristic. Emit a message when an invalid
Error Source ID is detected to alert silicon validation engineers.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=222095
Tested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
drivers/pci/pci.h | 7 ++++++-
drivers/pci/pcie/aer.c | 33 +++++++++++++++++++++++++--------
drivers/pci/pcie/rcec.c | 14 ++++++++++++++
3 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 77efa4c5c960..aa392bb6a482 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -871,6 +871,9 @@ static inline bool pci_dev_binding_disallowed(struct pci_dev *dev)
* @id: Value from register PCI_ERR_ROOT_ERR_SRC
* @severity: AER severity, 0-UNCOR Non-fatal, 1-UNCOR fatal, 2-COR
* @root_ratelimit_print: Flag to log or not log the root's error. 0=NotLog/1=Log
+ * @id_valid: Whether @id is a valid value. Some Root Ports report an invalid
+ * Error Source ID, necessitating a search for the error-signaling device
+ * in the hierarchy below the Root Port.
* @multi_error_valid: If multiple errors are reported
* @first_error: First reported error
* @__pad2: Padding for alignment
@@ -893,7 +896,8 @@ struct aer_err_info {
unsigned int severity:2;
unsigned int root_ratelimit_print:1;
- unsigned int __pad1:4;
+ unsigned int __pad1:3;
+ unsigned int id_valid:1;
unsigned int multi_error_valid:1;
unsigned int first_error:5;
@@ -955,6 +959,7 @@ void pcie_link_rcec(struct pci_dev *rcec);
void pcie_walk_rcec(struct pci_dev *rcec,
int (*cb)(struct pci_dev *, void *),
void *userdata);
+bool pci_rcec_associated(struct pci_dev *rcec, u16 id);
#else
static inline void pci_rcec_init(struct pci_dev *dev) { }
static inline void pci_rcec_exit(struct pci_dev *dev) { }
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index d492c7ce01e1..9957c36bf215 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -951,12 +951,13 @@ static void aer_print_source(struct pci_dev *dev, struct aer_err_info *info,
{
u16 source = info->id;
- pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s\n",
+ pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s%s\n",
info->multi_error_valid ? "Multiple " : "",
aer_error_severity_string[info->severity],
info->multi_error_valid ? "s received, first one" : " received",
pci_domain_nr(dev->bus), PCI_BUS_NUM(source),
PCI_SLOT(source), PCI_FUNC(source),
+ info->id_valid ? "" : " (invalid source)",
found ? "" : " (no details found)");
}
@@ -1146,6 +1147,24 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
return 0;
}
+static bool source_id_valid(struct pci_dev *root, u16 id)
+{
+ /* The Root Port or RCEC can itself be a valid Error Source */
+ if (pci_dev_id(root) == id)
+ return true;
+
+ /* For RCECs, @id shall be in range of its associated buses/devices */
+ if (pci_pcie_type(root) == PCI_EXP_TYPE_RC_EC)
+ return pci_rcec_associated(root, id);
+
+ /* For Root Ports, @id shall be in range of its subordinate buses */
+ if (!root->subordinate)
+ return false;
+
+ return root->subordinate->busn_res.start <= PCI_BUS_NUM(id) &&
+ root->subordinate->busn_res.end >= PCI_BUS_NUM(id);
+}
+
/**
* is_error_source - check whether the device is source of reported error
* @dev: pointer to pci_dev to be checked
@@ -1157,11 +1176,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
u32 status, mask;
u16 reg16;
- /*
- * When bus ID is equal to 0, it might be a bad ID
- * reported by Root Port.
- */
- if ((PCI_BUS_NUM(e_info->id) != 0) &&
+ /* Some Root Ports report an invalid Error Source ID */
+ if (e_info->id_valid &&
!(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
/* Device ID match? */
if (e_info->id == pci_dev_id(dev))
@@ -1174,8 +1190,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
/*
* When either
- * 1) bus ID is equal to 0. Some ports might lose the bus
- * ID of error source id;
+ * 1) Error Source ID register is invalid;
* 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
* 3) There are multiple errors and prior ID comparing fails;
* We check AER status registers to find possible reporter.
@@ -1566,6 +1581,8 @@ static void aer_isr_one_error_type(struct pci_dev *root,
{
bool found;
+ info->id_valid = source_id_valid(root, info->id);
+
found = find_source_device(root, info);
/*
diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c
index 2bf6d9d549ba..609d656300fa 100644
--- a/drivers/pci/pcie/rcec.c
+++ b/drivers/pci/pcie/rcec.c
@@ -21,6 +21,20 @@ struct walk_rcec_data {
void *user_data;
};
+bool pci_rcec_associated(struct pci_dev *rcec, u16 id)
+{
+ if (!rcec->rcec_ea)
+ return false;
+
+ if (rcec->bus->number == PCI_BUS_NUM(id)) {
+ unsigned long bitmap = rcec->rcec_ea->bitmap;
+ return test_bit(PCI_SLOT(id), &bitmap);
+ }
+
+ return rcec->rcec_ea->nextbusn <= PCI_BUS_NUM(id) &&
+ rcec->rcec_ea->lastbusn >= PCI_BUS_NUM(id);
+}
+
static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep)
{
unsigned long bitmap = rcec->rcec_ea->bitmap;
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source
2026-11-03 9:45 ` [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source Lukas Wunner
@ 2026-11-03 12:39 ` Ilpo Järvinen
2026-11-03 16:08 ` Kuppuswamy Sathyanarayanan
1 sibling, 0 replies; 7+ messages in thread
From: Ilpo Järvinen @ 2026-11-03 12:39 UTC (permalink / raw)
To: Lukas Wunner
Cc: Bjorn Helgaas, linux-pci, Sourabh Jain, Oliver OHalloran,
linuxppc-dev, Alex Deucher, Sathyanarayanan Kuppuswamy,
Keith Busch, Maciej Grochowski
[-- Attachment #1: Type: text/plain, Size: 1151 bytes --]
On Tue, 3 Nov 2026, Lukas Wunner wrote:
> A Root Port's subordinate bus may be NULL if the PCI core runs out of bus
> numbers on enumeration. Yet when the AER driver searches for the source
> of an Error Message, it dereferences the subordinate pointer without
> checking for NULL. Fix it.
>
> Fixes: 28eb27cf0839 ("PCI AER: support invalid error source IDs")
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> Cc: stable@vger.kernel.org # v2.6.31+
> ---
> drivers/pci/pcie/aer.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index db4f607f889c..d492c7ce01e1 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1251,7 +1251,7 @@ static bool find_source_device(struct pci_dev *parent,
>
> if (pci_pcie_type(parent) == PCI_EXP_TYPE_RC_EC)
> pcie_walk_rcec(parent, find_device_iter, e_info);
> - else
> + else if (parent->subordinate)
> pci_walk_bus(parent->subordinate, find_device_iter, e_info);
>
> if (!e_info->error_dev_num)
>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
--
i.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] PCI/AER: Check validity of Error Source ID register
2026-11-03 9:45 ` [PATCH 2/2] PCI/AER: Check validity of Error Source ID register Lukas Wunner
@ 2026-11-03 12:57 ` Ilpo Järvinen
2026-11-03 16:15 ` Kuppuswamy Sathyanarayanan
1 sibling, 0 replies; 7+ messages in thread
From: Ilpo Järvinen @ 2026-11-03 12:57 UTC (permalink / raw)
To: Lukas Wunner
Cc: Bjorn Helgaas, linux-pci, Sourabh Jain, Oliver OHalloran,
linuxppc-dev, Alex Deucher, Sathyanarayanan Kuppuswamy,
Keith Busch, Maciej Grochowski
On Tue, 3 Nov 2026, Lukas Wunner wrote:
> Certain Intel and AMD Root Ports are known to populate the Error Source ID
> register with an invalid value. The AER driver seeks to recognize such
> buggy silicon by assuming invalidity if the bus number is zero. It then
> searches for the error-signaling device in the hierarchy below the Root
> Port. This was introduced by commit 28eb27cf0839 ("PCI AER: support
> invalid error source IDs").
>
> Alex has provided dmesg output which shows an invalid Error Source ID with
> a non-zero bus number. The AER driver's heuristic fails to recognize its
> invalidity:
>
> pcieport 0000:00:07.1: AER: Correctable Error message received from 0000:01:00.0 (no details found)
>
> The Root Port at 0000:00:07.1 has subordinate bus 04, so an error source
> on bus 01 is obviously invalid. The range of subordinate buses is cached
> and checking against it is cheap.
>
> Do that instead of relying on a heuristic. Emit a message when an invalid
> Error Source ID is detected to alert silicon validation engineers.
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=222095
> Tested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
> drivers/pci/pci.h | 7 ++++++-
> drivers/pci/pcie/aer.c | 33 +++++++++++++++++++++++++--------
> drivers/pci/pcie/rcec.c | 14 ++++++++++++++
> 3 files changed, 45 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 77efa4c5c960..aa392bb6a482 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -871,6 +871,9 @@ static inline bool pci_dev_binding_disallowed(struct pci_dev *dev)
> * @id: Value from register PCI_ERR_ROOT_ERR_SRC
> * @severity: AER severity, 0-UNCOR Non-fatal, 1-UNCOR fatal, 2-COR
> * @root_ratelimit_print: Flag to log or not log the root's error. 0=NotLog/1=Log
> + * @id_valid: Whether @id is a valid value. Some Root Ports report an invalid
> + * Error Source ID, necessitating a search for the error-signaling device
> + * in the hierarchy below the Root Port.
> * @multi_error_valid: If multiple errors are reported
> * @first_error: First reported error
> * @__pad2: Padding for alignment
> @@ -893,7 +896,8 @@ struct aer_err_info {
>
> unsigned int severity:2;
> unsigned int root_ratelimit_print:1;
> - unsigned int __pad1:4;
> + unsigned int __pad1:3;
> + unsigned int id_valid:1;
> unsigned int multi_error_valid:1;
>
> unsigned int first_error:5;
> @@ -955,6 +959,7 @@ void pcie_link_rcec(struct pci_dev *rcec);
> void pcie_walk_rcec(struct pci_dev *rcec,
> int (*cb)(struct pci_dev *, void *),
> void *userdata);
> +bool pci_rcec_associated(struct pci_dev *rcec, u16 id);
> #else
> static inline void pci_rcec_init(struct pci_dev *dev) { }
> static inline void pci_rcec_exit(struct pci_dev *dev) { }
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index d492c7ce01e1..9957c36bf215 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -951,12 +951,13 @@ static void aer_print_source(struct pci_dev *dev, struct aer_err_info *info,
> {
> u16 source = info->id;
>
> - pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s\n",
> + pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s%s\n",
> info->multi_error_valid ? "Multiple " : "",
> aer_error_severity_string[info->severity],
> info->multi_error_valid ? "s received, first one" : " received",
> pci_domain_nr(dev->bus), PCI_BUS_NUM(source),
> PCI_SLOT(source), PCI_FUNC(source),
> + info->id_valid ? "" : " (invalid source)",
> found ? "" : " (no details found)");
> }
>
> @@ -1146,6 +1147,24 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
> return 0;
> }
>
> +static bool source_id_valid(struct pci_dev *root, u16 id)
> +{
> + /* The Root Port or RCEC can itself be a valid Error Source */
> + if (pci_dev_id(root) == id)
> + return true;
> +
> + /* For RCECs, @id shall be in range of its associated buses/devices */
> + if (pci_pcie_type(root) == PCI_EXP_TYPE_RC_EC)
> + return pci_rcec_associated(root, id);
> +
> + /* For Root Ports, @id shall be in range of its subordinate buses */
> + if (!root->subordinate)
> + return false;
> +
> + return root->subordinate->busn_res.start <= PCI_BUS_NUM(id) &&
> + root->subordinate->busn_res.end >= PCI_BUS_NUM(id);
I kind of hate the order of this logic. I understand you're probably
doing it for the alignment which has some value but...
...For me, the more logical order would be to keep these in increasing
order even if doing it results in losing the alignment:
start <= val &&
val <= end
Maybe that's just me and it's not an end of the world either way.
> +}
> +
> /**
> * is_error_source - check whether the device is source of reported error
> * @dev: pointer to pci_dev to be checked
> @@ -1157,11 +1176,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
> u32 status, mask;
> u16 reg16;
>
> - /*
> - * When bus ID is equal to 0, it might be a bad ID
> - * reported by Root Port.
> - */
> - if ((PCI_BUS_NUM(e_info->id) != 0) &&
> + /* Some Root Ports report an invalid Error Source ID */
> + if (e_info->id_valid &&
> !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
> /* Device ID match? */
> if (e_info->id == pci_dev_id(dev))
> @@ -1174,8 +1190,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
>
> /*
> * When either
> - * 1) bus ID is equal to 0. Some ports might lose the bus
> - * ID of error source id;
> + * 1) Error Source ID register is invalid;
> * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
> * 3) There are multiple errors and prior ID comparing fails;
> * We check AER status registers to find possible reporter.
> @@ -1566,6 +1581,8 @@ static void aer_isr_one_error_type(struct pci_dev *root,
> {
> bool found;
>
> + info->id_valid = source_id_valid(root, info->id);
> +
> found = find_source_device(root, info);
>
> /*
> diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c
> index 2bf6d9d549ba..609d656300fa 100644
> --- a/drivers/pci/pcie/rcec.c
> +++ b/drivers/pci/pcie/rcec.c
> @@ -21,6 +21,20 @@ struct walk_rcec_data {
> void *user_data;
> };
>
> +bool pci_rcec_associated(struct pci_dev *rcec, u16 id)
> +{
> + if (!rcec->rcec_ea)
> + return false;
> +
> + if (rcec->bus->number == PCI_BUS_NUM(id)) {
> + unsigned long bitmap = rcec->rcec_ea->bitmap;
> + return test_bit(PCI_SLOT(id), &bitmap);
> + }
> +
> + return rcec->rcec_ea->nextbusn <= PCI_BUS_NUM(id) &&
> + rcec->rcec_ea->lastbusn >= PCI_BUS_NUM(id);
Same thing here.
Sashiko's comment about the behavior change on bad 0 report matching to
root port at 0 looked valid concern to me.
--
i.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source
2026-11-03 9:45 ` [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source Lukas Wunner
2026-11-03 12:39 ` Ilpo Järvinen
@ 2026-11-03 16:08 ` Kuppuswamy Sathyanarayanan
1 sibling, 0 replies; 7+ messages in thread
From: Kuppuswamy Sathyanarayanan @ 2026-11-03 16:08 UTC (permalink / raw)
To: Lukas Wunner, Bjorn Helgaas, linux-pci
Cc: Sourabh Jain, Oliver OHalloran, linuxppc-dev, Alex Deucher,
Keith Busch, Maciej Grochowski
On 11/3/2026 1:45 AM, Lukas Wunner wrote:
> A Root Port's subordinate bus may be NULL if the PCI core runs out of bus
> numbers on enumeration. Yet when the AER driver searches for the source
> of an Error Message, it dereferences the subordinate pointer without
> checking for NULL. Fix it.
>
> Fixes: 28eb27cf0839 ("PCI AER: support invalid error source IDs")
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> Cc: stable@vger.kernel.org # v2.6.31+
> ---
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> drivers/pci/pcie/aer.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index db4f607f889c..d492c7ce01e1 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -1251,7 +1251,7 @@ static bool find_source_device(struct pci_dev *parent,
>
> if (pci_pcie_type(parent) == PCI_EXP_TYPE_RC_EC)
> pcie_walk_rcec(parent, find_device_iter, e_info);
> - else
> + else if (parent->subordinate)
> pci_walk_bus(parent->subordinate, find_device_iter, e_info);
>
> if (!e_info->error_dev_num)
--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] PCI/AER: Check validity of Error Source ID register
2026-11-03 9:45 ` [PATCH 2/2] PCI/AER: Check validity of Error Source ID register Lukas Wunner
2026-11-03 12:57 ` Ilpo Järvinen
@ 2026-11-03 16:15 ` Kuppuswamy Sathyanarayanan
1 sibling, 0 replies; 7+ messages in thread
From: Kuppuswamy Sathyanarayanan @ 2026-11-03 16:15 UTC (permalink / raw)
To: Lukas Wunner, Bjorn Helgaas, linux-pci
Cc: Sourabh Jain, Oliver OHalloran, linuxppc-dev, Alex Deucher,
Keith Busch, Maciej Grochowski
On 11/3/2026 1:45 AM, Lukas Wunner wrote:
> Certain Intel and AMD Root Ports are known to populate the Error Source ID
> register with an invalid value. The AER driver seeks to recognize such
> buggy silicon by assuming invalidity if the bus number is zero. It then
> searches for the error-signaling device in the hierarchy below the Root
> Port. This was introduced by commit 28eb27cf0839 ("PCI AER: support
> invalid error source IDs").
>
> Alex has provided dmesg output which shows an invalid Error Source ID with
> a non-zero bus number. The AER driver's heuristic fails to recognize its
> invalidity:
>
> pcieport 0000:00:07.1: AER: Correctable Error message received from 0000:01:00.0 (no details found)
>
> The Root Port at 0000:00:07.1 has subordinate bus 04, so an error source
> on bus 01 is obviously invalid. The range of subordinate buses is cached
> and checking against it is cheap.
>
> Do that instead of relying on a heuristic. Emit a message when an invalid
> Error Source ID is detected to alert silicon validation engineers.
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=222095
> Tested-by: Alex Deucher <alexander.deucher@amd.com>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
> drivers/pci/pci.h | 7 ++++++-
> drivers/pci/pcie/aer.c | 33 +++++++++++++++++++++++++--------
> drivers/pci/pcie/rcec.c | 14 ++++++++++++++
> 3 files changed, 45 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 77efa4c5c960..aa392bb6a482 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -871,6 +871,9 @@ static inline bool pci_dev_binding_disallowed(struct pci_dev *dev)
> * @id: Value from register PCI_ERR_ROOT_ERR_SRC
> * @severity: AER severity, 0-UNCOR Non-fatal, 1-UNCOR fatal, 2-COR
> * @root_ratelimit_print: Flag to log or not log the root's error. 0=NotLog/1=Log
> + * @id_valid: Whether @id is a valid value. Some Root Ports report an invalid
> + * Error Source ID, necessitating a search for the error-signaling device
> + * in the hierarchy below the Root Port.
> * @multi_error_valid: If multiple errors are reported
> * @first_error: First reported error
> * @__pad2: Padding for alignment
> @@ -893,7 +896,8 @@ struct aer_err_info {
>
> unsigned int severity:2;
> unsigned int root_ratelimit_print:1;
> - unsigned int __pad1:4;
> + unsigned int __pad1:3;
> + unsigned int id_valid:1;
> unsigned int multi_error_valid:1;
>
> unsigned int first_error:5;
> @@ -955,6 +959,7 @@ void pcie_link_rcec(struct pci_dev *rcec);
> void pcie_walk_rcec(struct pci_dev *rcec,
> int (*cb)(struct pci_dev *, void *),
> void *userdata);
> +bool pci_rcec_associated(struct pci_dev *rcec, u16 id);
> #else
> static inline void pci_rcec_init(struct pci_dev *dev) { }
> static inline void pci_rcec_exit(struct pci_dev *dev) { }
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index d492c7ce01e1..9957c36bf215 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -951,12 +951,13 @@ static void aer_print_source(struct pci_dev *dev, struct aer_err_info *info,
> {
> u16 source = info->id;
>
> - pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s\n",
> + pci_info(dev, "%s%s Error message%s from %04x:%02x:%02x.%d%s%s\n",
> info->multi_error_valid ? "Multiple " : "",
> aer_error_severity_string[info->severity],
> info->multi_error_valid ? "s received, first one" : " received",
> pci_domain_nr(dev->bus), PCI_BUS_NUM(source),
> PCI_SLOT(source), PCI_FUNC(source),
> + info->id_valid ? "" : " (invalid source)",
> found ? "" : " (no details found)");
> }
>
> @@ -1146,6 +1147,24 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
> return 0;
> }
>
> +static bool source_id_valid(struct pci_dev *root, u16 id)
> +{
> + /* The Root Port or RCEC can itself be a valid Error Source */
> + if (pci_dev_id(root) == id)
> + return true;
> +
> + /* For RCECs, @id shall be in range of its associated buses/devices */
> + if (pci_pcie_type(root) == PCI_EXP_TYPE_RC_EC)
> + return pci_rcec_associated(root, id);
> +
> + /* For Root Ports, @id shall be in range of its subordinate buses */
> + if (!root->subordinate)
> + return false;
> +
> + return root->subordinate->busn_res.start <= PCI_BUS_NUM(id) &&
> + root->subordinate->busn_res.end >= PCI_BUS_NUM(id);
> +}
> +
> /**
> * is_error_source - check whether the device is source of reported error
> * @dev: pointer to pci_dev to be checked
> @@ -1157,11 +1176,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
> u32 status, mask;
> u16 reg16;
>
> - /*
> - * When bus ID is equal to 0, it might be a bad ID
> - * reported by Root Port.
> - */
> - if ((PCI_BUS_NUM(e_info->id) != 0) &&
> + /* Some Root Ports report an invalid Error Source ID */
> + if (e_info->id_valid &&
> !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
> /* Device ID match? */
> if (e_info->id == pci_dev_id(dev))
> @@ -1174,8 +1190,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
>
> /*
> * When either
> - * 1) bus ID is equal to 0. Some ports might lose the bus
> - * ID of error source id;
> + * 1) Error Source ID register is invalid;
> * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
> * 3) There are multiple errors and prior ID comparing fails;
> * We check AER status registers to find possible reporter.
> @@ -1566,6 +1581,8 @@ static void aer_isr_one_error_type(struct pci_dev *root,
> {
> bool found;
>
> + info->id_valid = source_id_valid(root, info->id);
> +
> found = find_source_device(root, info);
nit: Updated the kernel-doc help of find_source_device() to include id_valid.
>
> /*
> diff --git a/drivers/pci/pcie/rcec.c b/drivers/pci/pcie/rcec.c
> index 2bf6d9d549ba..609d656300fa 100644
> --- a/drivers/pci/pcie/rcec.c
> +++ b/drivers/pci/pcie/rcec.c
> @@ -21,6 +21,20 @@ struct walk_rcec_data {
> void *user_data;
> };
>
> +bool pci_rcec_associated(struct pci_dev *rcec, u16 id)
> +{
> + if (!rcec->rcec_ea)
> + return false;
> +
> + if (rcec->bus->number == PCI_BUS_NUM(id)) {
> + unsigned long bitmap = rcec->rcec_ea->bitmap;
> + return test_bit(PCI_SLOT(id), &bitmap);
> + }
> +
> + return rcec->rcec_ea->nextbusn <= PCI_BUS_NUM(id) &&
> + rcec->rcec_ea->lastbusn >= PCI_BUS_NUM(id);
> +}
> +
> static bool rcec_assoc_rciep(struct pci_dev *rcec, struct pci_dev *rciep)
> {
> unsigned long bitmap = rcec->rcec_ea->bitmap;
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-11-03 16:15 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 9:45 [PATCH 0/2] PCI/AER: Improve Error Source handling Lukas Wunner
2026-11-03 9:45 ` [PATCH 1/2] PCI/AER: Avoid NULL pointer deref on search for Error Source Lukas Wunner
2026-11-03 12:39 ` Ilpo Järvinen
2026-11-03 16:08 ` Kuppuswamy Sathyanarayanan
2026-11-03 9:45 ` [PATCH 2/2] PCI/AER: Check validity of Error Source ID register Lukas Wunner
2026-11-03 12:57 ` Ilpo Järvinen
2026-11-03 16:15 ` Kuppuswamy Sathyanarayanan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox