mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
drm/amd/ras: cap pending_ecc_list size
Drop new entries once pending_ecc_count hits RAS_UMC_PENDING_ECC_MAX (8192) so an ECC storm or repeated UMC error injection cannot exhaust kernel memory. Dropped events are counted and reported via a rate-limited warning. Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
a71db9b8f7
commit
82502db448
|
|
@ -46,6 +46,15 @@
|
|||
printk(KERN_WARNING fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RAS_DEV_WARN_RATELIMITED(device, fmt, ...) \
|
||||
do { \
|
||||
if (device) \
|
||||
dev_warn_ratelimited(((struct amdgpu_device *)device)->dev, \
|
||||
fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
printk_ratelimited(KERN_WARNING fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RAS_DEV_INFO(device, fmt, ...) \
|
||||
do { \
|
||||
if (device) \
|
||||
|
|
|
|||
|
|
@ -193,12 +193,29 @@ static void ras_umc_reserve_eeprom_record(struct ras_core_context *ras_core,
|
|||
}
|
||||
|
||||
/* When gpu reset is ongoing, ecc logging operations will be pended.
|
||||
*
|
||||
* The pending list is bounded by RAS_UMC_PENDING_ECC_MAX so that an ECC
|
||||
* storm or repeated UMC error injection cannot make this list (and the
|
||||
* kernel allocations behind it) grow without bound. Once the limit is
|
||||
* reached, additional events are dropped and counted in
|
||||
* pending_ecc_dropped, with a rate-limited warning emitted.
|
||||
*/
|
||||
int ras_umc_log_bad_bank_pending(struct ras_core_context *ras_core, struct ras_bank_ecc *bank)
|
||||
{
|
||||
struct ras_umc *ras_umc = &ras_core->ras_umc;
|
||||
struct ras_bank_ecc_node *ecc_node;
|
||||
|
||||
mutex_lock(&ras_umc->pending_ecc_lock);
|
||||
if (ras_umc->pending_ecc_count >= RAS_UMC_PENDING_ECC_MAX) {
|
||||
ras_umc->pending_ecc_dropped++;
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
RAS_DEV_WARN_RATELIMITED(ras_core->dev,
|
||||
"pending ECC list full (%u), dropping bad bank event (total dropped:%u)\n",
|
||||
RAS_UMC_PENDING_ECC_MAX, ras_umc->pending_ecc_dropped);
|
||||
return -ENOSPC;
|
||||
}
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
|
||||
ecc_node = kzalloc_obj(*ecc_node);
|
||||
if (!ecc_node)
|
||||
return -ENOMEM;
|
||||
|
|
@ -206,7 +223,15 @@ int ras_umc_log_bad_bank_pending(struct ras_core_context *ras_core, struct ras_b
|
|||
memcpy(&ecc_node->ecc, bank, sizeof(ecc_node->ecc));
|
||||
|
||||
mutex_lock(&ras_umc->pending_ecc_lock);
|
||||
/* re-check under the lock to honor the cap across concurrent callers */
|
||||
if (ras_umc->pending_ecc_count >= RAS_UMC_PENDING_ECC_MAX) {
|
||||
ras_umc->pending_ecc_dropped++;
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
kfree(ecc_node);
|
||||
return -ENOSPC;
|
||||
}
|
||||
list_add_tail(&ecc_node->node, &ras_umc->pending_ecc_list);
|
||||
ras_umc->pending_ecc_count++;
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -225,8 +250,16 @@ int ras_umc_log_pending_bad_bank(struct ras_core_context *ras_core)
|
|||
if (!ras_umc_log_bad_bank(ras_core, &ecc_node->ecc)) {
|
||||
list_del(&ecc_node->node);
|
||||
kfree(ecc_node);
|
||||
if (ras_umc->pending_ecc_count)
|
||||
ras_umc->pending_ecc_count--;
|
||||
}
|
||||
}
|
||||
if (ras_umc->pending_ecc_dropped) {
|
||||
RAS_DEV_WARN(ras_core->dev,
|
||||
"%u pending ECC bad-bank events were dropped during GPU reset\n",
|
||||
ras_umc->pending_ecc_dropped);
|
||||
ras_umc->pending_ecc_dropped = 0;
|
||||
}
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -609,6 +642,8 @@ int ras_umc_sw_fini(struct ras_core_context *ras_core)
|
|||
list_del(&ecc_node->node);
|
||||
kfree(ecc_node);
|
||||
}
|
||||
ras_umc->pending_ecc_count = 0;
|
||||
ras_umc->pending_ecc_dropped = 0;
|
||||
mutex_unlock(&ras_umc->pending_ecc_lock);
|
||||
|
||||
mutex_destroy(&ras_umc->tree_lock);
|
||||
|
|
|
|||
|
|
@ -139,8 +139,20 @@ struct ras_umc {
|
|||
struct mutex pending_ecc_lock;
|
||||
struct ras_umc_err_data umc_err_data;
|
||||
struct list_head pending_ecc_list;
|
||||
/* number of entries currently queued on pending_ecc_list */
|
||||
u32 pending_ecc_count;
|
||||
/* number of entries dropped because pending_ecc_list was full */
|
||||
u32 pending_ecc_dropped;
|
||||
};
|
||||
|
||||
/*
|
||||
* Upper bound on entries that can be queued on pending_ecc_list while a
|
||||
* GPU reset is in progress. Beyond this, new ECC events are dropped to
|
||||
* prevent unbounded kernel memory growth in case of an ECC storm or
|
||||
* malicious/repeated UMC error injection.
|
||||
*/
|
||||
#define RAS_UMC_PENDING_ECC_MAX 8192
|
||||
|
||||
int ras_umc_sw_init(struct ras_core_context *ras);
|
||||
int ras_umc_sw_fini(struct ras_core_context *ras);
|
||||
int ras_umc_hw_init(struct ras_core_context *ras);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user