sclp_init_req.callback_data = NULL;
sclp_init_req.sccb = 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);
sccb_set_sclp_recv_mask(sccb, 0);
irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
spin_lock_irqsave(&sclp_lock, flags);
del_timer(&sclp_request_timer);
- if (sclp_init_req.status == SCLP_REQ_DONE &&
- sccb->header.response_code == 0x20) {
- rc = 0;
- break;
- } else
- rc = -EBUSY;
+ rc = -EBUSY;
+ if (sclp_init_req.status == SCLP_REQ_DONE) {
+ if (sccb->header.response_code == 0x20) {
+ rc = 0;
+ break;
+ } 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);
spin_unlock_irqrestore(&sclp_lock, flags);
*/
} __attribute__((packed));
+#define SCLP_MASK_SIZE_COMPAT 4
+
static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i)
{
sccb_mask_t res = 0;
extern int sclp_console_pages;
extern int sclp_console_drop;
extern unsigned long sclp_console_full;
+extern bool sclp_mask_compat_mode;
extern char sclp_early_sccb[PAGE_SIZE];
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)
{
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;