Skip to content

Commit b3580dd

Browse files
adrianoveromaddy-kerneldev
authored andcommitted
powerpc/fadump: Add timeout to RTAS busy-wait loops
The ibm,configure-kernel-dump RTAS call sites in rtas_fadump_register(), rtas_fadump_unregister(), and rtas_fadump_invalidate() polled indefinitely while firmware returned a busy status. A misbehaving or hung firmware could stall these paths forever, blocking fadump registration at boot or preventing clean teardown. Introduce rtas_fadump_call(), a helper that wraps the common busy-wait pattern shared by all three sites. The helper accumulates the total delay and returns -ETIMEDOUT if firmware keeps returning a busy status beyond RTAS_FADUMP_MAX_WAIT_MS (60 seconds). A pr_debug() message is emitted on each busy iteration to aid diagnosis when the timeout is hit. Signed-off-by: Adriano Vero <adri.vero.dev@gmail.com> Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com> [Maddy: Fixed newline after Signed-off-by] Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20260506222024.30352-1-adri.vero.dev@gmail.com
1 parent b55b6b9 commit b3580dd

2 files changed

Lines changed: 53 additions & 33 deletions

File tree

arch/powerpc/platforms/pseries/rtas-fadump.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,42 @@ static u64 rtas_fadump_get_bootmem_min(void)
179179
return RTAS_FADUMP_MIN_BOOT_MEM;
180180
}
181181

182+
/*
183+
* Helper to make an ibm,configure-kernel-dump RTAS call with a bounded
184+
* busy-wait loop. Returns the RTAS return code on completion, or
185+
* -ETIMEDOUT if firmware keeps returning a busy status beyond
186+
* RTAS_FADUMP_MAX_WAIT_MS milliseconds.
187+
*/
188+
static int rtas_fadump_call(struct fw_dump *fadump_conf, int operation,
189+
void *fdm_ptr, unsigned int fdm_size,
190+
const char *op_name)
191+
{
192+
unsigned int wait_time, total_wait = 0;
193+
int rc;
194+
195+
do {
196+
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
197+
NULL, operation, fdm_ptr, fdm_size);
198+
wait_time = rtas_busy_delay_time(rc);
199+
if (wait_time) {
200+
pr_debug("Firmware busy during fadump %s, waiting %ums (total %ums)\n",
201+
op_name, wait_time, total_wait);
202+
if (total_wait >= RTAS_FADUMP_MAX_WAIT_MS) {
203+
pr_err("Timed out waiting for firmware to complete fadump %s\n",
204+
op_name);
205+
return -ETIMEDOUT;
206+
}
207+
total_wait += wait_time;
208+
mdelay(wait_time);
209+
}
210+
} while (wait_time);
211+
212+
return rc;
213+
}
214+
182215
static int rtas_fadump_register(struct fw_dump *fadump_conf)
183216
{
184-
unsigned int wait_time, fdm_size;
217+
unsigned int fdm_size;
185218
int rc, err = -EIO;
186219

187220
/*
@@ -192,16 +225,10 @@ static int rtas_fadump_register(struct fw_dump *fadump_conf)
192225
fdm_size = sizeof(struct rtas_fadump_section_header);
193226
fdm_size += be16_to_cpu(fdm.header.dump_num_sections) * sizeof(struct rtas_fadump_section);
194227

195-
/* TODO: Add upper time limit for the delay */
196-
do {
197-
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
198-
NULL, FADUMP_REGISTER, &fdm, fdm_size);
199-
200-
wait_time = rtas_busy_delay_time(rc);
201-
if (wait_time)
202-
mdelay(wait_time);
203-
204-
} while (wait_time);
228+
rc = rtas_fadump_call(fadump_conf, FADUMP_REGISTER, &fdm, fdm_size,
229+
"register");
230+
if (rc == -ETIMEDOUT)
231+
return -ETIMEDOUT;
205232

206233
switch (rc) {
207234
case 0:
@@ -234,19 +261,12 @@ static int rtas_fadump_register(struct fw_dump *fadump_conf)
234261

235262
static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
236263
{
237-
unsigned int wait_time;
238264
int rc;
239265

240-
/* TODO: Add upper time limit for the delay */
241-
do {
242-
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
243-
NULL, FADUMP_UNREGISTER, &fdm,
244-
sizeof(struct rtas_fadump_mem_struct));
245-
246-
wait_time = rtas_busy_delay_time(rc);
247-
if (wait_time)
248-
mdelay(wait_time);
249-
} while (wait_time);
266+
rc = rtas_fadump_call(fadump_conf, FADUMP_UNREGISTER, &fdm,
267+
sizeof(struct rtas_fadump_mem_struct), "unregister");
268+
if (rc == -ETIMEDOUT)
269+
return -ETIMEDOUT;
250270

251271
if (rc) {
252272
pr_err("Failed to un-register - unexpected error(%d).\n", rc);
@@ -259,19 +279,13 @@ static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
259279

260280
static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
261281
{
262-
unsigned int wait_time;
263282
int rc;
264283

265-
/* TODO: Add upper time limit for the delay */
266-
do {
267-
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
268-
NULL, FADUMP_INVALIDATE, fdm_active,
269-
sizeof(struct rtas_fadump_mem_struct));
270-
271-
wait_time = rtas_busy_delay_time(rc);
272-
if (wait_time)
273-
mdelay(wait_time);
274-
} while (wait_time);
284+
rc = rtas_fadump_call(fadump_conf, FADUMP_INVALIDATE,
285+
(void *)fdm_active,
286+
sizeof(struct rtas_fadump_mem_struct), "invalidate");
287+
if (rc == -ETIMEDOUT)
288+
return -ETIMEDOUT;
275289

276290
if (rc) {
277291
pr_err("Failed to invalidate - unexpected error (%d).\n", rc);

arch/powerpc/platforms/pseries/rtas-fadump.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
#define MAX_SECTIONS 10
4242
#define RTAS_FADUMP_MAX_BOOT_MEM_REGS 7
4343

44+
/*
45+
* Maximum time to wait for firmware to respond to an
46+
* ibm,configure-kernel-dump RTAS call before giving up.
47+
*/
48+
#define RTAS_FADUMP_MAX_WAIT_MS 60000U
49+
4450
/* Kernel Dump section info */
4551
struct rtas_fadump_section {
4652
__be32 request_flag;

0 commit comments

Comments
 (0)