aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/chsc_sch.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2013-06-06 03:50:21 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-06-26 15:10:12 -0400
commite9a8f32a98a6099b009ea7da4f299bb5427db126 (patch)
tree0fc44d45b835859404ace9043c11696f64fea67a /drivers/s390/cio/chsc_sch.c
parent7a9cc6e18b8fe751a41349b188dd468a8317192a (diff)
s390/cio: Introduce on-close CHSC IOCTLs
Introduce two new ioctls CHSC_ON_CLOSE_SET and CHSC_ON_CLOSE_REMOVE that allow to add and remove one CHSC that is unconditionally executed when the CHSC device node is closed. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/chsc_sch.c')
-rw-r--r--drivers/s390/cio/chsc_sch.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 5fe9f8c4b4fb..64cd60063ffc 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -29,6 +29,10 @@
29static debug_info_t *chsc_debug_msg_id; 29static debug_info_t *chsc_debug_msg_id;
30static debug_info_t *chsc_debug_log_id; 30static debug_info_t *chsc_debug_log_id;
31 31
32static struct chsc_request *on_close_request;
33static struct chsc_async_area *on_close_chsc_area;
34static DEFINE_MUTEX(on_close_mutex);
35
32#define CHSC_MSG(imp, args...) do { \ 36#define CHSC_MSG(imp, args...) do { \
33 debug_sprintf_event(chsc_debug_msg_id, imp , ##args); \ 37 debug_sprintf_event(chsc_debug_msg_id, imp , ##args); \
34 } while (0) 38 } while (0)
@@ -362,6 +366,68 @@ out_free:
362 return ret; 366 return ret;
363} 367}
364 368
369static int chsc_ioctl_on_close_set(void __user *user_area)
370{
371 char dbf[13];
372 int ret;
373
374 mutex_lock(&on_close_mutex);
375 if (on_close_chsc_area) {
376 ret = -EBUSY;
377 goto out_unlock;
378 }
379 on_close_request = kzalloc(sizeof(*on_close_request), GFP_KERNEL);
380 if (!on_close_request) {
381 ret = -ENOMEM;
382 goto out_unlock;
383 }
384 on_close_chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
385 if (!on_close_chsc_area) {
386 ret = -ENOMEM;
387 goto out_free_request;
388 }
389 if (copy_from_user(on_close_chsc_area, user_area, PAGE_SIZE)) {
390 ret = -EFAULT;
391 goto out_free_chsc;
392 }
393 ret = 0;
394 goto out_unlock;
395
396out_free_chsc:
397 free_page((unsigned long)on_close_chsc_area);
398 on_close_chsc_area = NULL;
399out_free_request:
400 kfree(on_close_request);
401 on_close_request = NULL;
402out_unlock:
403 mutex_unlock(&on_close_mutex);
404 sprintf(dbf, "ocsret:%d", ret);
405 CHSC_LOG(0, dbf);
406 return ret;
407}
408
409static int chsc_ioctl_on_close_remove(void)
410{
411 char dbf[13];
412 int ret;
413
414 mutex_lock(&on_close_mutex);
415 if (!on_close_chsc_area) {
416 ret = -ENOENT;
417 goto out_unlock;
418 }
419 free_page((unsigned long)on_close_chsc_area);
420 on_close_chsc_area = NULL;
421 kfree(on_close_request);
422 on_close_request = NULL;
423 ret = 0;
424out_unlock:
425 mutex_unlock(&on_close_mutex);
426 sprintf(dbf, "ocrret:%d", ret);
427 CHSC_LOG(0, dbf);
428 return ret;
429}
430
365static int chsc_ioctl_start_sync(void __user *user_area) 431static int chsc_ioctl_start_sync(void __user *user_area)
366{ 432{
367 struct chsc_sync_area *chsc_area; 433 struct chsc_sync_area *chsc_area;
@@ -842,6 +908,10 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd,
842 return chsc_ioctl_chpd(argp); 908 return chsc_ioctl_chpd(argp);
843 case CHSC_INFO_DCAL: 909 case CHSC_INFO_DCAL:
844 return chsc_ioctl_dcal(argp); 910 return chsc_ioctl_dcal(argp);
911 case CHSC_ON_CLOSE_SET:
912 return chsc_ioctl_on_close_set(argp);
913 case CHSC_ON_CLOSE_REMOVE:
914 return chsc_ioctl_on_close_remove();
845 default: /* unknown ioctl number */ 915 default: /* unknown ioctl number */
846 return -ENOIOCTLCMD; 916 return -ENOIOCTLCMD;
847 } 917 }
@@ -860,6 +930,30 @@ static int chsc_open(struct inode *inode, struct file *file)
860 930
861static int chsc_release(struct inode *inode, struct file *filp) 931static int chsc_release(struct inode *inode, struct file *filp)
862{ 932{
933 char dbf[13];
934 int ret;
935
936 mutex_lock(&on_close_mutex);
937 if (!on_close_chsc_area)
938 goto out_unlock;
939 init_completion(&on_close_request->completion);
940 CHSC_LOG(0, "on_close");
941 chsc_log_command(on_close_chsc_area);
942 spin_lock_irq(&chsc_lock);
943 ret = chsc_async(on_close_chsc_area, on_close_request);
944 spin_unlock_irq(&chsc_lock);
945 if (ret == -EINPROGRESS) {
946 wait_for_completion(&on_close_request->completion);
947 ret = chsc_examine_irb(on_close_request);
948 }
949 sprintf(dbf, "relret:%d", ret);
950 CHSC_LOG(0, dbf);
951 free_page((unsigned long)on_close_chsc_area);
952 on_close_chsc_area = NULL;
953 kfree(on_close_request);
954 on_close_request = NULL;
955out_unlock:
956 mutex_unlock(&on_close_mutex);
863 atomic_inc(&chsc_ready_for_use); 957 atomic_inc(&chsc_ready_for_use);
864 return 0; 958 return 0;
865} 959}