s390/cio: Introduce generic synchronous CHSC IOCTL
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Thu, 6 Jun 2013 07:44:28 +0000 (09:44 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 26 Jun 2013 19:10:10 +0000 (21:10 +0200)
This patch adds a new ioctl CHSC_START_SYNC that allows to
execute any synchronous CHSC that is provided by user space.

Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/uapi/asm/chsc.h
drivers/s390/cio/chsc.h
drivers/s390/cio/chsc_sch.c

index 1c6a7f85a5819d5354acb38f91820be5767d789c..6e5307fbeb1e8397690a5746c1e92f01fa391c82 100644 (file)
@@ -29,6 +29,16 @@ struct chsc_async_area {
        __u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
 } __attribute__ ((packed));
 
+struct chsc_header {
+       __u16 length;
+       __u16 code;
+} __attribute__ ((packed));
+
+struct chsc_sync_area {
+       struct chsc_header header;
+       __u8 data[CHSC_SIZE - sizeof(struct chsc_header)];
+} __attribute__ ((packed));
+
 struct chsc_response_struct {
        __u16 length;
        __u16 code;
@@ -126,5 +136,6 @@ struct chsc_cpd_info {
 #define CHSC_INFO_CCL _IOWR(CHSC_IOCTL_MAGIC, 0x86, struct chsc_comp_list)
 #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)
 #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal)
+#define CHSC_START_SYNC _IOWR(CHSC_IOCTL_MAGIC, 0x89, struct chsc_sync_area)
 
 #endif
index e7ef2a683b8fbc617368ad855f4f18d6832b3eb6..62d096f11e65bc66542fe2877a2dfd7ce214f02c 100644 (file)
 
 #define CHSC_SDA_OC_MSS   0x2
 
-struct chsc_header {
-       u16 length;
-       u16 code;
-} __attribute__ ((packed));
-
 #define NR_MEASUREMENT_CHARS 5
 struct cmg_chars {
        u32 values[NR_MEASUREMENT_CHARS];
index facdf809113f22a6fe9e070b3f8938942bbaf480..190fc844d8149622638c84348e2aefd3b59a4121 100644 (file)
@@ -287,11 +287,11 @@ static int chsc_async(struct chsc_async_area *chsc_area,
        return ret;
 }
 
-static void chsc_log_command(struct chsc_async_area *chsc_area)
+static void chsc_log_command(void *chsc_area)
 {
        char dbf[10];
 
-       sprintf(dbf, "CHSC:%x", chsc_area->header.code);
+       sprintf(dbf, "CHSC:%x", ((uint16_t *)chsc_area)[1]);
        CHSC_LOG(0, dbf);
        CHSC_LOG_HEX(0, chsc_area, 32);
 }
@@ -362,6 +362,37 @@ out_free:
        return ret;
 }
 
+static int chsc_ioctl_start_sync(void __user *user_area)
+{
+       struct chsc_sync_area *chsc_area;
+       int ret, ccode;
+
+       chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!chsc_area)
+               return -ENOMEM;
+       if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       if (chsc_area->header.code & 0x4000) {
+               ret = -EINVAL;
+               goto out_free;
+       }
+       chsc_log_command(chsc_area);
+       ccode = chsc(chsc_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       free_page((unsigned long)chsc_area);
+       return ret;
+}
+
 static int chsc_ioctl_info_channel_path(void __user *user_cd)
 {
        struct chsc_chp_cd *cd;
@@ -795,6 +826,8 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,
        switch (cmd) {
        case CHSC_START:
                return chsc_ioctl_start(argp);
+       case CHSC_START_SYNC:
+               return chsc_ioctl_start_sync(argp);
        case CHSC_INFO_CHANNEL_PATH:
                return chsc_ioctl_info_channel_path(argp);
        case CHSC_INFO_CU: