s390/cio: Introduce generic synchronous CHSC IOCTL
[sfrench/cifs-2.6.git] / drivers / s390 / cio / chsc_sch.c
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: