summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/Kconfig19
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/monwriter.c6
-rw-r--r--drivers/s390/char/raw3270.c7
-rw-r--r--drivers/s390/char/sclp.h12
-rw-r--r--drivers/s390/char/sclp_chp.c4
-rw-r--r--drivers/s390/char/sclp_info.c117
-rw-r--r--drivers/s390/char/sclp_vt220.c62
-rw-r--r--drivers/s390/char/tape.h2
-rw-r--r--drivers/s390/char/tape_34xx.c3
-rw-r--r--drivers/s390/char/tape_block.c4
-rw-r--r--drivers/s390/char/vmcp.c100
-rw-r--r--drivers/s390/char/vmcp.h4
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/zcore.c2
15 files changed, 229 insertions, 118 deletions
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 66102a184322..643033890e34 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -44,15 +44,9 @@ config CCW_CONSOLE
depends on TN3215_CONSOLE || TN3270_CONSOLE
default y
-config SCLP
- bool "Support for SCLP"
- depends on S390
- help
- Include support for the SCLP interface to the service element.
-
config SCLP_TTY
bool "Support for SCLP line mode terminal"
- depends on SCLP
+ depends on S390
help
Include support for IBM SCLP line-mode terminals.
@@ -65,7 +59,7 @@ config SCLP_CONSOLE
config SCLP_VT220_TTY
bool "Support for SCLP VT220-compatible terminal"
- depends on SCLP
+ depends on S390
help
Include support for an IBM SCLP VT220-compatible terminal.
@@ -78,7 +72,7 @@ config SCLP_VT220_CONSOLE
config SCLP_CPI
tristate "Control-Program Identification"
- depends on SCLP
+ depends on S390
help
This option enables the hardware console interface for system
identification. This is commonly used for workload management and
@@ -164,3 +158,10 @@ config MONWRITER
help
Character device driver for writing z/VM monitor service records
+config S390_VMUR
+ tristate "z/VM unit record device driver"
+ depends on S390
+ default "m"
+ help
+ Character device driver for z/VM reader, puncher and printer.
+
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index c210784bdf46..130de19916f2 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o
obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o
obj-$(CONFIG_MONREADER) += monreader.o
obj-$(CONFIG_MONWRITER) += monwriter.o
+obj-$(CONFIG_S390_VMUR) += vmur.o
zcore_mod-objs := sclp_sdias.o zcore.o
obj-$(CONFIG_ZFCPDUMP) += zcore_mod.o
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 268598ef3efe..20442fbf9346 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -17,6 +17,7 @@
#include <linux/miscdevice.h>
#include <linux/ctype.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/ebcdic.h>
#include <asm/io.h>
@@ -41,6 +42,7 @@ struct mon_private {
size_t hdr_to_read;
size_t data_to_read;
struct mon_buf *current_buf;
+ struct mutex thread_mutex;
};
/*
@@ -179,6 +181,7 @@ static int monwrite_open(struct inode *inode, struct file *filp)
return -ENOMEM;
INIT_LIST_HEAD(&monpriv->list);
monpriv->hdr_to_read = sizeof(monpriv->hdr);
+ mutex_init(&monpriv->thread_mutex);
filp->private_data = monpriv;
return nonseekable_open(inode, filp);
}
@@ -209,6 +212,7 @@ static ssize_t monwrite_write(struct file *filp, const char __user *data,
void *to;
int rc;
+ mutex_lock(&monpriv->thread_mutex);
for (written = 0; written < count; ) {
if (monpriv->hdr_to_read) {
len = min(count - written, monpriv->hdr_to_read);
@@ -247,11 +251,13 @@ static ssize_t monwrite_write(struct file *filp, const char __user *data,
}
monpriv->hdr_to_read = sizeof(monpriv->hdr);
}
+ mutex_unlock(&monpriv->thread_mutex);
return written;
out_error:
monpriv->data_to_read = 0;
monpriv->hdr_to_read = sizeof(struct monwrite_hdr);
+ mutex_unlock(&monpriv->thread_mutex);
return rc;
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 743944ad61ec..2edd5fb6d3dc 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -21,6 +21,7 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include <asm/ebcdic.h>
+#include <asm/diag.h>
#include "raw3270.h"
@@ -147,8 +148,7 @@ raw3270_request_alloc(size_t size)
* Allocate a new 3270 ccw request from bootmem. Only works very
* early in the boot process. Only con3270.c should be using this.
*/
-struct raw3270_request *
-raw3270_request_alloc_bootmem(size_t size)
+struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size)
{
struct raw3270_request *rq;
@@ -848,8 +848,7 @@ raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
/*
* Setup 3270 device configured as console.
*/
-struct raw3270 *
-raw3270_setup_console(struct ccw_device *cdev)
+struct raw3270 __init *raw3270_setup_console(struct ccw_device *cdev)
{
struct raw3270 *rp;
char *ascebc;
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f57..c7318a125852 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
+struct sccb_header {
+ u16 length;
+ u8 function_code;
+ u8 control_mask[3];
+ u16 response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
+
struct gds_subvector {
u8 length;
u8 key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914519b5..c68f5e7e63a0 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd)
struct chp_cfg_data *data;
int rc;
+ if (!SCLP_HAS_CHP_RECONFIG)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
@@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info)
struct chp_info_data *data;
int rc;
+ if (!SCLP_HAS_CHP_INFO)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b087..a1136e052750 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
#include <asm/sclp.h>
#include "sclp.h"
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+ struct sccb_header header; /* 0-7 */
+ u16 rnmax; /* 8-9 */
+ u8 rnsize; /* 10 */
+ u8 _reserved0[24 - 11]; /* 11-23 */
+ u8 loadparm[8]; /* 24-31 */
+ u8 _reserved1[48 - 32]; /* 32-47 */
+ u64 facilities; /* 48-55 */
+ u8 _reserved2[91 - 56]; /* 56-90 */
+ u8 flags; /* 91 */
+ u8 _reserved3[100 - 92]; /* 92-99 */
+ u32 rnsize2; /* 100-103 */
+ u64 rnmax2; /* 104-111 */
+ u8 _reserved4[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
void __init sclp_readinfo_early(void)
{
- sclp_cmdw_t command;
- struct sccb_header *sccb;
int ret;
+ int i;
+ struct sclp_readinfo_sccb *sccb;
+ sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+ SCLP_CMDW_READ_SCP_INFO};
- __ctl_set_bit(0, 9); /* enable service signal subclass mask */
-
- sccb = &s390_readinfo_sccb.header;
- command = SCLP_CMDW_READ_SCP_INFO_FORCED;
- while (1) {
- u16 response;
-
- memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
- sccb->length = sizeof(s390_readinfo_sccb);
- sccb->control_mask[2] = 0x80;
-
- ret = sclp_service_call(command, &s390_readinfo_sccb);
-
- if (ret == -EIO)
- goto out;
- if (ret == -EBUSY)
- continue;
+ /* Enable service signal subclass mask. */
+ __ctl_set_bit(0, 9);
+ sccb = &early_readinfo_sccb;
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ do {
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.control_mask[2] = 0x80;
+ ret = sclp_service_call(commands[i], sccb);
+ } while (ret == -EBUSY);
+ if (ret)
+ break;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable();
+ /*
+ * Contents of the sccb might have changed
+ * therefore a barrier is needed.
+ */
barrier();
+ if (sccb->header.response_code == 0x10) {
+ early_readinfo_sccb_valid = 1;
+ break;
+ }
+ if (sccb->header.response_code != 0x1f0)
+ break;
+ }
+ /* Disable service signal subclass mask again. */
+ __ctl_clear_bit(0, 9);
+}
- response = sccb->response_code;
+void __init sclp_facilities_detect(void)
+{
+ if (!early_readinfo_sccb_valid)
+ return;
+ sclp_facilities = early_readinfo_sccb.facilities;
+}
- if (response == 0x10)
- break;
+unsigned long long __init sclp_memory_detect(void)
+{
+ unsigned long long memsize;
+ struct sclp_readinfo_sccb *sccb;
- if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
- break;
+ if (!early_readinfo_sccb_valid)
+ return 0;
+ sccb = &early_readinfo_sccb;
+ if (sccb->rnsize)
+ memsize = sccb->rnsize << 20;
+ else
+ memsize = sccb->rnsize2 << 20;
+ if (sccb->rnmax)
+ memsize *= sccb->rnmax;
+ else
+ memsize *= sccb->rnmax2;
+ return memsize;
+}
- command = SCLP_CMDW_READ_SCP_INFO;
- }
-out:
- __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+ struct sclp_readinfo_sccb *sccb;
+
+ if (!early_readinfo_sccb_valid)
+ return;
+ sccb = &early_readinfo_sccb;
+ info->is_valid = 1;
+ if (sccb->flags & 0x2)
+ info->has_dump = 1;
+ memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 726334757bbf..40cd21bc5cc4 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -621,11 +621,24 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
/*
* Initialize all relevant components and register driver with system.
*/
-static int
-__sclp_vt220_init(int early)
+static void __init __sclp_vt220_cleanup(void)
+{
+ struct list_head *page, *p;
+
+ list_for_each_safe(page, p, &sclp_vt220_empty) {
+ list_del(page);
+ if (slab_is_available())
+ free_page((unsigned long) page);
+ else
+ free_bootmem((unsigned long) page, PAGE_SIZE);
+ }
+}
+
+static int __init __sclp_vt220_init(void)
{
void *page;
int i;
+ int num_pages;
if (sclp_vt220_initialized)
return 0;
@@ -642,13 +655,16 @@ __sclp_vt220_init(int early)
sclp_vt220_flush_later = 0;
/* Allocate pages for output buffering */
- for (i = 0; i < (early ? MAX_CONSOLE_PAGES : MAX_KMEM_PAGES); i++) {
- if (early)
- page = alloc_bootmem_low_pages(PAGE_SIZE);
- else
+ num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
+ for (i = 0; i < num_pages; i++) {
+ if (slab_is_available())
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!page)
+ else
+ page = alloc_bootmem_low_pages(PAGE_SIZE);
+ if (!page) {
+ __sclp_vt220_cleanup();
return -ENOMEM;
+ }
list_add_tail((struct list_head *) page, &sclp_vt220_empty);
}
return 0;
@@ -662,14 +678,13 @@ static const struct tty_operations sclp_vt220_ops = {
.flush_chars = sclp_vt220_flush_chars,
.write_room = sclp_vt220_write_room,
.chars_in_buffer = sclp_vt220_chars_in_buffer,
- .flush_buffer = sclp_vt220_flush_buffer
+ .flush_buffer = sclp_vt220_flush_buffer,
};
/*
* Register driver with SCLP and Linux and initialize internal tty structures.
*/
-static int __init
-sclp_vt220_tty_init(void)
+static int __init sclp_vt220_tty_init(void)
{
struct tty_driver *driver;
int rc;
@@ -679,18 +694,15 @@ sclp_vt220_tty_init(void)
driver = alloc_tty_driver(1);
if (!driver)
return -ENOMEM;
- rc = __sclp_vt220_init(0);
- if (rc) {
- put_tty_driver(driver);
- return rc;
- }
+ rc = __sclp_vt220_init();
+ if (rc)
+ goto out_driver;
rc = sclp_register(&sclp_vt220_register);
if (rc) {
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - "
"sclp_register returned %d\n", rc);
- put_tty_driver(driver);
- return rc;
+ goto out_init;
}
driver->owner = THIS_MODULE;
@@ -709,14 +721,20 @@ sclp_vt220_tty_init(void)
printk(KERN_ERR SCLP_VT220_PRINT_HEADER
"could not register tty - "
"tty_register_driver returned %d\n", rc);
- put_tty_driver(driver);
- return rc;
+ goto out_sclp;
}
sclp_vt220_driver = driver;
return 0;
-}
-module_init(sclp_vt220_tty_init);
+out_sclp:
+ sclp_unregister(&sclp_vt220_register);
+out_init:
+ __sclp_vt220_cleanup();
+out_driver:
+ put_tty_driver(driver);
+ return rc;
+}
+__initcall(sclp_vt220_tty_init);
#ifdef CONFIG_SCLP_VT220_CONSOLE
@@ -762,7 +780,7 @@ sclp_vt220_con_init(void)
if (!CONSOLE_IS_SCLP)
return 0;
- rc = __sclp_vt220_init(1);
+ rc = __sclp_vt220_init();
if (rc)
return rc;
/* Attach linux console */
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
index 3b52f5c1dbef..dddf8d62c153 100644
--- a/drivers/s390/char/tape.h
+++ b/drivers/s390/char/tape.h
@@ -188,7 +188,7 @@ struct tape_blk_data
{
struct tape_device * device;
/* Block device request queue. */
- request_queue_t * request_queue;
+ struct request_queue * request_queue;
spinlock_t request_queue_lock;
/* Task to move entries from block request to CCS request queue. */
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index e765875e8db2..80e7a537e7d2 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -131,10 +131,9 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
{
struct tape_34xx_work *p;
- if ((p = kmalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
+ if ((p = kzalloc(sizeof(*p), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- memset(p, 0, sizeof(*p));
INIT_WORK(&p->work, tape_34xx_work_handler);
p->device = tape_get_device_reference(device);
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index dd0ecaed592e..eeb92e2ed0cc 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -147,7 +147,7 @@ static void
tapeblock_requeue(struct work_struct *work) {
struct tape_blk_data * blkdat;
struct tape_device * device;
- request_queue_t * queue;
+ struct request_queue * queue;
int nr_queued;
struct request * req;
struct list_head * l;
@@ -194,7 +194,7 @@ tapeblock_requeue(struct work_struct *work) {
* Tape request queue function. Called from ll_rw_blk.c
*/
static void
-tapeblock_request_fn(request_queue_t *queue)
+tapeblock_request_fn(struct request_queue *queue)
{
struct tape_device *device;
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac5cb3e..2f419b0ea628 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2004,2005 IBM Corporation
+ * Copyright IBM Corp. 2004,2007
* Interface implementation for communication with the z/VM control program
- * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
*
*
* z/VMs CP offers the possibility to issue commands via the diagnose code 8
@@ -22,9 +22,11 @@
#include "vmcp.h"
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
+MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>");
MODULE_DESCRIPTION("z/VM CP interface");
+#define PRINTK_HEADER "vmcp: "
+
static debug_info_t *vmcp_debug;
static int vmcp_open(struct inode *inode, struct file *file)
@@ -40,7 +42,7 @@ static int vmcp_open(struct inode *inode, struct file *file)
session->bufsize = PAGE_SIZE;
session->response = NULL;
session->resp_size = 0;
- init_MUTEX(&session->mutex);
+ mutex_init(&session->mutex);
file->private_data = session;
return nonseekable_open(inode, file);
}
@@ -57,37 +59,37 @@ static int vmcp_release(struct inode *inode, struct file *file)
}
static ssize_t
-vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
+vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
{
size_t tocopy;
struct vmcp_session *session;
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex))
+ if (mutex_lock_interruptible(&session->mutex))
return -ERESTARTSYS;
if (!session->response) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return 0;
}
if (*ppos > session->resp_size) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return 0;
}
tocopy = min(session->resp_size - (size_t) (*ppos), count);
- tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
+ tocopy = min(tocopy, session->bufsize - (size_t) (*ppos));
if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return -EFAULT;
}
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
*ppos += tocopy;
return tocopy;
}
static ssize_t
-vmcp_write(struct file *file, const char __user * buff, size_t count,
- loff_t * ppos)
+vmcp_write(struct file *file, const char __user *buff, size_t count,
+ loff_t *ppos)
{
char *cmd;
struct vmcp_session *session;
@@ -103,24 +105,23 @@ vmcp_write(struct file *file, const char __user * buff, size_t count,
}
cmd[count] = '\0';
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex)) {
+ if (mutex_lock_interruptible(&session->mutex)) {
kfree(cmd);
return -ERESTARTSYS;
}
if (!session->response)
session->response = (char *)__get_free_pages(GFP_KERNEL
- | __GFP_REPEAT | GFP_DMA,
+ | __GFP_REPEAT | GFP_DMA,
get_order(session->bufsize));
if (!session->response) {
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
kfree(cmd);
return -ENOMEM;
}
debug_text_event(vmcp_debug, 1, cmd);
- session->resp_size = cpcmd(cmd, session->response,
- session->bufsize,
- &session->resp_code);
- up(&session->mutex);
+ session->resp_size = cpcmd(cmd, session->response, session->bufsize,
+ &session->resp_code);
+ mutex_unlock(&session->mutex);
kfree(cmd);
*ppos = 0; /* reset the file pointer after a command */
return count;
@@ -145,12 +146,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int temp;
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex))
+ if (mutex_lock_interruptible(&session->mutex))
return -ERESTARTSYS;
switch (cmd) {
case VMCP_GETCODE:
temp = session->resp_code;
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return put_user(temp, (int __user *)arg);
case VMCP_SETBUF:
free_pages((unsigned long)session->response,
@@ -161,27 +162,26 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
session->bufsize = PAGE_SIZE;
temp = -EINVAL;
}
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return temp;
case VMCP_GETSIZE:
temp = session->resp_size;
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return put_user(temp, (int __user *)arg);
default:
- up(&session->mutex);
+ mutex_unlock(&session->mutex);
return -ENOIOCTLCMD;
}
}
static const struct file_operations vmcp_fops = {
.owner = THIS_MODULE,
- .open = &vmcp_open,
- .release = &vmcp_release,
- .read = &vmcp_read,
- .llseek = &no_llseek,
- .write = &vmcp_write,
- .unlocked_ioctl = &vmcp_ioctl,
- .compat_ioctl = &vmcp_ioctl
+ .open = vmcp_open,
+ .release = vmcp_release,
+ .read = vmcp_read,
+ .write = vmcp_write,
+ .unlocked_ioctl = vmcp_ioctl,
+ .compat_ioctl = vmcp_ioctl,
};
static struct miscdevice vmcp_dev = {
@@ -195,26 +195,38 @@ static int __init vmcp_init(void)
int ret;
if (!MACHINE_IS_VM) {
- printk(KERN_WARNING
- "z/VM CP interface is only available under z/VM\n");
+ PRINT_WARN("z/VM CP interface is only available under z/VM\n");
return -ENODEV;
}
- ret = misc_register(&vmcp_dev);
- if (!ret)
- printk(KERN_INFO "z/VM CP interface loaded\n");
- else
- printk(KERN_WARNING
- "z/VM CP interface not loaded. Could not register misc device.\n");
vmcp_debug = debug_register("vmcp", 1, 1, 240);
- debug_register_view(vmcp_debug, &debug_hex_ascii_view);
- return ret;
+ if (!vmcp_debug) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "debug feature\n");
+ return -ENOMEM;
+ }
+ ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view);
+ if (ret) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "debug feature view. Error code: %d\n", ret);
+ debug_unregister(vmcp_debug);
+ return ret;
+ }
+ ret = misc_register(&vmcp_dev);
+ if (ret) {
+ PRINT_ERR("z/VM CP interface not loaded. Could not register "
+ "misc device. Error code: %d\n", ret);
+ debug_unregister(vmcp_debug);
+ return ret;
+ }
+ PRINT_INFO("z/VM CP interface loaded\n");
+ return 0;
}
static void __exit vmcp_exit(void)
{
- WARN_ON(misc_deregister(&vmcp_dev) != 0);
+ misc_deregister(&vmcp_dev);
debug_unregister(vmcp_debug);
- printk(KERN_INFO "z/VM CP interface unloaded.\n");
+ PRINT_INFO("z/VM CP interface unloaded.\n");
}
module_init(vmcp_init);
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
index 8a5975f3dad7..6a993948e188 100644
--- a/drivers/s390/char/vmcp.h
+++ b/drivers/s390/char/vmcp.h
@@ -12,8 +12,8 @@
* The idea of this driver is based on cpint from Neale Ferguson
*/
-#include <asm/semaphore.h>
#include <linux/ioctl.h>
+#include <linux/mutex.h>
#define VMCP_GETCODE _IOR(0x10, 1, int)
#define VMCP_SETBUF _IOW(0x10, 2, int)
@@ -26,5 +26,5 @@ struct vmcp_session {
int resp_code;
/* As we use copy_from/to_user, which might *
* sleep and cannot use a spinlock */
- struct semaphore mutex;
+ struct mutex mutex;
};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9ae4d0..12f7a4ce82c1 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void)
}
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
{
int rc;
int i;
@@ -885,7 +885,7 @@ cleanup:
}
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
{
vmlogrdr_cleanup();
printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 4e711a985d59..3712ede16723 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count)
return rc;
}
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;