Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Michael Holzheu and committed by
Martin Schwidefsky
e9a8f32a 7a9cc6e1

+96
+2
arch/s390/include/uapi/asm/chsc.h
··· 137 137 #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info) 138 138 #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal) 139 139 #define CHSC_START_SYNC _IOWR(CHSC_IOCTL_MAGIC, 0x89, struct chsc_sync_area) 140 + #define CHSC_ON_CLOSE_SET _IOWR(CHSC_IOCTL_MAGIC, 0x8a, struct chsc_async_area) 141 + #define CHSC_ON_CLOSE_REMOVE _IO(CHSC_IOCTL_MAGIC, 0x8b) 140 142 141 143 #endif
+94
drivers/s390/cio/chsc_sch.c
··· 29 29 static debug_info_t *chsc_debug_msg_id; 30 30 static debug_info_t *chsc_debug_log_id; 31 31 32 + static struct chsc_request *on_close_request; 33 + static struct chsc_async_area *on_close_chsc_area; 34 + static DEFINE_MUTEX(on_close_mutex); 35 + 32 36 #define CHSC_MSG(imp, args...) do { \ 33 37 debug_sprintf_event(chsc_debug_msg_id, imp , ##args); \ 34 38 } while (0) ··· 363 359 CHSC_LOG(0, dbf); 364 360 kfree(request); 365 361 free_page((unsigned long)chsc_area); 362 + return ret; 363 + } 364 + 365 + static int chsc_ioctl_on_close_set(void __user *user_area) 366 + { 367 + char dbf[13]; 368 + int ret; 369 + 370 + mutex_lock(&on_close_mutex); 371 + if (on_close_chsc_area) { 372 + ret = -EBUSY; 373 + goto out_unlock; 374 + } 375 + on_close_request = kzalloc(sizeof(*on_close_request), GFP_KERNEL); 376 + if (!on_close_request) { 377 + ret = -ENOMEM; 378 + goto out_unlock; 379 + } 380 + on_close_chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL); 381 + if (!on_close_chsc_area) { 382 + ret = -ENOMEM; 383 + goto out_free_request; 384 + } 385 + if (copy_from_user(on_close_chsc_area, user_area, PAGE_SIZE)) { 386 + ret = -EFAULT; 387 + goto out_free_chsc; 388 + } 389 + ret = 0; 390 + goto out_unlock; 391 + 392 + out_free_chsc: 393 + free_page((unsigned long)on_close_chsc_area); 394 + on_close_chsc_area = NULL; 395 + out_free_request: 396 + kfree(on_close_request); 397 + on_close_request = NULL; 398 + out_unlock: 399 + mutex_unlock(&on_close_mutex); 400 + sprintf(dbf, "ocsret:%d", ret); 401 + CHSC_LOG(0, dbf); 402 + return ret; 403 + } 404 + 405 + static int chsc_ioctl_on_close_remove(void) 406 + { 407 + char dbf[13]; 408 + int ret; 409 + 410 + mutex_lock(&on_close_mutex); 411 + if (!on_close_chsc_area) { 412 + ret = -ENOENT; 413 + goto out_unlock; 414 + } 415 + free_page((unsigned long)on_close_chsc_area); 416 + on_close_chsc_area = NULL; 417 + kfree(on_close_request); 418 + on_close_request = NULL; 419 + ret = 0; 420 + out_unlock: 421 + mutex_unlock(&on_close_mutex); 422 + sprintf(dbf, "ocrret:%d", ret); 423 + CHSC_LOG(0, dbf); 366 424 return ret; 367 425 } 368 426 ··· 908 842 return chsc_ioctl_chpd(argp); 909 843 case CHSC_INFO_DCAL: 910 844 return chsc_ioctl_dcal(argp); 845 + case CHSC_ON_CLOSE_SET: 846 + return chsc_ioctl_on_close_set(argp); 847 + case CHSC_ON_CLOSE_REMOVE: 848 + return chsc_ioctl_on_close_remove(); 911 849 default: /* unknown ioctl number */ 912 850 return -ENOIOCTLCMD; 913 851 } ··· 930 860 931 861 static int chsc_release(struct inode *inode, struct file *filp) 932 862 { 863 + char dbf[13]; 864 + int ret; 865 + 866 + mutex_lock(&on_close_mutex); 867 + if (!on_close_chsc_area) 868 + goto out_unlock; 869 + init_completion(&on_close_request->completion); 870 + CHSC_LOG(0, "on_close"); 871 + chsc_log_command(on_close_chsc_area); 872 + spin_lock_irq(&chsc_lock); 873 + ret = chsc_async(on_close_chsc_area, on_close_request); 874 + spin_unlock_irq(&chsc_lock); 875 + if (ret == -EINPROGRESS) { 876 + wait_for_completion(&on_close_request->completion); 877 + ret = chsc_examine_irb(on_close_request); 878 + } 879 + sprintf(dbf, "relret:%d", ret); 880 + CHSC_LOG(0, dbf); 881 + free_page((unsigned long)on_close_chsc_area); 882 + on_close_chsc_area = NULL; 883 + kfree(on_close_request); 884 + on_close_request = NULL; 885 + out_unlock: 886 + mutex_unlock(&on_close_mutex); 933 887 atomic_inc(&chsc_ready_for_use); 934 888 return 0; 935 889 }