From b843563518c1e06521c446b9a043b7d352df02e0 Mon Sep 17 00:00:00 2001 From: Claudio Imbrenda Date: Tue, 23 Jan 2018 16:41:38 +0100 Subject: [PATCH] s390/sclp: generic event mask accessors Switch the layout of the event masks to be a generic buffer, and implement accessors to retrieve the values of the masks. This will be needed in the next patches, where we will eventually switch the mask size to 64 bits. Reviewed-by: Heiko Carstens Signed-off-by: Claudio Imbrenda Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp.c | 29 +++++++++-------- drivers/s390/char/sclp.h | 48 ++++++++++++++++++++++++++--- drivers/s390/char/sclp_early.c | 2 +- drivers/s390/char/sclp_early_core.c | 19 +++++++++--- 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index fe85f9aaf359..59e3219ce5c9 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -618,9 +618,12 @@ struct sclp_statechangebuf { u16 _zeros : 12; u16 mask_length; u64 sclp_active_facility_mask; - sccb_mask_t sclp_receive_mask; - sccb_mask_t sclp_send_mask; - u32 read_data_function_mask; + u8 masks[2 * 1021 + 4]; /* variable length */ + /* + * u8 sclp_receive_mask[mask_length]; + * u8 sclp_send_mask[mask_length]; + * u32 read_data_function_mask; + */ } __attribute__((packed)); @@ -631,14 +634,14 @@ sclp_state_change_cb(struct evbuf_header *evbuf) unsigned long flags; struct sclp_statechangebuf *scbuf; + BUILD_BUG_ON(sizeof(struct sclp_statechangebuf) > PAGE_SIZE); + scbuf = (struct sclp_statechangebuf *) evbuf; - if (scbuf->mask_length != sizeof(sccb_mask_t)) - return; spin_lock_irqsave(&sclp_lock, flags); if (scbuf->validity_sclp_receive_mask) - sclp_receive_mask = scbuf->sclp_receive_mask; + sclp_receive_mask = sccb_get_recv_mask(scbuf); if (scbuf->validity_sclp_send_mask) - sclp_send_mask = scbuf->sclp_send_mask; + sclp_send_mask = sccb_get_send_mask(scbuf); spin_unlock_irqrestore(&sclp_lock, flags); if (scbuf->validity_sclp_active_facility_mask) sclp.facilities = scbuf->sclp_active_facility_mask; @@ -763,10 +766,10 @@ __sclp_make_init_req(sccb_mask_t receive_mask, sccb_mask_t send_mask) sclp_init_req.sccb = sccb; sccb->header.length = sizeof(*sccb); sccb->mask_length = sizeof(sccb_mask_t); - sccb->receive_mask = receive_mask; - sccb->send_mask = send_mask; - sccb->sclp_receive_mask = 0; - sccb->sclp_send_mask = 0; + sccb_set_recv_mask(sccb, receive_mask); + sccb_set_send_mask(sccb, send_mask); + sccb_set_sclp_recv_mask(sccb, 0); + sccb_set_sclp_send_mask(sccb, 0); } /* Start init mask request. If calculate is non-zero, calculate the mask as @@ -822,8 +825,8 @@ sclp_init_mask(int calculate) sccb->header.response_code == 0x20) { /* Successful request */ if (calculate) { - sclp_receive_mask = sccb->sclp_receive_mask; - sclp_send_mask = sccb->sclp_send_mask; + sclp_receive_mask = sccb_get_sclp_recv_mask(sccb); + sclp_send_mask = sccb_get_sclp_send_mask(sccb); } else { sclp_receive_mask = 0; sclp_send_mask = 0; diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index e31aaf266154..ee44d169f10f 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -100,12 +100,51 @@ struct init_sccb { struct sccb_header header; u16 _reserved; u16 mask_length; - sccb_mask_t receive_mask; - sccb_mask_t send_mask; - sccb_mask_t sclp_receive_mask; - sccb_mask_t sclp_send_mask; + u8 masks[4 * 1021]; /* variable length */ + /* + * u8 receive_mask[mask_length]; + * u8 send_mask[mask_length]; + * u8 sclp_receive_mask[mask_length]; + * u8 sclp_send_mask[mask_length]; + */ } __attribute__((packed)); +static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i) +{ + sccb_mask_t res = 0; + + memcpy(&res, masks + i * len, min(sizeof(res), len)); + return res; +} + +static inline void sccb_set_mask(u8 *masks, size_t len, int i, sccb_mask_t val) +{ + memset(masks + i * len, 0, len); + memcpy(masks + i * len, &val, min(sizeof(val), len)); +} + +#define sccb_get_generic_mask(sccb, i) \ +({ \ + __typeof__(sccb) __sccb = sccb; \ + \ + sccb_get_mask(__sccb->masks, __sccb->mask_length, i); \ +}) +#define sccb_get_recv_mask(sccb) sccb_get_generic_mask(sccb, 0) +#define sccb_get_send_mask(sccb) sccb_get_generic_mask(sccb, 1) +#define sccb_get_sclp_recv_mask(sccb) sccb_get_generic_mask(sccb, 2) +#define sccb_get_sclp_send_mask(sccb) sccb_get_generic_mask(sccb, 3) + +#define sccb_set_generic_mask(sccb, i, val) \ +({ \ + __typeof__(sccb) __sccb = sccb; \ + \ + sccb_set_mask(__sccb->masks, __sccb->mask_length, i, val); \ +}) +#define sccb_set_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 0, val) +#define sccb_set_send_mask(sccb, val) sccb_set_generic_mask(sccb, 1, val) +#define sccb_set_sclp_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 2, val) +#define sccb_set_sclp_send_mask(sccb, val) sccb_set_generic_mask(sccb, 3, val) + struct read_cpu_info_sccb { struct sccb_header header; u16 nr_configured; @@ -229,6 +268,7 @@ extern char sclp_early_sccb[PAGE_SIZE]; void sclp_early_wait_irq(void); int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb); unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb); +unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb); int sclp_early_set_event_mask(struct init_sccb *sccb, sccb_mask_t receive_mask, sccb_mask_t send_mask); diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 6b1891539c84..9a74abb9224d 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -249,7 +249,7 @@ static void __init sclp_early_console_detect(struct init_sccb *sccb) if (sccb->header.response_code != 0x20) return; - if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) + if (sclp_early_con_check_vt220(sccb)) sclp.has_vt220 = 1; if (sclp_early_con_check_linemode(sccb)) diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index e33d8be518d1..c8c53260f4b7 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -148,8 +148,8 @@ int sclp_early_set_event_mask(struct init_sccb *sccb, memset(sccb, 0, sizeof(*sccb)); sccb->header.length = sizeof(*sccb); sccb->mask_length = sizeof(sccb_mask_t); - sccb->receive_mask = receive_mask; - sccb->send_mask = send_mask; + 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 != 0x20) @@ -159,19 +159,28 @@ int sclp_early_set_event_mask(struct init_sccb *sccb, unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb) { - if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK)) + if (!(sccb_get_sclp_send_mask(sccb) & EVTYP_OPCMD_MASK)) return 0; - if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) + if (!(sccb_get_sclp_recv_mask(sccb) & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) return 0; return 1; } +unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb) +{ + if (sccb_get_sclp_send_mask(sccb) & EVTYP_VT220MSG_MASK) + return 1; + return 0; +} + static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220) { unsigned long receive_mask, send_mask; struct init_sccb *sccb; int rc; + BUILD_BUG_ON(sizeof(struct init_sccb) > PAGE_SIZE); + *have_linemode = *have_vt220 = 0; sccb = (struct init_sccb *) &sclp_early_sccb; receive_mask = disable ? 0 : EVTYP_OPCMD_MASK; @@ -180,7 +189,7 @@ static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220) if (rc) return rc; *have_linemode = sclp_early_con_check_linemode(sccb); - *have_vt220 = sccb->send_mask & EVTYP_VT220MSG_MASK; + *have_vt220 = !!(sccb_get_send_mask(sccb) & EVTYP_VT220MSG_MASK); return rc; }