Commit 6b979de395c7e1b7e59f74a870e1d1911853eccb

Authored by Christian Borntraeger
Committed by Linus Torvalds
1 parent 77fa22450d

[PATCH] s390: add vmcp interface

Add interface to issue VM control program commands.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 15 changed files with 359 additions and 66 deletions Side-by-side Diff

... ... @@ -245,6 +245,7 @@
245 245 #
246 246 CONFIG_S390_TAPE_34XX=m
247 247 # CONFIG_VMLOGRDR is not set
  248 +# CONFIG_VMCP is not set
248 249 # CONFIG_MONREADER is not set
249 250 # CONFIG_DCSS_SHM is not set
250 251  
arch/s390/kernel/cpcmd.c
... ... @@ -2,7 +2,7 @@
2 2 * arch/s390/kernel/cpcmd.c
3 3 *
4 4 * S390 version
5   - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  5 + * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 7 * Christian Borntraeger (cborntra@de.ibm.com),
8 8 */
9 9  
10 10  
11 11  
12 12  
13 13  
14 14  
15 15  
16 16  
17 17  
18 18  
19 19  
20 20  
21 21  
22 22  
23 23  
... ... @@ -18,93 +18,114 @@
18 18 #include <asm/system.h>
19 19  
20 20 static DEFINE_SPINLOCK(cpcmd_lock);
21   -static char cpcmd_buf[240];
  21 +static char cpcmd_buf[241];
22 22  
23 23 /*
24 24 * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
25 25 */
26   -void __cpcmd(char *cmd, char *response, int rlen)
  26 +int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
27 27 {
28 28 const int mask = 0x40000000L;
29 29 unsigned long flags;
  30 + int return_code;
  31 + int return_len;
30 32 int cmdlen;
31 33  
32 34 spin_lock_irqsave(&cpcmd_lock, flags);
33 35 cmdlen = strlen(cmd);
34 36 BUG_ON(cmdlen > 240);
35   - strcpy(cpcmd_buf, cmd);
  37 + memcpy(cpcmd_buf, cmd, cmdlen);
36 38 ASCEBC(cpcmd_buf, cmdlen);
37 39  
38 40 if (response != NULL && rlen > 0) {
39 41 memset(response, 0, rlen);
40 42 #ifndef CONFIG_ARCH_S390X
41   - asm volatile ("LRA 2,0(%0)\n\t"
42   - "LR 4,%1\n\t"
43   - "O 4,%4\n\t"
44   - "LRA 3,0(%2)\n\t"
45   - "LR 5,%3\n\t"
46   - ".long 0x83240008 # Diagnose X'08'\n\t"
47   - : /* no output */
48   - : "a" (cpcmd_buf), "d" (cmdlen),
49   - "a" (response), "d" (rlen), "m" (mask)
50   - : "cc", "2", "3", "4", "5" );
  43 + asm volatile ( "lra 2,0(%2)\n"
  44 + "lr 4,%3\n"
  45 + "o 4,%6\n"
  46 + "lra 3,0(%4)\n"
  47 + "lr 5,%5\n"
  48 + "diag 2,4,0x8\n"
  49 + "brc 8, .Litfits\n"
  50 + "ar 5, %5\n"
  51 + ".Litfits: \n"
  52 + "lr %0,4\n"
  53 + "lr %1,5\n"
  54 + : "=d" (return_code), "=d" (return_len)
  55 + : "a" (cpcmd_buf), "d" (cmdlen),
  56 + "a" (response), "d" (rlen), "m" (mask)
  57 + : "cc", "2", "3", "4", "5" );
51 58 #else /* CONFIG_ARCH_S390X */
52   - asm volatile (" lrag 2,0(%0)\n"
53   - " lgr 4,%1\n"
54   - " o 4,%4\n"
55   - " lrag 3,0(%2)\n"
56   - " lgr 5,%3\n"
57   - " sam31\n"
58   - " .long 0x83240008 # Diagnose X'08'\n"
59   - " sam64"
60   - : /* no output */
61   - : "a" (cpcmd_buf), "d" (cmdlen),
62   - "a" (response), "d" (rlen), "m" (mask)
63   - : "cc", "2", "3", "4", "5" );
  59 + asm volatile ( "lrag 2,0(%2)\n"
  60 + "lgr 4,%3\n"
  61 + "o 4,%6\n"
  62 + "lrag 3,0(%4)\n"
  63 + "lgr 5,%5\n"
  64 + "sam31\n"
  65 + "diag 2,4,0x8\n"
  66 + "sam64\n"
  67 + "brc 8, .Litfits\n"
  68 + "agr 5, %5\n"
  69 + ".Litfits: \n"
  70 + "lgr %0,4\n"
  71 + "lgr %1,5\n"
  72 + : "=d" (return_code), "=d" (return_len)
  73 + : "a" (cpcmd_buf), "d" (cmdlen),
  74 + "a" (response), "d" (rlen), "m" (mask)
  75 + : "cc", "2", "3", "4", "5" );
64 76 #endif /* CONFIG_ARCH_S390X */
65 77 EBCASC(response, rlen);
66 78 } else {
  79 + return_len = 0;
67 80 #ifndef CONFIG_ARCH_S390X
68   - asm volatile ("LRA 2,0(%0)\n\t"
69   - "LR 3,%1\n\t"
70   - ".long 0x83230008 # Diagnose X'08'\n\t"
71   - : /* no output */
72   - : "a" (cpcmd_buf), "d" (cmdlen)
73   - : "2", "3" );
  81 + asm volatile ( "lra 2,0(%1)\n"
  82 + "lr 3,%2\n"
  83 + "diag 2,3,0x8\n"
  84 + "lr %0,3\n"
  85 + : "=d" (return_code)
  86 + : "a" (cpcmd_buf), "d" (cmdlen)
  87 + : "2", "3" );
74 88 #else /* CONFIG_ARCH_S390X */
75   - asm volatile (" lrag 2,0(%0)\n"
76   - " lgr 3,%1\n"
77   - " sam31\n"
78   - " .long 0x83230008 # Diagnose X'08'\n"
79   - " sam64"
80   - : /* no output */
81   - : "a" (cpcmd_buf), "d" (cmdlen)
82   - : "2", "3" );
  89 + asm volatile ( "lrag 2,0(%1)\n"
  90 + "lgr 3,%2\n"
  91 + "sam31\n"
  92 + "diag 2,3,0x8\n"
  93 + "sam64\n"
  94 + "lgr %0,3\n"
  95 + : "=d" (return_code)
  96 + : "a" (cpcmd_buf), "d" (cmdlen)
  97 + : "2", "3" );
83 98 #endif /* CONFIG_ARCH_S390X */
84 99 }
85 100 spin_unlock_irqrestore(&cpcmd_lock, flags);
  101 + if (response_code != NULL)
  102 + *response_code = return_code;
  103 + return return_len;
86 104 }
87 105  
88 106 EXPORT_SYMBOL(__cpcmd);
89 107  
90 108 #ifdef CONFIG_ARCH_S390X
91   -void cpcmd(char *cmd, char *response, int rlen)
  109 +int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
92 110 {
93 111 char *lowbuf;
  112 + int len;
  113 +
94 114 if ((rlen == 0) || (response == NULL)
95 115 || !((unsigned long)response >> 31))
96   - __cpcmd(cmd, response, rlen);
  116 + len = __cpcmd(cmd, response, rlen, response_code);
97 117 else {
98 118 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
99 119 if (!lowbuf) {
100 120 printk(KERN_WARNING
101 121 "cpcmd: could not allocate response buffer\n");
102   - return;
  122 + return -ENOMEM;
103 123 }
104   - __cpcmd(cmd, lowbuf, rlen);
  124 + len = __cpcmd(cmd, lowbuf, rlen, response_code);
105 125 memcpy(response, lowbuf, rlen);
106 126 kfree(lowbuf);
107 127 }
  128 + return len;
108 129 }
109 130  
110 131 EXPORT_SYMBOL(cpcmd);
arch/s390/kernel/setup.c
... ... @@ -198,11 +198,11 @@
198 198 char *ptr;
199 199  
200 200 if (MACHINE_IS_VM) {
201   - __cpcmd("QUERY CONSOLE", query_buffer, 1024);
  201 + __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
202 202 console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
203 203 ptr = strstr(query_buffer, "SUBCHANNEL =");
204 204 console_irq = simple_strtoul(ptr + 13, NULL, 16);
205   - __cpcmd("QUERY TERM", query_buffer, 1024);
  205 + __cpcmd("QUERY TERM", query_buffer, 1024, NULL);
206 206 ptr = strstr(query_buffer, "CONMODE");
207 207 /*
208 208 * Set the conmode to 3215 so that the device recognition
... ... @@ -211,7 +211,7 @@
211 211 * 3215 and the 3270 driver will try to access the console
212 212 * device (3215 as console and 3270 as normal tty).
213 213 */
214   - __cpcmd("TERM CONMODE 3215", NULL, 0);
  214 + __cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
215 215 if (ptr == NULL) {
216 216 #if defined(CONFIG_SCLP_CONSOLE)
217 217 SET_CONSOLE_SCLP;
arch/s390/kernel/smp.c
... ... @@ -284,7 +284,7 @@
284 284 * locks are always held disabled).
285 285 */
286 286 if (MACHINE_IS_VM)
287   - cpcmd ("IPL", NULL, 0);
  287 + cpcmd ("IPL", NULL, 0, NULL);
288 288 else
289 289 reipl (0x10000 | S390_lowcore.ipl_device);
290 290 }
... ... @@ -313,7 +313,7 @@
313 313 if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
314 314 smp_send_stop();
315 315 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
316   - cpcmd(vmhalt_cmd, NULL, 0);
  316 + cpcmd(vmhalt_cmd, NULL, 0, NULL);
317 317 signal_processor(smp_processor_id(),
318 318 sigp_stop_and_store_status);
319 319 }
... ... @@ -332,7 +332,7 @@
332 332 if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
333 333 smp_send_stop();
334 334 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
335   - cpcmd(vmpoff_cmd, NULL, 0);
  335 + cpcmd(vmpoff_cmd, NULL, 0, NULL);
336 336 signal_processor(smp_processor_id(),
337 337 sigp_stop_and_store_status);
338 338 }
arch/s390/kernel/traps.c
... ... @@ -735,7 +735,7 @@
735 735 &ext_int_pfault);
736 736 #endif
737 737 #ifndef CONFIG_ARCH_S390X
738   - cpcmd("SET PAGEX ON", NULL, 0);
  738 + cpcmd("SET PAGEX ON", NULL, 0, NULL);
739 739 #endif
740 740 }
741 741 }
arch/s390/mm/extmem.c
... ... @@ -576,8 +576,8 @@
576 576 segtype_string[seg->range[i].start & 0xff]);
577 577 }
578 578 sprintf(cmd2, "SAVESEG %s", name);
579   - cpcmd(cmd1, NULL, 0);
580   - cpcmd(cmd2, NULL, 0);
  579 + cpcmd(cmd1, NULL, 0, NULL);
  580 + cpcmd(cmd2, NULL, 0, NULL);
581 581 spin_unlock(&dcss_lock);
582 582 }
583 583  
drivers/s390/Kconfig
... ... @@ -187,6 +187,13 @@
187 187 *SYMPTOM.
188 188 This driver depends on the IUCV support driver.
189 189  
  190 +config VMCP
  191 + tristate "Support for the z/VM CP interface (VM only)"
  192 + help
  193 + Select this option if you want to be able to interact with the control
  194 + program on z/VM
  195 +
  196 +
190 197 config MONREADER
191 198 tristate "API for reading z/VM monitor service records"
192 199 depends on IUCV
drivers/s390/char/Makefile
... ... @@ -19,6 +19,7 @@
19 19  
20 20 obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o
21 21 obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
  22 +obj-$(CONFIG_VMCP) += vmcp.o
22 23  
23 24 tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
24 25 tape-$(CONFIG_PROC_FS) += tape_proc.o
drivers/s390/char/con3215.c
... ... @@ -860,8 +860,8 @@
860 860  
861 861 /* Set the console mode for VM */
862 862 if (MACHINE_IS_VM) {
863   - cpcmd("TERM CONMODE 3215", NULL, 0);
864   - cpcmd("TERM AUTOCR OFF", NULL, 0);
  863 + cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
  864 + cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
865 865 }
866 866  
867 867 /* allocate 3215 request structures */
drivers/s390/char/con3270.c
... ... @@ -591,8 +591,8 @@
591 591  
592 592 /* Set the console mode for VM */
593 593 if (MACHINE_IS_VM) {
594   - cpcmd("TERM CONMODE 3270", 0, 0);
595   - cpcmd("TERM AUTOCR OFF", 0, 0);
  594 + cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
  595 + cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
596 596 }
597 597  
598 598 cdev = ccw_device_probe_console();
drivers/s390/char/vmcp.c
  1 +/*
  2 + * Copyright (C) 2004,2005 IBM Corporation
  3 + * Interface implementation for communication with the v/VM control program
  4 + * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
  5 + *
  6 + *
  7 + * z/VMs CP offers the possibility to issue commands via the diagnose code 8
  8 + * this driver implements a character device that issues these commands and
  9 + * returns the answer of CP.
  10 +
  11 + * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS
  12 + */
  13 +
  14 +#include <linux/fs.h>
  15 +#include <linux/init.h>
  16 +#include <linux/kernel.h>
  17 +#include <linux/miscdevice.h>
  18 +#include <linux/module.h>
  19 +#include <asm/cpcmd.h>
  20 +#include <asm/debug.h>
  21 +#include <asm/uaccess.h>
  22 +#include "vmcp.h"
  23 +
  24 +MODULE_LICENSE("GPL");
  25 +MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
  26 +MODULE_DESCRIPTION("z/VM CP interface");
  27 +
  28 +static debug_info_t *vmcp_debug;
  29 +
  30 +static int vmcp_open(struct inode *inode, struct file *file)
  31 +{
  32 + struct vmcp_session *session;
  33 +
  34 + if (!capable(CAP_SYS_ADMIN))
  35 + return -EPERM;
  36 +
  37 + session = kmalloc(sizeof(*session), GFP_KERNEL);
  38 + if (!session)
  39 + return -ENOMEM;
  40 + session->bufsize = PAGE_SIZE;
  41 + session->response = NULL;
  42 + session->resp_size = 0;
  43 + init_MUTEX(&session->mutex);
  44 + file->private_data = session;
  45 + return nonseekable_open(inode, file);
  46 +}
  47 +
  48 +static int vmcp_release(struct inode *inode, struct file *file)
  49 +{
  50 + struct vmcp_session *session;
  51 +
  52 + session = (struct vmcp_session *)file->private_data;
  53 + file->private_data = NULL;
  54 + free_pages((unsigned long)session->response, get_order(session->bufsize));
  55 + kfree(session);
  56 + return 0;
  57 +}
  58 +
  59 +static ssize_t
  60 +vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
  61 +{
  62 + size_t tocopy;
  63 + struct vmcp_session *session;
  64 +
  65 + session = (struct vmcp_session *)file->private_data;
  66 + if (down_interruptible(&session->mutex))
  67 + return -ERESTARTSYS;
  68 + if (!session->response) {
  69 + up(&session->mutex);
  70 + return 0;
  71 + }
  72 + if (*ppos > session->resp_size) {
  73 + up(&session->mutex);
  74 + return 0;
  75 + }
  76 + tocopy = min(session->resp_size - (size_t) (*ppos), count);
  77 + tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
  78 +
  79 + if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
  80 + up(&session->mutex);
  81 + return -EFAULT;
  82 + }
  83 + up(&session->mutex);
  84 + *ppos += tocopy;
  85 + return tocopy;
  86 +}
  87 +
  88 +static ssize_t
  89 +vmcp_write(struct file *file, const char __user * buff, size_t count,
  90 + loff_t * ppos)
  91 +{
  92 + char *cmd;
  93 + struct vmcp_session *session;
  94 +
  95 + if (count > 240)
  96 + return -EINVAL;
  97 + cmd = kmalloc(count + 1, GFP_KERNEL);
  98 + if (!cmd)
  99 + return -ENOMEM;
  100 + if (copy_from_user(cmd, buff, count)) {
  101 + kfree(cmd);
  102 + return -EFAULT;
  103 + }
  104 + cmd[count] = '\0';
  105 + session = (struct vmcp_session *)file->private_data;
  106 + if (down_interruptible(&session->mutex))
  107 + return -ERESTARTSYS;
  108 + if (!session->response)
  109 + session->response = (char *)__get_free_pages(GFP_KERNEL
  110 + | __GFP_REPEAT | GFP_DMA,
  111 + get_order(session->bufsize));
  112 + if (!session->response) {
  113 + up(&session->mutex);
  114 + kfree(cmd);
  115 + return -ENOMEM;
  116 + }
  117 + debug_text_event(vmcp_debug, 1, cmd);
  118 + session->resp_size = cpcmd(cmd, session->response,
  119 + session->bufsize,
  120 + &session->resp_code);
  121 + up(&session->mutex);
  122 + kfree(cmd);
  123 + *ppos = 0; /* reset the file pointer after a command */
  124 + return count;
  125 +}
  126 +
  127 +
  128 +/*
  129 + * These ioctls are available, as the semantics of the diagnose 8 call
  130 + * does not fit very well into a Linux call. Diagnose X'08' is described in
  131 + * CP Programming Services SC24-6084-00
  132 + *
  133 + * VMCP_GETCODE: gives the CP return code back to user space
  134 + * VMCP_SETBUF: sets the response buffer for the next write call. diagnose 8
  135 + * expects adjacent pages in real storage and to make matters worse, we
  136 + * dont know the size of the response. Therefore we default to PAGESIZE and
  137 + * let userspace to change the response size, if userspace expects a bigger
  138 + * response
  139 + */
  140 +static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  141 +{
  142 + struct vmcp_session *session;
  143 + int temp;
  144 +
  145 + session = (struct vmcp_session *)file->private_data;
  146 + if (down_interruptible(&session->mutex))
  147 + return -ERESTARTSYS;
  148 + switch (cmd) {
  149 + case VMCP_GETCODE:
  150 + temp = session->resp_code;
  151 + up(&session->mutex);
  152 + return put_user(temp, (int __user *)arg);
  153 + case VMCP_SETBUF:
  154 + free_pages((unsigned long)session->response,
  155 + get_order(session->bufsize));
  156 + session->response=NULL;
  157 + temp = get_user(session->bufsize, (int __user *)arg);
  158 + if (get_order(session->bufsize) > 8) {
  159 + session->bufsize = PAGE_SIZE;
  160 + temp = -EINVAL;
  161 + }
  162 + up(&session->mutex);
  163 + return temp;
  164 + case VMCP_GETSIZE:
  165 + temp = session->resp_size;
  166 + up(&session->mutex);
  167 + return put_user(temp, (int __user *)arg);
  168 + default:
  169 + up(&session->mutex);
  170 + return -ENOIOCTLCMD;
  171 + }
  172 +}
  173 +
  174 +static struct file_operations vmcp_fops = {
  175 + .owner = THIS_MODULE,
  176 + .open = &vmcp_open,
  177 + .release = &vmcp_release,
  178 + .read = &vmcp_read,
  179 + .llseek = &no_llseek,
  180 + .write = &vmcp_write,
  181 + .unlocked_ioctl = &vmcp_ioctl,
  182 + .compat_ioctl = &vmcp_ioctl
  183 +};
  184 +
  185 +static struct miscdevice vmcp_dev = {
  186 + .name = "vmcp",
  187 + .minor = MISC_DYNAMIC_MINOR,
  188 + .fops = &vmcp_fops,
  189 +};
  190 +
  191 +static int __init vmcp_init(void)
  192 +{
  193 + int ret;
  194 +
  195 + if (!MACHINE_IS_VM) {
  196 + printk(KERN_WARNING
  197 + "z/VM CP interface is only available under z/VM\n");
  198 + return -ENODEV;
  199 + }
  200 + ret = misc_register(&vmcp_dev);
  201 + if (!ret)
  202 + printk(KERN_INFO "z/VM CP interface loaded\n");
  203 + else
  204 + printk(KERN_WARNING
  205 + "z/VM CP interface not loaded. Could not register misc device.\n");
  206 + vmcp_debug = debug_register("vmcp", 0, 1, 240);
  207 + debug_register_view(vmcp_debug, &debug_hex_ascii_view);
  208 + return ret;
  209 +}
  210 +
  211 +static void __exit vmcp_exit(void)
  212 +{
  213 + WARN_ON(misc_deregister(&vmcp_dev) != 0);
  214 + debug_unregister(vmcp_debug);
  215 + printk(KERN_INFO "z/VM CP interface unloaded.\n");
  216 +}
  217 +
  218 +module_init(vmcp_init);
  219 +module_exit(vmcp_exit);
drivers/s390/char/vmcp.h
  1 +/*
  2 + * Copyright (C) 2004, 2005 IBM Corporation
  3 + * Interface implementation for communication with the v/VM control program
  4 + * Version 1.0
  5 + * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
  6 + *
  7 + *
  8 + * z/VMs CP offers the possibility to issue commands via the diagnose code 8
  9 + * this driver implements a character device that issues these commands and
  10 + * returns the answer of CP.
  11 + *
  12 + * The idea of this driver is based on cpint from Neale Ferguson
  13 + */
  14 +
  15 +#include <asm/semaphore.h>
  16 +#include <linux/ioctl.h>
  17 +
  18 +#define VMCP_GETCODE _IOR(0x10, 1, int)
  19 +#define VMCP_SETBUF _IOW(0x10, 2, int)
  20 +#define VMCP_GETSIZE _IOR(0x10, 3, int)
  21 +
  22 +struct vmcp_session {
  23 + unsigned int bufsize;
  24 + char *response;
  25 + int resp_size;
  26 + int resp_code;
  27 + /* As we use copy_from/to_user, which might *
  28 + * sleep and cannot use a spinlock */
  29 + struct semaphore mutex;
  30 +};
drivers/s390/char/vmlogrdr.c
... ... @@ -236,7 +236,7 @@
236 236 int len,i;
237 237  
238 238 printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
239   - cpcmd(cp_command, cp_response, sizeof(cp_response));
  239 + cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
240 240 printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
241 241 len = strnlen(cp_response,sizeof(cp_response));
242 242 // now the parsing
... ... @@ -288,7 +288,7 @@
288 288  
289 289 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
290 290 cp_command);
291   - cpcmd(cp_command, cp_response, sizeof(cp_response));
  291 + cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
292 292 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
293 293 cp_response);
294 294 }
... ... @@ -301,7 +301,7 @@
301 301 qid_string);
302 302  
303 303 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
304   - cpcmd(cp_command, cp_response, sizeof(cp_response));
  304 + cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
305 305 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
306 306 cp_response);
307 307 /* The recording command will usually answer with 'Command complete'
... ... @@ -607,7 +607,7 @@
607 607 priv->recording_name);
608 608  
609 609 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
610   - cpcmd(cp_command, cp_response, sizeof(cp_response));
  610 + cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
611 611 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
612 612 cp_response);
613 613  
... ... @@ -682,7 +682,7 @@
682 682 char cp_command[] = "QUERY RECORDING ";
683 683 int len;
684 684  
685   - cpcmd(cp_command, buf, 4096);
  685 + cpcmd(cp_command, buf, 4096, NULL);
686 686 len = strlen(buf);
687 687 return len;
688 688 }
drivers/s390/net/smsgiucv.c
... ... @@ -138,7 +138,7 @@
138 138 smsg_exit(void)
139 139 {
140 140 if (smsg_handle > 0) {
141   - cpcmd("SET SMSG OFF", 0, 0);
  141 + cpcmd("SET SMSG OFF", NULL, 0, NULL);
142 142 iucv_sever(smsg_pathid, 0);
143 143 iucv_unregister_program(smsg_handle);
144 144 driver_unregister(&smsg_driver);
... ... @@ -177,7 +177,7 @@
177 177 smsg_handle = 0;
178 178 return -EIO;
179 179 }
180   - cpcmd("SET SMSG IUCV", 0, 0);
  180 + cpcmd("SET SMSG IUCV", NULL, 0, NULL);
181 181 return 0;
182 182 }
183 183  
include/asm-s390/cpcmd.h
... ... @@ -11,14 +11,28 @@
11 11 #define __CPCMD__
12 12  
13 13 /*
  14 + * the lowlevel function for cpcmd
14 15 * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
15 16 */
16   -extern void __cpcmd(char *cmd, char *response, int rlen);
  17 +extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);
17 18  
18 19 #ifndef __s390x__
19 20 #define cpcmd __cpcmd
20 21 #else
21   -extern void cpcmd(char *cmd, char *response, int rlen);
  22 +/*
  23 + * cpcmd is the in-kernel interface for issuing CP commands
  24 + *
  25 + * cmd: null-terminated command string, max 240 characters
  26 + * response: response buffer for VM's textual response
  27 + * rlen: size of the response buffer, cpcmd will not exceed this size
  28 + * but will cap the output, if its too large. Everything that
  29 + * did not fit into the buffer will be silently dropped
  30 + * response_code: return pointer for VM's error code
  31 + * return value: the size of the response. The caller can check if the buffer
  32 + * was large enough by comparing the return value and rlen
  33 + * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
  34 + */
  35 +extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
22 36 #endif /*__s390x__*/
23 37  
24 38 #endif