diff options
-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); |