[S390] chsc: use the global page to determine the chp desriptor

chsc_determine_channel_path_desc is called by a wrapper
who allocates a response struct. The response data
is then memcpy'ed to this response struct by
chsc_determine_channel_path_desc.

Change chsc_determine_base_channel_path_desc to use the
global chsc_page and deliver it to the function doing
the actual chsc call. The channel path desriptor is
then directly read from the response data.

As a result we get rid of the additional allocation
for the response struct.

Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index f2b77e7..3c3f3ff 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -688,25 +688,31 @@
 
 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;
 }