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

Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] Fix broken logic, SIGA flags must be bitwise ORed
[S390] cio: Dont print trailing \0 in modalias_show().
[S390] Simplify stack trace.
[S390] z/VM unit record device driver
[S390] vmcp cleanup
[S390] qdio: output queue stall on FCP and network devices
[S390] Fix disassembly of RX_URRD, SI_URD & PC-relative instructions.
[S390] Update default configuration.

+1126 -145
+32 -78
arch/s390/defconfig
··· 1 1 # 2 2 # Automatically generated make config: don't edit 3 - # Linux kernel version: 2.6.21 4 - # Thu May 10 15:18:19 2007 3 + # Linux kernel version: 2.6.22 4 + # Tue Jul 17 12:50:23 2007 5 5 # 6 6 CONFIG_MMU=y 7 7 CONFIG_ZONE_DMA=y ··· 32 32 CONFIG_LOCALVERSION_AUTO=y 33 33 CONFIG_SWAP=y 34 34 CONFIG_SYSVIPC=y 35 - # CONFIG_IPC_NS is not set 36 35 CONFIG_SYSVIPC_SYSCTL=y 37 36 CONFIG_POSIX_MQUEUE=y 38 37 # CONFIG_BSD_PROCESS_ACCT is not set 39 38 # CONFIG_TASKSTATS is not set 40 - # CONFIG_UTS_NS is not set 39 + # CONFIG_USER_NS is not set 41 40 CONFIG_AUDIT=y 42 41 # CONFIG_AUDITSYSCALL is not set 43 42 CONFIG_IKCONFIG=y ··· 60 61 CONFIG_ELF_CORE=y 61 62 CONFIG_BASE_FULL=y 62 63 CONFIG_FUTEX=y 64 + CONFIG_ANON_INODES=y 63 65 CONFIG_EPOLL=y 66 + CONFIG_SIGNALFD=y 67 + CONFIG_TIMERFD=y 68 + CONFIG_EVENTFD=y 64 69 CONFIG_SHMEM=y 65 70 CONFIG_VM_EVENT_COUNTERS=y 66 - CONFIG_SLUB_DEBUG=y 67 71 CONFIG_SLAB=y 68 72 # CONFIG_SLUB is not set 69 73 # CONFIG_SLOB is not set 70 74 CONFIG_RT_MUTEXES=y 71 75 # CONFIG_TINY_SHMEM is not set 72 76 CONFIG_BASE_SMALL=0 73 - 74 - # 75 - # Loadable module support 76 - # 77 77 CONFIG_MODULES=y 78 78 CONFIG_MODULE_UNLOAD=y 79 79 # CONFIG_MODULE_FORCE_UNLOAD is not set ··· 80 82 # CONFIG_MODULE_SRCVERSION_ALL is not set 81 83 CONFIG_KMOD=y 82 84 CONFIG_STOP_MACHINE=y 83 - 84 - # 85 - # Block layer 86 - # 87 85 CONFIG_BLOCK=y 88 86 # CONFIG_BLK_DEV_IO_TRACE is not set 87 + CONFIG_BLK_DEV_BSG=y 89 88 90 89 # 91 90 # IO Schedulers ··· 146 151 CONFIG_SPLIT_PTLOCK_CPUS=4 147 152 CONFIG_RESOURCES_64BIT=y 148 153 CONFIG_ZONE_DMA_FLAG=1 154 + CONFIG_VIRT_TO_BUS=y 149 155 CONFIG_HOLES_IN_ZONE=y 150 156 151 157 # ··· 244 248 # CONFIG_IPV6_MULTIPLE_TABLES is not set 245 249 # CONFIG_NETWORK_SECMARK is not set 246 250 # CONFIG_NETFILTER is not set 247 - 248 - # 249 - # DCCP Configuration (EXPERIMENTAL) 250 - # 251 251 # CONFIG_IP_DCCP is not set 252 - 253 - # 254 - # SCTP Configuration (EXPERIMENTAL) 255 - # 256 252 CONFIG_IP_SCTP=m 257 253 # CONFIG_SCTP_DBG_MSG is not set 258 254 # CONFIG_SCTP_DBG_OBJCNT is not set 259 255 # CONFIG_SCTP_HMAC_NONE is not set 260 256 # CONFIG_SCTP_HMAC_SHA1 is not set 261 257 CONFIG_SCTP_HMAC_MD5=y 262 - 263 - # 264 - # TIPC Configuration (EXPERIMENTAL) 265 - # 266 258 # CONFIG_TIPC is not set 267 259 # CONFIG_ATM is not set 268 260 # CONFIG_BRIDGE is not set ··· 277 293 # CONFIG_NET_SCH_HTB is not set 278 294 # CONFIG_NET_SCH_HFSC is not set 279 295 CONFIG_NET_SCH_PRIO=m 296 + CONFIG_NET_SCH_RR=m 280 297 CONFIG_NET_SCH_RED=m 281 298 CONFIG_NET_SCH_SFQ=m 282 299 CONFIG_NET_SCH_TEQL=m ··· 302 317 CONFIG_NET_CLS_RSVP=m 303 318 CONFIG_NET_CLS_RSVP6=m 304 319 # CONFIG_NET_EMATCH is not set 305 - # CONFIG_NET_CLS_ACT is not set 320 + CONFIG_NET_CLS_ACT=y 321 + CONFIG_NET_ACT_POLICE=y 322 + # CONFIG_NET_ACT_GACT is not set 323 + # CONFIG_NET_ACT_MIRRED is not set 324 + # CONFIG_NET_ACT_PEDIT is not set 325 + # CONFIG_NET_ACT_SIMP is not set 306 326 CONFIG_NET_CLS_POLICE=y 307 327 # CONFIG_NET_CLS_IND is not set 308 - CONFIG_NET_ESTIMATOR=y 309 328 310 329 # 311 330 # Network testing ··· 318 329 # CONFIG_NET_TCPPROBE is not set 319 330 # CONFIG_AF_RXRPC is not set 320 331 # CONFIG_RFKILL is not set 332 + # CONFIG_NET_9P is not set 321 333 # CONFIG_PCMCIA is not set 322 334 CONFIG_CCW=y 323 335 ··· 335 345 # CONFIG_DEBUG_DRIVER is not set 336 346 # CONFIG_DEBUG_DEVRES is not set 337 347 CONFIG_SYS_HYPERVISOR=y 338 - 339 - # 340 - # Connector - unified userspace <-> kernelspace linker 341 - # 342 348 # CONFIG_CONNECTOR is not set 343 - 344 - # 345 - # Block devices 346 - # 349 + CONFIG_BLK_DEV=y 347 350 # CONFIG_BLK_DEV_COW_COMMON is not set 348 351 CONFIG_BLK_DEV_LOOP=m 349 352 # CONFIG_BLK_DEV_CRYPTOLOOP is not set ··· 359 376 CONFIG_DASD_FBA=y 360 377 CONFIG_DASD_DIAG=y 361 378 CONFIG_DASD_EER=y 362 - 363 - # 364 - # Misc devices 365 - # 366 - # CONFIG_BLINK is not set 379 + CONFIG_MISC_DEVICES=y 380 + # CONFIG_EEPROM_93CX6 is not set 367 381 368 382 # 369 383 # SCSI device support 370 384 # 371 385 # CONFIG_RAID_ATTRS is not set 372 386 CONFIG_SCSI=y 387 + # CONFIG_SCSI_DMA is not set 373 388 # CONFIG_SCSI_TGT is not set 374 389 CONFIG_SCSI_NETLINK=y 375 390 CONFIG_SCSI_PROC_FS=y ··· 428 447 CONFIG_DM_ZERO=y 429 448 CONFIG_DM_MULTIPATH=y 430 449 # CONFIG_DM_MULTIPATH_EMC is not set 450 + # CONFIG_DM_MULTIPATH_RDAC is not set 431 451 # CONFIG_DM_DELAY is not set 432 - 433 - # 434 - # Network device support 435 - # 436 452 CONFIG_NETDEVICES=y 453 + # CONFIG_NETDEVICES_MULTIQUEUE is not set 454 + # CONFIG_IFB is not set 437 455 CONFIG_DUMMY=m 438 456 CONFIG_BONDING=m 457 + # CONFIG_MACVLAN is not set 439 458 CONFIG_EQUALIZER=m 440 459 CONFIG_TUN=m 441 - 442 - # 443 - # Ethernet (10 or 100Mbit) 444 - # 445 460 CONFIG_NET_ETHERNET=y 446 461 # CONFIG_MII is not set 447 - 448 - # 449 - # Ethernet (1000 Mbit) 450 - # 451 - 452 - # 453 - # Ethernet (10000 Mbit) 454 - # 455 - CONFIG_MLX4_DEBUG=y 456 - 457 - # 458 - # Token Ring devices 459 - # 462 + CONFIG_NETDEV_1000=y 463 + CONFIG_NETDEV_10000=y 460 464 # CONFIG_TR is not set 461 - 462 - # 463 - # Wan interfaces 464 - # 465 465 # CONFIG_WAN is not set 466 466 467 467 # ··· 473 511 CONFIG_UNIX98_PTYS=y 474 512 CONFIG_LEGACY_PTYS=y 475 513 CONFIG_LEGACY_PTY_COUNT=256 476 - 477 - # 478 - # Watchdog Cards 479 - # 480 514 # CONFIG_WATCHDOG is not set 481 515 CONFIG_HW_RANDOM=m 482 516 # CONFIG_R3964 is not set ··· 512 554 # CONFIG_VMCP is not set 513 555 # CONFIG_MONREADER is not set 514 556 CONFIG_MONWRITER=m 557 + CONFIG_S390_VMUR=m 558 + # CONFIG_POWER_SUPPLY is not set 515 559 516 560 # 517 561 # File systems ··· 615 655 # CONFIG_NCP_FS is not set 616 656 # CONFIG_CODA_FS is not set 617 657 # CONFIG_AFS_FS is not set 618 - # CONFIG_9P_FS is not set 619 658 620 659 # 621 660 # Partition Types ··· 671 712 CONFIG_DEBUG_FS=y 672 713 CONFIG_HEADERS_CHECK=y 673 714 CONFIG_DEBUG_KERNEL=y 715 + # CONFIG_SCHED_DEBUG is not set 674 716 # CONFIG_SCHEDSTATS is not set 675 717 # CONFIG_TIMER_STATS is not set 676 718 # CONFIG_DEBUG_SLAB is not set ··· 700 740 # 701 741 # CONFIG_KEYS is not set 702 742 # CONFIG_SECURITY is not set 703 - 704 - # 705 - # Cryptographic options 706 - # 707 743 CONFIG_CRYPTO=y 708 744 CONFIG_CRYPTO_ALGAPI=y 709 745 CONFIG_CRYPTO_BLKCIPHER=y ··· 738 782 # CONFIG_CRYPTO_CRC32C is not set 739 783 CONFIG_CRYPTO_CAMELLIA=m 740 784 # CONFIG_CRYPTO_TEST is not set 741 - 742 - # 743 - # Hardware crypto devices 744 - # 785 + CONFIG_CRYPTO_HW=y 745 786 # CONFIG_CRYPTO_SHA1_S390 is not set 746 787 # CONFIG_CRYPTO_SHA256_S390 is not set 747 788 # CONFIG_CRYPTO_DES_S390 is not set ··· 753 800 CONFIG_BITREVERSE=m 754 801 # CONFIG_CRC_CCITT is not set 755 802 # CONFIG_CRC16 is not set 803 + # CONFIG_CRC_ITU_T is not set 756 804 CONFIG_CRC32=m 757 805 # CONFIG_LIBCRC32C is not set 758 806 CONFIG_PLIST=y
+4 -3
arch/s390/kernel/dis.c
··· 240 240 [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */ 241 241 [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */ 242 242 [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */ 243 - [INSTR_RX_URRD] = { 0x00, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ 244 - [INSTR_SI_URD] = { 0x00, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ 243 + [INSTR_RX_URRD] = { 0xff, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ 244 + [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ 245 245 [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */ 246 246 [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */ 247 247 [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, ··· 1190 1190 else if (operand->flags & OPERAND_CR) 1191 1191 ptr += sprintf(ptr, "%%c%i", value); 1192 1192 else if (operand->flags & OPERAND_PCREL) 1193 - ptr += sprintf(ptr, "%lx", value + addr); 1193 + ptr += sprintf(ptr, "%lx", (signed int) value 1194 + + addr); 1194 1195 else if (operand->flags & OPERAND_SIGNED) 1195 1196 ptr += sprintf(ptr, "%i", value); 1196 1197 else
+11 -15
arch/s390/kernel/stacktrace.c
··· 12 12 #include <linux/kallsyms.h> 13 13 14 14 static unsigned long save_context_stack(struct stack_trace *trace, 15 - unsigned int *skip, 16 15 unsigned long sp, 17 16 unsigned long low, 18 17 unsigned long high) ··· 27 28 sf = (struct stack_frame *)sp; 28 29 while(1) { 29 30 addr = sf->gprs[8] & PSW_ADDR_INSN; 30 - if (!(*skip)) 31 + if (!trace->skip) 31 32 trace->entries[trace->nr_entries++] = addr; 32 33 else 33 - (*skip)--; 34 + trace->skip--; 34 35 if (trace->nr_entries >= trace->max_entries) 35 36 return sp; 36 37 low = sp; ··· 47 48 return sp; 48 49 regs = (struct pt_regs *)sp; 49 50 addr = regs->psw.addr & PSW_ADDR_INSN; 50 - if (!(*skip)) 51 + if (!trace->skip) 51 52 trace->entries[trace->nr_entries++] = addr; 52 53 else 53 - (*skip)--; 54 + trace->skip--; 54 55 if (trace->nr_entries >= trace->max_entries) 55 56 return sp; 56 57 low = sp; ··· 64 65 unsigned long orig_sp, new_sp; 65 66 66 67 orig_sp = sp & PSW_ADDR_INSN; 67 - 68 - new_sp = save_context_stack(trace, &trace->skip, orig_sp, 69 - S390_lowcore.panic_stack - PAGE_SIZE, 70 - S390_lowcore.panic_stack); 68 + new_sp = save_context_stack(trace, orig_sp, 69 + S390_lowcore.panic_stack - PAGE_SIZE, 70 + S390_lowcore.panic_stack); 71 71 if (new_sp != orig_sp) 72 72 return; 73 - new_sp = save_context_stack(trace, &trace->skip, new_sp, 74 - S390_lowcore.async_stack - ASYNC_SIZE, 75 - S390_lowcore.async_stack); 73 + new_sp = save_context_stack(trace, new_sp, 74 + S390_lowcore.async_stack - ASYNC_SIZE, 75 + S390_lowcore.async_stack); 76 76 if (new_sp != orig_sp) 77 77 return; 78 - 79 - save_context_stack(trace, &trace->skip, new_sp, 78 + save_context_stack(trace, new_sp, 80 79 S390_lowcore.thread_info, 81 80 S390_lowcore.thread_info + THREAD_SIZE); 82 - return; 83 81 }
+6
drivers/s390/char/Kconfig
··· 164 164 help 165 165 Character device driver for writing z/VM monitor service records 166 166 167 + config S390_VMUR 168 + tristate "z/VM unit record device driver" 169 + default "m" 170 + help 171 + Character device driver for z/VM reader, puncher and printer. 172 +
+1
drivers/s390/char/Makefile
··· 29 29 obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o 30 30 obj-$(CONFIG_MONREADER) += monreader.o 31 31 obj-$(CONFIG_MONWRITER) += monwriter.o 32 + obj-$(CONFIG_S390_VMUR) += vmur.o 32 33 33 34 zcore_mod-objs := sclp_sdias.o zcore.o 34 35 obj-$(CONFIG_ZFCPDUMP) += zcore_mod.o
+51 -38
drivers/s390/char/vmcp.c
··· 1 1 /* 2 - * Copyright (C) 2004,2005 IBM Corporation 2 + * Copyright IBM Corp. 2004,2007 3 3 * Interface implementation for communication with the z/VM control program 4 - * Author(s): Christian Borntraeger <cborntra@de.ibm.com> 4 + * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> 5 5 * 6 6 * 7 7 * z/VMs CP offers the possibility to issue commands via the diagnose code 8 ··· 22 22 #include "vmcp.h" 23 23 24 24 MODULE_LICENSE("GPL"); 25 - MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>"); 25 + MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>"); 26 26 MODULE_DESCRIPTION("z/VM CP interface"); 27 + 28 + #define PRINTK_HEADER "vmcp: " 27 29 28 30 static debug_info_t *vmcp_debug; 29 31 ··· 42 40 session->bufsize = PAGE_SIZE; 43 41 session->response = NULL; 44 42 session->resp_size = 0; 45 - init_MUTEX(&session->mutex); 43 + mutex_init(&session->mutex); 46 44 file->private_data = session; 47 45 return nonseekable_open(inode, file); 48 46 } ··· 59 57 } 60 58 61 59 static ssize_t 62 - vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos) 60 + vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) 63 61 { 64 62 size_t tocopy; 65 63 struct vmcp_session *session; 66 64 67 65 session = (struct vmcp_session *)file->private_data; 68 - if (down_interruptible(&session->mutex)) 66 + if (mutex_lock_interruptible(&session->mutex)) 69 67 return -ERESTARTSYS; 70 68 if (!session->response) { 71 - up(&session->mutex); 69 + mutex_unlock(&session->mutex); 72 70 return 0; 73 71 } 74 72 if (*ppos > session->resp_size) { 75 - up(&session->mutex); 73 + mutex_unlock(&session->mutex); 76 74 return 0; 77 75 } 78 76 tocopy = min(session->resp_size - (size_t) (*ppos), count); 79 - tocopy = min(tocopy,session->bufsize - (size_t) (*ppos)); 77 + tocopy = min(tocopy, session->bufsize - (size_t) (*ppos)); 80 78 81 79 if (copy_to_user(buff, session->response + (*ppos), tocopy)) { 82 - up(&session->mutex); 80 + mutex_unlock(&session->mutex); 83 81 return -EFAULT; 84 82 } 85 - up(&session->mutex); 83 + mutex_unlock(&session->mutex); 86 84 *ppos += tocopy; 87 85 return tocopy; 88 86 } 89 87 90 88 static ssize_t 91 - vmcp_write(struct file *file, const char __user * buff, size_t count, 92 - loff_t * ppos) 89 + vmcp_write(struct file *file, const char __user *buff, size_t count, 90 + loff_t *ppos) 93 91 { 94 92 char *cmd; 95 93 struct vmcp_session *session; ··· 105 103 } 106 104 cmd[count] = '\0'; 107 105 session = (struct vmcp_session *)file->private_data; 108 - if (down_interruptible(&session->mutex)) { 106 + if (mutex_lock_interruptible(&session->mutex)) { 109 107 kfree(cmd); 110 108 return -ERESTARTSYS; 111 109 } 112 110 if (!session->response) 113 111 session->response = (char *)__get_free_pages(GFP_KERNEL 114 - | __GFP_REPEAT | GFP_DMA, 112 + | __GFP_REPEAT | GFP_DMA, 115 113 get_order(session->bufsize)); 116 114 if (!session->response) { 117 - up(&session->mutex); 115 + mutex_unlock(&session->mutex); 118 116 kfree(cmd); 119 117 return -ENOMEM; 120 118 } 121 119 debug_text_event(vmcp_debug, 1, cmd); 122 - session->resp_size = cpcmd(cmd, session->response, 123 - session->bufsize, 124 - &session->resp_code); 125 - up(&session->mutex); 120 + session->resp_size = cpcmd(cmd, session->response, session->bufsize, 121 + &session->resp_code); 122 + mutex_unlock(&session->mutex); 126 123 kfree(cmd); 127 124 *ppos = 0; /* reset the file pointer after a command */ 128 125 return count; ··· 146 145 int temp; 147 146 148 147 session = (struct vmcp_session *)file->private_data; 149 - if (down_interruptible(&session->mutex)) 148 + if (mutex_lock_interruptible(&session->mutex)) 150 149 return -ERESTARTSYS; 151 150 switch (cmd) { 152 151 case VMCP_GETCODE: 153 152 temp = session->resp_code; 154 - up(&session->mutex); 153 + mutex_unlock(&session->mutex); 155 154 return put_user(temp, (int __user *)arg); 156 155 case VMCP_SETBUF: 157 156 free_pages((unsigned long)session->response, ··· 162 161 session->bufsize = PAGE_SIZE; 163 162 temp = -EINVAL; 164 163 } 165 - up(&session->mutex); 164 + mutex_unlock(&session->mutex); 166 165 return temp; 167 166 case VMCP_GETSIZE: 168 167 temp = session->resp_size; 169 - up(&session->mutex); 168 + mutex_unlock(&session->mutex); 170 169 return put_user(temp, (int __user *)arg); 171 170 default: 172 - up(&session->mutex); 171 + mutex_unlock(&session->mutex); 173 172 return -ENOIOCTLCMD; 174 173 } 175 174 } ··· 181 180 .read = vmcp_read, 182 181 .write = vmcp_write, 183 182 .unlocked_ioctl = vmcp_ioctl, 184 - .compat_ioctl = vmcp_ioctl 183 + .compat_ioctl = vmcp_ioctl, 185 184 }; 186 185 187 186 static struct miscdevice vmcp_dev = { ··· 195 194 int ret; 196 195 197 196 if (!MACHINE_IS_VM) { 198 - printk(KERN_WARNING 199 - "z/VM CP interface is only available under z/VM\n"); 197 + PRINT_WARN("z/VM CP interface is only available under z/VM\n"); 200 198 return -ENODEV; 201 199 } 202 - ret = misc_register(&vmcp_dev); 203 - if (!ret) 204 - printk(KERN_INFO "z/VM CP interface loaded\n"); 205 - else 206 - printk(KERN_WARNING 207 - "z/VM CP interface not loaded. Could not register misc device.\n"); 208 200 vmcp_debug = debug_register("vmcp", 1, 1, 240); 209 - debug_register_view(vmcp_debug, &debug_hex_ascii_view); 210 - return ret; 201 + if (!vmcp_debug) { 202 + PRINT_ERR("z/VM CP interface not loaded. Could not register " 203 + "debug feature\n"); 204 + return -ENOMEM; 205 + } 206 + ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view); 207 + if (ret) { 208 + PRINT_ERR("z/VM CP interface not loaded. Could not register " 209 + "debug feature view. Error code: %d\n", ret); 210 + debug_unregister(vmcp_debug); 211 + return ret; 212 + } 213 + ret = misc_register(&vmcp_dev); 214 + if (ret) { 215 + PRINT_ERR("z/VM CP interface not loaded. Could not register " 216 + "misc device. Error code: %d\n", ret); 217 + debug_unregister(vmcp_debug); 218 + return ret; 219 + } 220 + PRINT_INFO("z/VM CP interface loaded\n"); 221 + return 0; 211 222 } 212 223 213 224 static void __exit vmcp_exit(void) 214 225 { 215 - WARN_ON(misc_deregister(&vmcp_dev) != 0); 226 + misc_deregister(&vmcp_dev); 216 227 debug_unregister(vmcp_debug); 217 - printk(KERN_INFO "z/VM CP interface unloaded.\n"); 228 + PRINT_INFO("z/VM CP interface unloaded.\n"); 218 229 } 219 230 220 231 module_init(vmcp_init);
+2 -2
drivers/s390/char/vmcp.h
··· 12 12 * The idea of this driver is based on cpint from Neale Ferguson 13 13 */ 14 14 15 - #include <asm/semaphore.h> 16 15 #include <linux/ioctl.h> 16 + #include <linux/mutex.h> 17 17 18 18 #define VMCP_GETCODE _IOR(0x10, 1, int) 19 19 #define VMCP_SETBUF _IOW(0x10, 2, int) ··· 26 26 int resp_code; 27 27 /* As we use copy_from/to_user, which might * 28 28 * sleep and cannot use a spinlock */ 29 - struct semaphore mutex; 29 + struct mutex mutex; 30 30 };
+906
drivers/s390/char/vmur.c
··· 1 + /* 2 + * Linux driver for System z and s390 unit record devices 3 + * (z/VM virtual punch, reader, printer) 4 + * 5 + * Copyright IBM Corp. 2001, 2007 6 + * Authors: Malcolm Beattie <beattiem@uk.ibm.com> 7 + * Michael Holzheu <holzheu@de.ibm.com> 8 + * Frank Munzert <munzert@de.ibm.com> 9 + */ 10 + 11 + #include <linux/cdev.h> 12 + 13 + #include <asm/uaccess.h> 14 + #include <asm/cio.h> 15 + #include <asm/ccwdev.h> 16 + #include <asm/debug.h> 17 + 18 + #include "vmur.h" 19 + 20 + /* 21 + * Driver overview 22 + * 23 + * Unit record device support is implemented as a character device driver. 24 + * We can fit at least 16 bits into a device minor number and use the 25 + * simple method of mapping a character device number with minor abcd 26 + * to the unit record device with devno abcd. 27 + * I/O to virtual unit record devices is handled as follows: 28 + * Reads: Diagnose code 0x14 (input spool file manipulation) 29 + * is used to read spool data page-wise. 30 + * Writes: The CCW used is WRITE_CCW_CMD (0x01). The device's record length 31 + * is available by reading sysfs attr reclen. Each write() to the device 32 + * must specify an integral multiple (maximal 511) of reclen. 33 + */ 34 + 35 + static char ur_banner[] = "z/VM virtual unit record device driver"; 36 + 37 + MODULE_AUTHOR("IBM Corporation"); 38 + MODULE_DESCRIPTION("s390 z/VM virtual unit record device driver"); 39 + MODULE_LICENSE("GPL"); 40 + 41 + #define PRINTK_HEADER "vmur: " 42 + 43 + static dev_t ur_first_dev_maj_min; 44 + static struct class *vmur_class; 45 + static struct debug_info *vmur_dbf; 46 + 47 + /* We put the device's record length (for writes) in the driver_info field */ 48 + static struct ccw_device_id ur_ids[] = { 49 + { CCWDEV_CU_DI(READER_PUNCH_DEVTYPE, 80) }, 50 + { CCWDEV_CU_DI(PRINTER_DEVTYPE, 132) }, 51 + { /* end of list */ } 52 + }; 53 + 54 + MODULE_DEVICE_TABLE(ccw, ur_ids); 55 + 56 + static int ur_probe(struct ccw_device *cdev); 57 + static void ur_remove(struct ccw_device *cdev); 58 + static int ur_set_online(struct ccw_device *cdev); 59 + static int ur_set_offline(struct ccw_device *cdev); 60 + 61 + static struct ccw_driver ur_driver = { 62 + .name = "vmur", 63 + .owner = THIS_MODULE, 64 + .ids = ur_ids, 65 + .probe = ur_probe, 66 + .remove = ur_remove, 67 + .set_online = ur_set_online, 68 + .set_offline = ur_set_offline, 69 + }; 70 + 71 + /* 72 + * Allocation, freeing, getting and putting of urdev structures 73 + */ 74 + static struct urdev *urdev_alloc(struct ccw_device *cdev) 75 + { 76 + struct urdev *urd; 77 + 78 + urd = kzalloc(sizeof(struct urdev), GFP_KERNEL); 79 + if (!urd) 80 + return NULL; 81 + urd->cdev = cdev; 82 + urd->reclen = cdev->id.driver_info; 83 + ccw_device_get_id(cdev, &urd->dev_id); 84 + mutex_init(&urd->io_mutex); 85 + mutex_init(&urd->open_mutex); 86 + return urd; 87 + } 88 + 89 + static void urdev_free(struct urdev *urd) 90 + { 91 + kfree(urd); 92 + } 93 + 94 + /* 95 + * This is how the character device driver gets a reference to a 96 + * ur device. When this call returns successfully, a reference has 97 + * been taken (by get_device) on the underlying kobject. The recipient 98 + * of this urdev pointer must eventually drop it with urdev_put(urd) 99 + * which does the corresponding put_device(). 100 + */ 101 + static struct urdev *urdev_get_from_devno(u16 devno) 102 + { 103 + char bus_id[16]; 104 + struct ccw_device *cdev; 105 + 106 + sprintf(bus_id, "0.0.%04x", devno); 107 + cdev = get_ccwdev_by_busid(&ur_driver, bus_id); 108 + if (!cdev) 109 + return NULL; 110 + 111 + return cdev->dev.driver_data; 112 + } 113 + 114 + static void urdev_put(struct urdev *urd) 115 + { 116 + put_device(&urd->cdev->dev); 117 + } 118 + 119 + /* 120 + * Low-level functions to do I/O to a ur device. 121 + * alloc_chan_prog 122 + * do_ur_io 123 + * ur_int_handler 124 + * 125 + * alloc_chan_prog allocates and builds the channel program 126 + * 127 + * do_ur_io issues the channel program to the device and blocks waiting 128 + * on a completion event it publishes at urd->io_done. The function 129 + * serialises itself on the device's mutex so that only one I/O 130 + * is issued at a time (and that I/O is synchronous). 131 + * 132 + * ur_int_handler catches the "I/O done" interrupt, writes the 133 + * subchannel status word into the scsw member of the urdev structure 134 + * and complete()s the io_done to wake the waiting do_ur_io. 135 + * 136 + * The caller of do_ur_io is responsible for kfree()ing the channel program 137 + * address pointer that alloc_chan_prog returned. 138 + */ 139 + 140 + 141 + /* 142 + * alloc_chan_prog 143 + * The channel program we use is write commands chained together 144 + * with a final NOP CCW command-chained on (which ensures that CE and DE 145 + * are presented together in a single interrupt instead of as separate 146 + * interrupts unless an incorrect length indication kicks in first). The 147 + * data length in each CCW is reclen. The caller must ensure that count 148 + * is an integral multiple of reclen. 149 + * The channel program pointer returned by this function must be freed 150 + * with kfree. The caller is responsible for checking that 151 + * count/reclen is not ridiculously large. 152 + */ 153 + static struct ccw1 *alloc_chan_prog(char *buf, size_t count, size_t reclen) 154 + { 155 + size_t num_ccws; 156 + struct ccw1 *cpa; 157 + int i; 158 + 159 + TRACE("alloc_chan_prog(%p, %zu, %zu)\n", buf, count, reclen); 160 + 161 + /* 162 + * We chain a NOP onto the writes to force CE+DE together. 163 + * That means we allocate room for CCWs to cover count/reclen 164 + * records plus a NOP. 165 + */ 166 + num_ccws = count / reclen + 1; 167 + cpa = kmalloc(num_ccws * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); 168 + if (!cpa) 169 + return NULL; 170 + 171 + for (i = 0; count; i++) { 172 + cpa[i].cmd_code = WRITE_CCW_CMD; 173 + cpa[i].flags = CCW_FLAG_CC | CCW_FLAG_SLI; 174 + cpa[i].count = reclen; 175 + cpa[i].cda = __pa(buf); 176 + buf += reclen; 177 + count -= reclen; 178 + } 179 + /* The following NOP CCW forces CE+DE to be presented together */ 180 + cpa[i].cmd_code = CCW_CMD_NOOP; 181 + cpa[i].flags = 0; 182 + cpa[i].count = 0; 183 + cpa[i].cda = 0; 184 + 185 + return cpa; 186 + } 187 + 188 + static int do_ur_io(struct urdev *urd, struct ccw1 *cpa) 189 + { 190 + int rc; 191 + struct ccw_device *cdev = urd->cdev; 192 + DECLARE_COMPLETION(event); 193 + 194 + TRACE("do_ur_io: cpa=%p\n", cpa); 195 + 196 + rc = mutex_lock_interruptible(&urd->io_mutex); 197 + if (rc) 198 + return rc; 199 + 200 + urd->io_done = &event; 201 + 202 + spin_lock_irq(get_ccwdev_lock(cdev)); 203 + rc = ccw_device_start(cdev, cpa, 1, 0, 0); 204 + spin_unlock_irq(get_ccwdev_lock(cdev)); 205 + 206 + TRACE("do_ur_io: ccw_device_start returned %d\n", rc); 207 + if (rc) 208 + goto out; 209 + 210 + wait_for_completion(&event); 211 + TRACE("do_ur_io: I/O complete\n"); 212 + rc = 0; 213 + 214 + out: 215 + mutex_unlock(&urd->io_mutex); 216 + return rc; 217 + } 218 + 219 + /* 220 + * ur interrupt handler, called from the ccw_device layer 221 + */ 222 + static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm, 223 + struct irb *irb) 224 + { 225 + struct urdev *urd; 226 + 227 + TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n", 228 + intparm, irb->scsw.cstat, irb->scsw.dstat, irb->scsw.count); 229 + 230 + if (!intparm) { 231 + TRACE("ur_int_handler: unsolicited interrupt\n"); 232 + return; 233 + } 234 + urd = cdev->dev.driver_data; 235 + /* On special conditions irb is an error pointer */ 236 + if (IS_ERR(irb)) 237 + urd->io_request_rc = PTR_ERR(irb); 238 + else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) 239 + urd->io_request_rc = 0; 240 + else 241 + urd->io_request_rc = -EIO; 242 + 243 + complete(urd->io_done); 244 + } 245 + 246 + /* 247 + * reclen sysfs attribute - The record length to be used for write CCWs 248 + */ 249 + static ssize_t ur_attr_reclen_show(struct device *dev, 250 + struct device_attribute *attr, char *buf) 251 + { 252 + struct urdev *urd = dev->driver_data; 253 + 254 + return sprintf(buf, "%zu\n", urd->reclen); 255 + } 256 + 257 + static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL); 258 + 259 + static int ur_create_attributes(struct device *dev) 260 + { 261 + return device_create_file(dev, &dev_attr_reclen); 262 + } 263 + 264 + static void ur_remove_attributes(struct device *dev) 265 + { 266 + device_remove_file(dev, &dev_attr_reclen); 267 + } 268 + 269 + /* 270 + * diagnose code 0x210 - retrieve device information 271 + * cc=0 normal completion, we have a real device 272 + * cc=1 CP paging error 273 + * cc=2 The virtual device exists, but is not associated with a real device 274 + * cc=3 Invalid device address, or the virtual device does not exist 275 + */ 276 + static int get_urd_class(struct urdev *urd) 277 + { 278 + static struct diag210 ur_diag210; 279 + int cc; 280 + 281 + ur_diag210.vrdcdvno = urd->dev_id.devno; 282 + ur_diag210.vrdclen = sizeof(struct diag210); 283 + 284 + cc = diag210(&ur_diag210); 285 + switch (cc) { 286 + case 0: 287 + return -ENOTSUPP; 288 + case 2: 289 + return ur_diag210.vrdcvcla; /* virtual device class */ 290 + case 3: 291 + return -ENODEV; 292 + default: 293 + return -EIO; 294 + } 295 + } 296 + 297 + /* 298 + * Allocation and freeing of urfile structures 299 + */ 300 + static struct urfile *urfile_alloc(struct urdev *urd) 301 + { 302 + struct urfile *urf; 303 + 304 + urf = kzalloc(sizeof(struct urfile), GFP_KERNEL); 305 + if (!urf) 306 + return NULL; 307 + urf->urd = urd; 308 + 309 + TRACE("urfile_alloc: urd=%p urf=%p rl=%zu\n", urd, urf, 310 + urf->dev_reclen); 311 + 312 + return urf; 313 + } 314 + 315 + static void urfile_free(struct urfile *urf) 316 + { 317 + TRACE("urfile_free: urf=%p urd=%p\n", urf, urf->urd); 318 + kfree(urf); 319 + } 320 + 321 + /* 322 + * The fops implementation of the character device driver 323 + */ 324 + static ssize_t do_write(struct urdev *urd, const char __user *udata, 325 + size_t count, size_t reclen, loff_t *ppos) 326 + { 327 + struct ccw1 *cpa; 328 + char *buf; 329 + int rc; 330 + 331 + /* Data buffer must be under 2GB line for fmt1 CCWs: hence GFP_DMA */ 332 + buf = kmalloc(count, GFP_KERNEL | GFP_DMA); 333 + if (!buf) 334 + return -ENOMEM; 335 + 336 + if (copy_from_user(buf, udata, count)) { 337 + rc = -EFAULT; 338 + goto fail_kfree_buf; 339 + } 340 + 341 + cpa = alloc_chan_prog(buf, count, reclen); 342 + if (!cpa) { 343 + rc = -ENOMEM; 344 + goto fail_kfree_buf; 345 + } 346 + 347 + rc = do_ur_io(urd, cpa); 348 + if (rc) 349 + goto fail_kfree_cpa; 350 + 351 + if (urd->io_request_rc) { 352 + rc = urd->io_request_rc; 353 + goto fail_kfree_cpa; 354 + } 355 + *ppos += count; 356 + rc = count; 357 + fail_kfree_cpa: 358 + kfree(cpa); 359 + fail_kfree_buf: 360 + kfree(buf); 361 + return rc; 362 + } 363 + 364 + static ssize_t ur_write(struct file *file, const char __user *udata, 365 + size_t count, loff_t *ppos) 366 + { 367 + struct urfile *urf = file->private_data; 368 + 369 + TRACE("ur_write: count=%zu\n", count); 370 + 371 + if (count == 0) 372 + return 0; 373 + 374 + if (count % urf->dev_reclen) 375 + return -EINVAL; /* count must be a multiple of reclen */ 376 + 377 + if (count > urf->dev_reclen * MAX_RECS_PER_IO) 378 + count = urf->dev_reclen * MAX_RECS_PER_IO; 379 + 380 + return do_write(urf->urd, udata, count, urf->dev_reclen, ppos); 381 + } 382 + 383 + static int do_diag_14(unsigned long rx, unsigned long ry1, 384 + unsigned long subcode) 385 + { 386 + register unsigned long _ry1 asm("2") = ry1; 387 + register unsigned long _ry2 asm("3") = subcode; 388 + int rc = 0; 389 + 390 + asm volatile( 391 + #ifdef CONFIG_64BIT 392 + " sam31\n" 393 + " diag %2,2,0x14\n" 394 + " sam64\n" 395 + #else 396 + " diag %2,2,0x14\n" 397 + #endif 398 + " ipm %0\n" 399 + " srl %0,28\n" 400 + : "=d" (rc), "+d" (_ry2) 401 + : "d" (rx), "d" (_ry1) 402 + : "cc"); 403 + 404 + TRACE("diag 14: subcode=0x%lx, cc=%i\n", subcode, rc); 405 + return rc; 406 + } 407 + 408 + /* 409 + * diagnose code 0x14 subcode 0x0028 - position spool file to designated 410 + * record 411 + * cc=0 normal completion 412 + * cc=2 no file active on the virtual reader or device not ready 413 + * cc=3 record specified is beyond EOF 414 + */ 415 + static int diag_position_to_record(int devno, int record) 416 + { 417 + int cc; 418 + 419 + cc = do_diag_14(record, devno, 0x28); 420 + switch (cc) { 421 + case 0: 422 + return 0; 423 + case 2: 424 + return -ENOMEDIUM; 425 + case 3: 426 + return -ENODATA; /* position beyond end of file */ 427 + default: 428 + return -EIO; 429 + } 430 + } 431 + 432 + /* 433 + * diagnose code 0x14 subcode 0x0000 - read next spool file buffer 434 + * cc=0 normal completion 435 + * cc=1 EOF reached 436 + * cc=2 no file active on the virtual reader, and no file eligible 437 + * cc=3 file already active on the virtual reader or specified virtual 438 + * reader does not exist or is not a reader 439 + */ 440 + static int diag_read_file(int devno, char *buf) 441 + { 442 + int cc; 443 + 444 + cc = do_diag_14((unsigned long) buf, devno, 0x00); 445 + switch (cc) { 446 + case 0: 447 + return 0; 448 + case 1: 449 + return -ENODATA; 450 + case 2: 451 + return -ENOMEDIUM; 452 + default: 453 + return -EIO; 454 + } 455 + } 456 + 457 + static ssize_t diag14_read(struct file *file, char __user *ubuf, size_t count, 458 + loff_t *offs) 459 + { 460 + size_t len, copied, res; 461 + char *buf; 462 + int rc; 463 + u16 reclen; 464 + struct urdev *urd; 465 + 466 + urd = ((struct urfile *) file->private_data)->urd; 467 + reclen = ((struct urfile *) file->private_data)->file_reclen; 468 + 469 + rc = diag_position_to_record(urd->dev_id.devno, *offs / PAGE_SIZE + 1); 470 + if (rc == -ENODATA) 471 + return 0; 472 + if (rc) 473 + return rc; 474 + 475 + len = min((size_t) PAGE_SIZE, count); 476 + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 477 + if (!buf) 478 + return -ENOMEM; 479 + 480 + copied = 0; 481 + res = (size_t) (*offs % PAGE_SIZE); 482 + do { 483 + rc = diag_read_file(urd->dev_id.devno, buf); 484 + if (rc == -ENODATA) { 485 + break; 486 + } 487 + if (rc) 488 + goto fail; 489 + if (reclen) 490 + *((u16 *) &buf[FILE_RECLEN_OFFSET]) = reclen; 491 + len = min(count - copied, PAGE_SIZE - res); 492 + if (copy_to_user(ubuf + copied, buf + res, len)) { 493 + rc = -EFAULT; 494 + goto fail; 495 + } 496 + res = 0; 497 + copied += len; 498 + } while (copied != count); 499 + 500 + *offs += copied; 501 + rc = copied; 502 + fail: 503 + kfree(buf); 504 + return rc; 505 + } 506 + 507 + static ssize_t ur_read(struct file *file, char __user *ubuf, size_t count, 508 + loff_t *offs) 509 + { 510 + struct urdev *urd; 511 + int rc; 512 + 513 + TRACE("ur_read: count=%zu ppos=%li\n", count, (unsigned long) *offs); 514 + 515 + if (count == 0) 516 + return 0; 517 + 518 + urd = ((struct urfile *) file->private_data)->urd; 519 + rc = mutex_lock_interruptible(&urd->io_mutex); 520 + if (rc) 521 + return rc; 522 + rc = diag14_read(file, ubuf, count, offs); 523 + mutex_unlock(&urd->io_mutex); 524 + return rc; 525 + } 526 + 527 + /* 528 + * diagnose code 0x14 subcode 0x0fff - retrieve next file descriptor 529 + * cc=0 normal completion 530 + * cc=1 no files on reader queue or no subsequent file 531 + * cc=2 spid specified is invalid 532 + */ 533 + static int diag_read_next_file_info(struct file_control_block *buf, int spid) 534 + { 535 + int cc; 536 + 537 + cc = do_diag_14((unsigned long) buf, spid, 0xfff); 538 + switch (cc) { 539 + case 0: 540 + return 0; 541 + default: 542 + return -ENODATA; 543 + } 544 + } 545 + 546 + static int verify_device(struct urdev *urd) 547 + { 548 + struct file_control_block fcb; 549 + char *buf; 550 + int rc; 551 + 552 + switch (urd->class) { 553 + case DEV_CLASS_UR_O: 554 + return 0; /* no check needed here */ 555 + case DEV_CLASS_UR_I: 556 + /* check for empty reader device (beginning of chain) */ 557 + rc = diag_read_next_file_info(&fcb, 0); 558 + if (rc) 559 + return rc; 560 + 561 + /* open file on virtual reader */ 562 + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 563 + if (!buf) 564 + return -ENOMEM; 565 + rc = diag_read_file(urd->dev_id.devno, buf); 566 + kfree(buf); 567 + 568 + if ((rc != 0) && (rc != -ENODATA)) /* EOF does not hurt */ 569 + return rc; 570 + return 0; 571 + default: 572 + return -ENOTSUPP; 573 + } 574 + } 575 + 576 + static int get_file_reclen(struct urdev *urd) 577 + { 578 + struct file_control_block fcb; 579 + int rc; 580 + 581 + switch (urd->class) { 582 + case DEV_CLASS_UR_O: 583 + return 0; 584 + case DEV_CLASS_UR_I: 585 + rc = diag_read_next_file_info(&fcb, 0); 586 + if (rc) 587 + return rc; 588 + break; 589 + default: 590 + return -ENOTSUPP; 591 + } 592 + if (fcb.file_stat & FLG_CP_DUMP) 593 + return 0; 594 + 595 + return fcb.rec_len; 596 + } 597 + 598 + static int ur_open(struct inode *inode, struct file *file) 599 + { 600 + u16 devno; 601 + struct urdev *urd; 602 + struct urfile *urf; 603 + unsigned short accmode; 604 + int rc; 605 + 606 + accmode = file->f_flags & O_ACCMODE; 607 + 608 + if (accmode == O_RDWR) 609 + return -EACCES; 610 + 611 + /* 612 + * We treat the minor number as the devno of the ur device 613 + * to find in the driver tree. 614 + */ 615 + devno = MINOR(file->f_dentry->d_inode->i_rdev); 616 + 617 + urd = urdev_get_from_devno(devno); 618 + if (!urd) 619 + return -ENXIO; 620 + 621 + if (file->f_flags & O_NONBLOCK) { 622 + if (!mutex_trylock(&urd->open_mutex)) { 623 + rc = -EBUSY; 624 + goto fail_put; 625 + } 626 + } else { 627 + if (mutex_lock_interruptible(&urd->open_mutex)) { 628 + rc = -ERESTARTSYS; 629 + goto fail_put; 630 + } 631 + } 632 + 633 + TRACE("ur_open\n"); 634 + 635 + if (((accmode == O_RDONLY) && (urd->class != DEV_CLASS_UR_I)) || 636 + ((accmode == O_WRONLY) && (urd->class != DEV_CLASS_UR_O))) { 637 + TRACE("ur_open: unsupported dev class (%d)\n", urd->class); 638 + rc = -EACCES; 639 + goto fail_unlock; 640 + } 641 + 642 + rc = verify_device(urd); 643 + if (rc) 644 + goto fail_unlock; 645 + 646 + urf = urfile_alloc(urd); 647 + if (!urf) { 648 + rc = -ENOMEM; 649 + goto fail_unlock; 650 + } 651 + 652 + urf->dev_reclen = urd->reclen; 653 + rc = get_file_reclen(urd); 654 + if (rc < 0) 655 + goto fail_urfile_free; 656 + urf->file_reclen = rc; 657 + file->private_data = urf; 658 + return 0; 659 + 660 + fail_urfile_free: 661 + urfile_free(urf); 662 + fail_unlock: 663 + mutex_unlock(&urd->open_mutex); 664 + fail_put: 665 + urdev_put(urd); 666 + return rc; 667 + } 668 + 669 + static int ur_release(struct inode *inode, struct file *file) 670 + { 671 + struct urfile *urf = file->private_data; 672 + 673 + TRACE("ur_release\n"); 674 + mutex_unlock(&urf->urd->open_mutex); 675 + urdev_put(urf->urd); 676 + urfile_free(urf); 677 + return 0; 678 + } 679 + 680 + static loff_t ur_llseek(struct file *file, loff_t offset, int whence) 681 + { 682 + loff_t newpos; 683 + 684 + if ((file->f_flags & O_ACCMODE) != O_RDONLY) 685 + return -ESPIPE; /* seek allowed only for reader */ 686 + if (offset % PAGE_SIZE) 687 + return -ESPIPE; /* only multiples of 4K allowed */ 688 + switch (whence) { 689 + case 0: /* SEEK_SET */ 690 + newpos = offset; 691 + break; 692 + case 1: /* SEEK_CUR */ 693 + newpos = file->f_pos + offset; 694 + break; 695 + default: 696 + return -EINVAL; 697 + } 698 + file->f_pos = newpos; 699 + return newpos; 700 + } 701 + 702 + static struct file_operations ur_fops = { 703 + .owner = THIS_MODULE, 704 + .open = ur_open, 705 + .release = ur_release, 706 + .read = ur_read, 707 + .write = ur_write, 708 + .llseek = ur_llseek, 709 + }; 710 + 711 + /* 712 + * ccw_device infrastructure: 713 + * ur_probe gets its own ref to the device (i.e. get_device), 714 + * creates the struct urdev, the device attributes, sets up 715 + * the interrupt handler and validates the virtual unit record device. 716 + * ur_remove removes the device attributes, frees the struct urdev 717 + * and drops (put_device) the ref to the device we got in ur_probe. 718 + */ 719 + static int ur_probe(struct ccw_device *cdev) 720 + { 721 + struct urdev *urd; 722 + int rc; 723 + 724 + TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private); 725 + 726 + if (!get_device(&cdev->dev)) 727 + return -ENODEV; 728 + 729 + urd = urdev_alloc(cdev); 730 + if (!urd) { 731 + rc = -ENOMEM; 732 + goto fail; 733 + } 734 + rc = ur_create_attributes(&cdev->dev); 735 + if (rc) { 736 + rc = -ENOMEM; 737 + goto fail; 738 + } 739 + cdev->dev.driver_data = urd; 740 + cdev->handler = ur_int_handler; 741 + 742 + /* validate virtual unit record device */ 743 + urd->class = get_urd_class(urd); 744 + if (urd->class < 0) { 745 + rc = urd->class; 746 + goto fail; 747 + } 748 + if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { 749 + rc = -ENOTSUPP; 750 + goto fail; 751 + } 752 + 753 + return 0; 754 + 755 + fail: 756 + urdev_free(urd); 757 + put_device(&cdev->dev); 758 + return rc; 759 + } 760 + 761 + static void ur_remove(struct ccw_device *cdev) 762 + { 763 + struct urdev *urd = cdev->dev.driver_data; 764 + 765 + TRACE("ur_remove\n"); 766 + if (cdev->online) 767 + ur_set_offline(cdev); 768 + ur_remove_attributes(&cdev->dev); 769 + urdev_free(urd); 770 + put_device(&cdev->dev); 771 + } 772 + 773 + static int ur_set_online(struct ccw_device *cdev) 774 + { 775 + struct urdev *urd; 776 + int minor, major, rc; 777 + char node_id[16]; 778 + 779 + TRACE("ur_set_online: cdev=%p state=%d\n", cdev, 780 + *(int *) cdev->private); 781 + 782 + if (!try_module_get(ur_driver.owner)) 783 + return -EINVAL; 784 + 785 + urd = (struct urdev *) cdev->dev.driver_data; 786 + minor = urd->dev_id.devno; 787 + major = MAJOR(ur_first_dev_maj_min); 788 + 789 + urd->char_device = cdev_alloc(); 790 + if (!urd->char_device) { 791 + rc = -ENOMEM; 792 + goto fail_module_put; 793 + } 794 + 795 + cdev_init(urd->char_device, &ur_fops); 796 + urd->char_device->dev = MKDEV(major, minor); 797 + urd->char_device->owner = ur_fops.owner; 798 + 799 + rc = cdev_add(urd->char_device, urd->char_device->dev, 1); 800 + if (rc) 801 + goto fail_free_cdev; 802 + if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) { 803 + if (urd->class == DEV_CLASS_UR_I) 804 + sprintf(node_id, "vmrdr-%s", cdev->dev.bus_id); 805 + if (urd->class == DEV_CLASS_UR_O) 806 + sprintf(node_id, "vmpun-%s", cdev->dev.bus_id); 807 + } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) { 808 + sprintf(node_id, "vmprt-%s", cdev->dev.bus_id); 809 + } else { 810 + rc = -ENOTSUPP; 811 + goto fail_free_cdev; 812 + } 813 + 814 + urd->device = device_create(vmur_class, NULL, urd->char_device->dev, 815 + "%s", node_id); 816 + if (IS_ERR(urd->device)) { 817 + rc = PTR_ERR(urd->device); 818 + TRACE("ur_set_online: device_create rc=%d\n", rc); 819 + goto fail_free_cdev; 820 + } 821 + 822 + return 0; 823 + 824 + fail_free_cdev: 825 + cdev_del(urd->char_device); 826 + fail_module_put: 827 + module_put(ur_driver.owner); 828 + 829 + return rc; 830 + } 831 + 832 + static int ur_set_offline(struct ccw_device *cdev) 833 + { 834 + struct urdev *urd; 835 + 836 + TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n", 837 + cdev, cdev->private, *(int *) cdev->private); 838 + urd = (struct urdev *) cdev->dev.driver_data; 839 + device_destroy(vmur_class, urd->char_device->dev); 840 + cdev_del(urd->char_device); 841 + module_put(ur_driver.owner); 842 + 843 + return 0; 844 + } 845 + 846 + /* 847 + * Module initialisation and cleanup 848 + */ 849 + static int __init ur_init(void) 850 + { 851 + int rc; 852 + dev_t dev; 853 + 854 + if (!MACHINE_IS_VM) { 855 + PRINT_ERR("%s is only available under z/VM.\n", ur_banner); 856 + return -ENODEV; 857 + } 858 + 859 + vmur_dbf = debug_register("vmur", 4, 1, 4 * sizeof(long)); 860 + if (!vmur_dbf) 861 + return -ENOMEM; 862 + rc = debug_register_view(vmur_dbf, &debug_sprintf_view); 863 + if (rc) 864 + goto fail_free_dbf; 865 + 866 + debug_set_level(vmur_dbf, 6); 867 + 868 + rc = ccw_driver_register(&ur_driver); 869 + if (rc) 870 + goto fail_free_dbf; 871 + 872 + rc = alloc_chrdev_region(&dev, 0, NUM_MINORS, "vmur"); 873 + if (rc) { 874 + PRINT_ERR("alloc_chrdev_region failed: err = %d\n", rc); 875 + goto fail_unregister_driver; 876 + } 877 + ur_first_dev_maj_min = MKDEV(MAJOR(dev), 0); 878 + 879 + vmur_class = class_create(THIS_MODULE, "vmur"); 880 + if (IS_ERR(vmur_class)) { 881 + rc = PTR_ERR(vmur_class); 882 + goto fail_unregister_region; 883 + } 884 + PRINT_INFO("%s loaded.\n", ur_banner); 885 + return 0; 886 + 887 + fail_unregister_region: 888 + unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS); 889 + fail_unregister_driver: 890 + ccw_driver_unregister(&ur_driver); 891 + fail_free_dbf: 892 + debug_unregister(vmur_dbf); 893 + return rc; 894 + } 895 + 896 + static void __exit ur_exit(void) 897 + { 898 + class_destroy(vmur_class); 899 + unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS); 900 + ccw_driver_unregister(&ur_driver); 901 + debug_unregister(vmur_dbf); 902 + PRINT_INFO("%s unloaded.\n", ur_banner); 903 + } 904 + 905 + module_init(ur_init); 906 + module_exit(ur_exit);
+104
drivers/s390/char/vmur.h
··· 1 + /* 2 + * Linux driver for System z and s390 unit record devices 3 + * (z/VM virtual punch, reader, printer) 4 + * 5 + * Copyright IBM Corp. 2001, 2007 6 + * Authors: Malcolm Beattie <beattiem@uk.ibm.com> 7 + * Michael Holzheu <holzheu@de.ibm.com> 8 + * Frank Munzert <munzert@de.ibm.com> 9 + */ 10 + 11 + #ifndef _VMUR_H_ 12 + #define _VMUR_H_ 13 + 14 + #define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */ 15 + #define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */ 16 + /* 17 + * we only support z/VM's default unit record devices: 18 + * both in SPOOL directory control statement and in CP DEFINE statement 19 + * RDR defaults to 2540 reader 20 + * PUN defaults to 2540 punch 21 + * PRT defaults to 1403 printer 22 + */ 23 + #define READER_PUNCH_DEVTYPE 0x2540 24 + #define PRINTER_DEVTYPE 0x1403 25 + 26 + /* z/VM spool file control block SFBLOK */ 27 + struct file_control_block { 28 + char reserved_1[8]; 29 + char user_owner[8]; 30 + char user_orig[8]; 31 + __s32 data_recs; 32 + __s16 rec_len; 33 + __s16 file_num; 34 + __u8 file_stat; 35 + __u8 dev_type; 36 + char reserved_2[6]; 37 + char file_name[12]; 38 + char file_type[12]; 39 + char create_date[8]; 40 + char create_time[8]; 41 + char reserved_3[6]; 42 + __u8 file_class; 43 + __u8 sfb_lok; 44 + __u64 distr_code; 45 + __u32 reserved_4; 46 + __u8 current_starting_copy_number; 47 + __u8 sfblock_cntrl_flags; 48 + __u8 reserved_5; 49 + __u8 more_status_flags; 50 + char rest[200]; 51 + } __attribute__ ((packed)); 52 + 53 + #define FLG_CP_DUMP 0x10 54 + 55 + /* 56 + * A struct urdev is created for each ur device that is made available 57 + * via the ccw_device driver model. 58 + */ 59 + struct urdev { 60 + struct ccw_device *cdev; /* Backpointer to ccw device */ 61 + struct mutex io_mutex; /* Serialises device IO */ 62 + struct mutex open_mutex; /* Serialises access to device */ 63 + struct completion *io_done; /* do_ur_io waits; irq completes */ 64 + struct device *device; 65 + struct cdev *char_device; 66 + struct ccw_dev_id dev_id; /* device id */ 67 + size_t reclen; /* Record length for *write* CCWs */ 68 + int class; /* VM device class */ 69 + int io_request_rc; /* return code from I/O request */ 70 + }; 71 + 72 + /* 73 + * A struct urfile is allocated at open() time for each device and 74 + * freed on release(). 75 + */ 76 + struct urfile { 77 + struct urdev *urd; 78 + unsigned int flags; 79 + size_t dev_reclen; 80 + __u16 file_reclen; 81 + }; 82 + 83 + /* 84 + * Device major/minor definitions. 85 + */ 86 + 87 + #define UR_MAJOR 0 /* get dynamic major */ 88 + /* 89 + * We map minor numbers directly to device numbers (0-FFFF) for simplicity. 90 + * This avoids having to allocate (and manage) slot numbers. 91 + */ 92 + #define NUM_MINORS 65536 93 + 94 + /* Limiting each I/O to 511 records limits chan prog to 4KB (511 r/w + 1 NOP) */ 95 + #define MAX_RECS_PER_IO 511 96 + #define WRITE_CCW_CMD 0x01 97 + 98 + #define TRACE(x...) debug_sprintf_event(vmur_dbf, 1, x) 99 + #define CCWDEV_CU_DI(cutype, di) \ 100 + CCW_DEVICE(cutype, 0x00), .driver_info = (di) 101 + 102 + #define FILE_RECLEN_OFFSET 4064 /* reclen offset in spool data block */ 103 + 104 + #endif /* _VMUR_H_ */
+1 -1
drivers/s390/cio/device.c
··· 272 272 struct ccw_device_id *id = &(cdev->id); 273 273 int len; 274 274 275 - len = snprint_alias(buf, PAGE_SIZE, id, "\n") + 1; 275 + len = snprint_alias(buf, PAGE_SIZE, id, "\n"); 276 276 277 277 return len > PAGE_SIZE ? PAGE_SIZE : len; 278 278 }
+8 -8
drivers/s390/cio/qdio.c
··· 166 166 { 167 167 char dbf_text[15]; 168 168 169 - if (ccq == 0 || ccq == 32 || ccq == 96) 169 + if (ccq == 0 || ccq == 32) 170 170 return 0; 171 - if (ccq == 97) 171 + if (ccq == 96 || ccq == 97) 172 172 return 1; 173 173 /*notify devices immediately*/ 174 174 sprintf(dbf_text,"%d", ccq); ··· 2306 2306 if (!ssqd_area) { 2307 2307 QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ 2308 2308 "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); 2309 - irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2310 - CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2309 + irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | 2310 + CHSC_FLAG_SIGA_OUTPUT_NECESSARY | 2311 2311 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ 2312 2312 irq_ptr->is_qebsm = 0; 2313 2313 irq_ptr->sch_token = 0; ··· 2328 2328 QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ 2329 2329 "SIGAs for sch 0.%x.%x.\n", result, 2330 2330 irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2331 - qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2332 - CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2331 + qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | 2332 + CHSC_FLAG_SIGA_OUTPUT_NECESSARY | 2333 2333 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ 2334 2334 irq_ptr->is_qebsm = 0; 2335 2335 goto out; ··· 2340 2340 "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n", 2341 2341 ssqd_area->response.code, 2342 2342 irq_ptr->schid.ssid, irq_ptr->schid.sch_no); 2343 - qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || 2344 - CHSC_FLAG_SIGA_OUTPUT_NECESSARY || 2343 + qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | 2344 + CHSC_FLAG_SIGA_OUTPUT_NECESSARY | 2345 2345 CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ 2346 2346 irq_ptr->is_qebsm = 0; 2347 2347 goto out;