forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
b843563518
commit
0b0d1173d8
|
@ -765,7 +765,10 @@ __sclp_make_init_req(sccb_mask_t receive_mask, sccb_mask_t send_mask)
|
||||||
sclp_init_req.callback_data = NULL;
|
sclp_init_req.callback_data = NULL;
|
||||||
sclp_init_req.sccb = sccb;
|
sclp_init_req.sccb = sccb;
|
||||||
sccb->header.length = 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_recv_mask(sccb, receive_mask);
|
||||||
sccb_set_send_mask(sccb, send_mask);
|
sccb_set_send_mask(sccb, send_mask);
|
||||||
sccb_set_sclp_recv_mask(sccb, 0);
|
sccb_set_sclp_recv_mask(sccb, 0);
|
||||||
|
@ -977,12 +980,18 @@ sclp_check_interface(void)
|
||||||
irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
|
irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
|
||||||
spin_lock_irqsave(&sclp_lock, flags);
|
spin_lock_irqsave(&sclp_lock, flags);
|
||||||
del_timer(&sclp_request_timer);
|
del_timer(&sclp_request_timer);
|
||||||
if (sclp_init_req.status == SCLP_REQ_DONE &&
|
rc = -EBUSY;
|
||||||
sccb->header.response_code == 0x20) {
|
if (sclp_init_req.status == SCLP_REQ_DONE) {
|
||||||
rc = 0;
|
if (sccb->header.response_code == 0x20) {
|
||||||
break;
|
rc = 0;
|
||||||
} else
|
break;
|
||||||
rc = -EBUSY;
|
} else if (sccb->header.response_code == 0x74f0) {
|
||||||
|
if (!sclp_mask_compat_mode) {
|
||||||
|
sclp_mask_compat_mode = true;
|
||||||
|
retry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
unregister_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
|
unregister_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
|
||||||
spin_unlock_irqrestore(&sclp_lock, flags);
|
spin_unlock_irqrestore(&sclp_lock, flags);
|
||||||
|
|
|
@ -109,6 +109,8 @@ struct init_sccb {
|
||||||
*/
|
*/
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define SCLP_MASK_SIZE_COMPAT 4
|
||||||
|
|
||||||
static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i)
|
static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i)
|
||||||
{
|
{
|
||||||
sccb_mask_t res = 0;
|
sccb_mask_t res = 0;
|
||||||
|
@ -262,6 +264,7 @@ extern int sclp_init_state;
|
||||||
extern int sclp_console_pages;
|
extern int sclp_console_pages;
|
||||||
extern int sclp_console_drop;
|
extern int sclp_console_drop;
|
||||||
extern unsigned long sclp_console_full;
|
extern unsigned long sclp_console_full;
|
||||||
|
extern bool sclp_mask_compat_mode;
|
||||||
|
|
||||||
extern char sclp_early_sccb[PAGE_SIZE];
|
extern char sclp_early_sccb[PAGE_SIZE];
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
|
|
||||||
char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data);
|
char sclp_early_sccb[PAGE_SIZE] __aligned(PAGE_SIZE) __section(.data);
|
||||||
int sclp_init_state __section(.data) = sclp_init_state_uninitialized;
|
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)
|
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 receive_mask,
|
||||||
sccb_mask_t send_mask)
|
sccb_mask_t send_mask)
|
||||||
{
|
{
|
||||||
|
retry:
|
||||||
memset(sccb, 0, sizeof(*sccb));
|
memset(sccb, 0, sizeof(*sccb));
|
||||||
sccb->header.length = 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_recv_mask(sccb, receive_mask);
|
||||||
sccb_set_send_mask(sccb, send_mask);
|
sccb_set_send_mask(sccb, send_mask);
|
||||||
if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb))
|
if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb))
|
||||||
return -EIO;
|
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)
|
if (sccb->header.response_code != 0x20)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user