[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 f2b77e7bfc6f389aa11061a2c9986edfd98ff735..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;
 }