Skip to content

Commit a57f2bf

Browse files
Jon Pan-Dohbjorn-helgaas
authored andcommitted
PCI/AER: Ratelimit correctable and non-fatal error logging
Spammy devices can flood kernel logs with AER errors and slow/stall execution. Add per-device ratelimits for AER correctable and non-fatal uncorrectable errors that use the kernel defaults (10 per 5s). Logging of fatal errors is not ratelimited. There are two AER logging entry points: - aer_print_error() is used by DPC and native AER - pci_print_aer() is used by GHES and CXL The native AER aer_print_error() case includes a loop that may log details from multiple devices, which are ratelimited individually. If we log details for any device, we also log the Error Source ID from the Root Port or RCEC. If no such device details are found, we still log the Error Source from the ERR_* Message, ratelimited by the Root Port or RCEC that received it. The DPC aer_print_error() case is not ratelimited, since this only happens for fatal errors. The CXL pci_print_aer() case is ratelimited by the Error Source device. The GHES pci_print_aer() case is via aer_recover_work_func(), which searches for the Error Source device. If the device is not found, there's no per-device ratelimit, so we use a system-wide ratelimit that covers all error types (correctable, non-fatal, and fatal). Sargun at Meta reported internally that a flood of AER errors causes RCU CPU stall warnings and CSD-lock warnings. Tested using aer-inject[1]. Sent 11 AER errors. Observed 10 errors logged while AER stats (cat /sys/bus/pci/devices/<dev>/aer_dev_correctable) show true count of 11. [1] https://git.kernel.org/pub/scm/linux/kernel/git/gong.chen/aer-inject.git [bhelgaas: commit log, factor out trace_aer_event() and aer_print_rp_info() changes to previous patches, enable Error Source logging if any downstream detail will be printed, don't ratelimit fatal errors, "aer_report" -> "aer_info", "cor_log_ratelimit" -> "correctable_ratelimit", "uncor_log_ratelimit" -> "nonfatal_ratelimit"] Reported-by: Sargun Dhillon <[email protected]> Signed-off-by: Jon Pan-Doh <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Kuppuswamy Sathyanarayanan <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent d72bae4 commit a57f2bf

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

drivers/pci/pci.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,13 +587,15 @@ static inline bool pci_dev_test_and_set_removed(struct pci_dev *dev)
587587

588588
struct aer_err_info {
589589
struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
590+
int ratelimit_print[AER_MAX_MULTI_ERR_DEVICES];
590591
int error_dev_num;
591592
const char *level; /* printk level */
592593

593594
unsigned int id:16;
594595

595596
unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */
596-
unsigned int __pad1:5;
597+
unsigned int root_ratelimit_print:1; /* 0=skip, 1=print */
598+
unsigned int __pad1:4;
597599
unsigned int multi_error_valid:1;
598600

599601
unsigned int first_error:5;

drivers/pci/pcie/aer.c

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/interrupt.h>
2929
#include <linux/delay.h>
3030
#include <linux/kfifo.h>
31+
#include <linux/ratelimit.h>
3132
#include <linux/slab.h>
3233
#include <acpi/apei.h>
3334
#include <acpi/ghes.h>
@@ -88,6 +89,10 @@ struct aer_info {
8889
u64 rootport_total_cor_errs;
8990
u64 rootport_total_fatal_errs;
9091
u64 rootport_total_nonfatal_errs;
92+
93+
/* Ratelimits for errors */
94+
struct ratelimit_state correctable_ratelimit;
95+
struct ratelimit_state nonfatal_ratelimit;
9196
};
9297

9398
#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
@@ -379,6 +384,11 @@ void pci_aer_init(struct pci_dev *dev)
379384

380385
dev->aer_info = kzalloc(sizeof(*dev->aer_info), GFP_KERNEL);
381386

387+
ratelimit_state_init(&dev->aer_info->correctable_ratelimit,
388+
DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
389+
ratelimit_state_init(&dev->aer_info->nonfatal_ratelimit,
390+
DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
391+
382392
/*
383393
* We save/restore PCI_ERR_UNCOR_MASK, PCI_ERR_UNCOR_SEVER,
384394
* PCI_ERR_COR_MASK, and PCI_ERR_CAP. Root and Root Complex Event
@@ -669,6 +679,18 @@ static void pci_rootport_aer_stats_incr(struct pci_dev *pdev,
669679
}
670680
}
671681

682+
static int aer_ratelimit(struct pci_dev *dev, unsigned int severity)
683+
{
684+
switch (severity) {
685+
case AER_NONFATAL:
686+
return __ratelimit(&dev->aer_info->nonfatal_ratelimit);
687+
case AER_CORRECTABLE:
688+
return __ratelimit(&dev->aer_info->correctable_ratelimit);
689+
default:
690+
return 1; /* Don't ratelimit fatal errors */
691+
}
692+
}
693+
672694
static void __aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
673695
{
674696
const char **strings;
@@ -721,6 +743,9 @@ void aer_print_error(struct aer_err_info *info, int i)
721743
trace_aer_event(pci_name(dev), (info->status & ~info->mask),
722744
info->severity, info->tlp_header_valid, &info->tlp);
723745

746+
if (!info->ratelimit_print[i])
747+
return;
748+
724749
if (!info->status) {
725750
pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
726751
aer_error_severity_string[info->severity]);
@@ -790,6 +815,9 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
790815
trace_aer_event(pci_name(dev), (status & ~mask),
791816
aer_severity, tlp_header_valid, &aer->header_log);
792817

818+
if (!aer_ratelimit(dev, info.severity))
819+
return;
820+
793821
layer = AER_GET_LAYER_ERROR(aer_severity, status);
794822
agent = AER_GET_AGENT(aer_severity, status);
795823

@@ -824,6 +852,18 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
824852
e_info->dev[i] = pci_dev_get(dev);
825853
e_info->error_dev_num++;
826854

855+
/*
856+
* Ratelimit AER log messages. "dev" is either the source
857+
* identified by the root's Error Source ID or it has an unmasked
858+
* error logged in its own AER Capability. Messages are emitted
859+
* when "ratelimit_print[i]" is non-zero. If we will print detail
860+
* for a downstream device, make sure we print the Error Source ID
861+
* from the root as well.
862+
*/
863+
if (aer_ratelimit(dev, e_info->severity)) {
864+
e_info->ratelimit_print[i] = 1;
865+
e_info->root_ratelimit_print = 1;
866+
}
827867
return 0;
828868
}
829869

@@ -918,7 +958,7 @@ static int find_device_iter(struct pci_dev *dev, void *data)
918958
* e_info->error_dev_num and e_info->dev[], based on the given information.
919959
*/
920960
static bool find_source_device(struct pci_dev *parent,
921-
struct aer_err_info *e_info)
961+
struct aer_err_info *e_info)
922962
{
923963
struct pci_dev *dev = parent;
924964
int result;
@@ -1144,9 +1184,10 @@ static void aer_recover_work_func(struct work_struct *work)
11441184
pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
11451185
entry.devfn);
11461186
if (!pdev) {
1147-
pr_err("no pci_dev for %04x:%02x:%02x.%x\n",
1148-
entry.domain, entry.bus,
1149-
PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
1187+
pr_err_ratelimited("%04x:%02x:%02x.%x: no pci_dev found\n",
1188+
entry.domain, entry.bus,
1189+
PCI_SLOT(entry.devfn),
1190+
PCI_FUNC(entry.devfn));
11501191
continue;
11511192
}
11521193
pci_print_aer(pdev, entry.severity, entry.regs);
@@ -1294,7 +1335,22 @@ static void aer_isr_one_error_type(struct pci_dev *root,
12941335
bool found;
12951336

12961337
found = find_source_device(root, info);
1297-
aer_print_source(root, info, found);
1338+
1339+
/*
1340+
* If we're going to log error messages, we've already set
1341+
* "info->root_ratelimit_print" and "info->ratelimit_print[i]" to
1342+
* non-zero (which enables printing) because this is either an
1343+
* ERR_FATAL or we found a device with an error logged in its AER
1344+
* Capability.
1345+
*
1346+
* If we didn't find the Error Source device, at least log the
1347+
* Requester ID from the ERR_* Message received by the Root Port or
1348+
* RCEC, ratelimited by the RP or RCEC.
1349+
*/
1350+
if (info->root_ratelimit_print ||
1351+
(!found && aer_ratelimit(root, info->severity)))
1352+
aer_print_source(root, info, found);
1353+
12981354
if (found)
12991355
aer_process_err_devices(info);
13001356
}

0 commit comments

Comments
 (0)