[S390] chsc: use the global page to determine the chp desriptor
[firefly-linux-kernel-4.4.55.git] / drivers / s390 / cio / chsc_sch.c
index a83877c664a654108791d785526f22f7de4e7043..3c3f3ffe21794fde9ce1a4c89cd06f182b385637 100644 (file)
@@ -688,25 +688,31 @@ out_free:
 
 static int chsc_ioctl_chpd(void __user *user_chpd)
 {
+       struct chsc_scpd *scpd_area;
        struct chsc_cpd_info *chpd;
        int ret;
 
        chpd = kzalloc(sizeof(*chpd), GFP_KERNEL);
-       if (!chpd)
-               return -ENOMEM;
+       scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!scpd_area || !chpd) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
        if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) {
                ret = -EFAULT;
                goto out_free;
        }
        ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt,
                                               chpd->rfmt, chpd->c, chpd->m,
-                                              &chpd->chpdb);
+                                              scpd_area);
        if (ret)
                goto out_free;
+       memcpy(&chpd->chpdb, &scpd_area->response, scpd_area->response.length);
        if (copy_to_user(user_chpd, chpd, sizeof(*chpd)))
                ret = -EFAULT;
 out_free:
        kfree(chpd);
+       free_page((unsigned long)scpd_area);
        return ret;
 }
 
@@ -806,6 +812,7 @@ static const struct file_operations chsc_fops = {
        .open = nonseekable_open,
        .unlocked_ioctl = chsc_ioctl,
        .compat_ioctl = chsc_ioctl,
+       .llseek = no_llseek,
 };
 
 static struct miscdevice chsc_misc_device = {