aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2013-06-06 03:44:28 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-06-26 15:10:10 -0400
commit64150adf89df2ed165d6760f414fa6df07d22628 (patch)
treefaacbf1ffd1daf2aa370d2b4880b8b093ac2966f /drivers/s390
parent80b054ba2ab1c46e6c34c6a54f542d8f7ad77fca (diff)
s390/cio: Introduce generic synchronous CHSC IOCTL
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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/chsc.h5
-rw-r--r--drivers/s390/cio/chsc_sch.c37
2 files changed, 35 insertions, 7 deletions
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index e7ef2a683b8f..62d096f11e65 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -10,11 +10,6 @@
10 10
11#define CHSC_SDA_OC_MSS 0x2 11#define CHSC_SDA_OC_MSS 0x2
12 12
13struct chsc_header {
14 u16 length;
15 u16 code;
16} __attribute__ ((packed));
17
18#define NR_MEASUREMENT_CHARS 5 13#define NR_MEASUREMENT_CHARS 5
19struct cmg_chars { 14struct cmg_chars {
20 u32 values[NR_MEASUREMENT_CHARS]; 15 u32 values[NR_MEASUREMENT_CHARS];
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index facdf809113f..190fc844d814 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -287,11 +287,11 @@ static int chsc_async(struct chsc_async_area *chsc_area,
287 return ret; 287 return ret;
288} 288}
289 289
290static void chsc_log_command(struct chsc_async_area *chsc_area) 290static void chsc_log_command(void *chsc_area)
291{ 291{
292 char dbf[10]; 292 char dbf[10];
293 293
294 sprintf(dbf, "CHSC:%x", chsc_area->header.code); 294 sprintf(dbf, "CHSC:%x", ((uint16_t *)chsc_area)[1]);
295 CHSC_LOG(0, dbf); 295 CHSC_LOG(0, dbf);
296 CHSC_LOG_HEX(0, chsc_area, 32); 296 CHSC_LOG_HEX(0, chsc_area, 32);
297} 297}
@@ -362,6 +362,37 @@ out_free:
362 return ret; 362 return ret;
363} 363}
364 364
365static int chsc_ioctl_start_sync(void __user *user_area)
366{
367 struct chsc_sync_area *chsc_area;
368 int ret, ccode;
369
370 chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
371 if (!chsc_area)
372 return -ENOMEM;
373 if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
374 ret = -EFAULT;
375 goto out_free;
376 }
377 if (chsc_area->header.code & 0x4000) {
378 ret = -EINVAL;
379 goto out_free;
380 }
381 chsc_log_command(chsc_area);
382 ccode = chsc(chsc_area);
383 if (ccode != 0) {
384 ret = -EIO;
385 goto out_free;
386 }
387 if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
388 ret = -EFAULT;
389 else
390 ret = 0;
391out_free:
392 free_page((unsigned long)chsc_area);
393 return ret;
394}
395
365static int chsc_ioctl_info_channel_path(void __user *user_cd) 396static int chsc_ioctl_info_channel_path(void __user *user_cd)
366{ 397{
367 struct chsc_chp_cd *cd; 398 struct chsc_chp_cd *cd;
@@ -795,6 +826,8 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,
795 switch (cmd) { 826 switch (cmd) {
796 case CHSC_START: 827 case CHSC_START:
797 return chsc_ioctl_start(argp); 828 return chsc_ioctl_start(argp);
829 case CHSC_START_SYNC:
830 return chsc_ioctl_start_sync(argp);
798 case CHSC_INFO_CHANNEL_PATH: 831 case CHSC_INFO_CHANNEL_PATH:
799 return chsc_ioctl_info_channel_path(argp); 832 return chsc_ioctl_info_channel_path(argp);
800 case CHSC_INFO_CU: 833 case CHSC_INFO_CU: