s390/sclp: generic event mask accessors
authorClaudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Tue, 23 Jan 2018 15:41:38 +0000 (16:41 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 22 Feb 2018 14:31:24 +0000 (15:31 +0100)
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 <heiko.carstens@de.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/char/sclp.c
drivers/s390/char/sclp.h
drivers/s390/char/sclp_early.c
drivers/s390/char/sclp_early_core.c

index fe85f9aaf3593bf05a4345dcb3aa9c58ec803377..59e3219ce5c941d41f9e401da55c6899b21386c9 100644 (file)
@@ -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;
index e31aaf266154b9cba1413e443c6add83327411b4..ee44d169f10fd2ed9c6011e002b920ac138e7bbb 100644 (file)
@@ -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);
index 6b1891539c840b723409f03d054125cc50b924a2..9a74abb9224d02fc47041e98a6600265a3bac881 100644 (file)
@@ -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))
index e33d8be518d1f75678995af581f15aa81cc448f7..c8c53260f4b71f4188e509f3bb21ba58adba25d2 100644 (file)
@@ -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;
 }