diff options
author | Peter Oberparleiter <oberpar@linux.ibm.com> | 2024-06-20 15:20:28 +0300 |
---|---|---|
committer | Alexander Gordeev <agordeev@linux.ibm.com> | 2024-07-01 18:47:01 +0300 |
commit | bb748badfdfb4c6e5c5cb40ded1721f99d32072f (patch) | |
tree | 8c147df3bc68ef18e4aa1d5819b47940fab70770 /drivers/s390 | |
parent | bf365071ea92b9579d5a272679b74052a5643e35 (diff) | |
download | linux-bb748badfdfb4c6e5c5cb40ded1721f99d32072f.tar.xz |
s390/sclp: Add timeout to Store Data requests
Due to a bug in some firmware versions, Store Data requests might not
get an event response in certain situations. As a result, the boot
process will be blocked indefinitely.
Fix this by introducing timeout handling for Store Data requests. In
case a timeout occurs, the Store Data operation is halted and no data
is retrieved from the SCLP facility.
Note: A minority of installed systems rely on Store Data result for
device auto-configuration. These systems will fail to boot in case of a
Store Data timeout and will need to be switched to manual device
configuration as workaround.
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/char/sclp_sd.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c index 322700b96207..c2dc9aadb7d2 100644 --- a/drivers/s390/char/sclp_sd.c +++ b/drivers/s390/char/sclp_sd.c @@ -9,6 +9,7 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/completion.h> +#include <linux/jiffies.h> #include <linux/kobject.h> #include <linux/list.h> #include <linux/printk.h> @@ -28,6 +29,8 @@ #define SD_DI_CONFIG 3 +#define SD_TIMEOUT msecs_to_jiffies(30000) + struct sclp_sd_evbuf { struct evbuf_header hdr; u8 eq; @@ -234,9 +237,12 @@ static int sclp_sd_sync(unsigned long page, u8 eq, u8 di, u64 sat, u64 sa, goto out; } if (!(evbuf->rflags & 0x80)) { - rc = wait_for_completion_interruptible(&listener.completion); - if (rc) + rc = wait_for_completion_interruptible_timeout(&listener.completion, SD_TIMEOUT); + if (rc == 0) + rc = -ETIME; + if (rc < 0) goto out; + rc = 0; evbuf = &listener.evbuf; } switch (evbuf->status) { @@ -323,8 +329,8 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di) rc = sclp_sd_sync(page, SD_EQ_STORE_DATA, di, asce, (u64) data, &dsize, &esize); if (rc) { - /* Cancel running request if interrupted */ - if (rc == -ERESTARTSYS) { + /* Cancel running request if interrupted or timed out */ + if (rc == -ERESTARTSYS || rc == -ETIME) { if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) { pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n", (size_t)dsize * PAGE_SIZE); |