diff options
author | Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> | 2018-01-23 18:50:43 +0300 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2018-02-22 17:31:24 +0300 |
commit | 0b0d1173d8aef75e821c0cceedb0e8178834ec1b (patch) | |
tree | eceecae57a15d49a22440434cc3aeb0ed0e97831 /drivers/s390/char/sclp_early_core.c | |
parent | b843563518c1e06521c446b9a043b7d352df02e0 (diff) | |
download | linux-0b0d1173d8aef75e821c0cceedb0e8178834ec1b.tar.xz |
s390/sclp: 32 bit event mask compatibility mode
Qemu before version 2.11 does not implement the architecture correctly,
and does not allow for a mask size of size different than 4.
This patch introduces a compatibility mode for such systems, forcing
the mask sizes to 4.
Since the mask size is currently still 4 anyway, this patch should have
no impact whatsoever by itself, but it will be needed when the mask size
is increased to 64 bits in the next patch.
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/char/sclp_early_core.c')
-rw-r--r-- | drivers/s390/char/sclp_early_core.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index c8c53260f4b7..5f8d9ea69ebd 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -14,6 +14,11 @@ char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data); int sclp_init_state __section(.data) = sclp_init_state_uninitialized; +/* + * Used to keep track of the size of the event masks. Qemu until version 2.11 + * only supports 4 and needs a workaround. + */ +bool sclp_mask_compat_mode; void sclp_early_wait_irq(void) { @@ -145,13 +150,21 @@ int sclp_early_set_event_mask(struct init_sccb *sccb, sccb_mask_t receive_mask, sccb_mask_t send_mask) { +retry: memset(sccb, 0, sizeof(*sccb)); sccb->header.length = sizeof(*sccb); - sccb->mask_length = sizeof(sccb_mask_t); + if (sclp_mask_compat_mode) + sccb->mask_length = SCLP_MASK_SIZE_COMPAT; + else + sccb->mask_length = sizeof(sccb_mask_t); sccb_set_recv_mask(sccb, receive_mask); sccb_set_send_mask(sccb, send_mask); if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb)) return -EIO; + if ((sccb->header.response_code == 0x74f0) && !sclp_mask_compat_mode) { + sclp_mask_compat_mode = true; + goto retry; + } if (sccb->header.response_code != 0x20) return -EIO; return 0; |