summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3215.c5
-rw-r--r--drivers/s390/char/monreader.c54
-rw-r--r--drivers/s390/char/sclp_config.c17
-rw-r--r--drivers/s390/char/sclp_tty.c6
-rw-r--r--drivers/s390/char/sclp_vt220.c19
-rw-r--r--drivers/s390/char/tape_34xx.c2
-rw-r--r--drivers/s390/char/tape_char.c4
-rw-r--r--drivers/s390/char/tape_class.c5
-rw-r--r--drivers/s390/char/tape_class.h2
-rw-r--r--drivers/s390/char/tape_proc.c9
-rw-r--r--drivers/s390/char/tty3270.c3
-rw-r--r--drivers/s390/char/vmur.c24
-rw-r--r--drivers/s390/char/vmur.h4
-rw-r--r--drivers/s390/char/vmwatchdog.c4
-rw-r--r--drivers/s390/char/zcore.c2
15 files changed, 70 insertions, 90 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 0e1f35c9ed9d..3e5653c92f4b 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -982,15 +982,16 @@ tty3215_write(struct tty_struct * tty,
/*
* Put character routine for 3215 ttys
*/
-static void
+static int
tty3215_put_char(struct tty_struct *tty, unsigned char ch)
{
struct raw3215_info *raw;
if (!tty)
- return;
+ return 0;
raw = (struct raw3215_info *) tty->driver_data;
raw3215_putchar(raw, ch);
+ return 1;
}
static void
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 67009bfa093e..1e1f50655bbf 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -111,56 +111,6 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
ASCEBC(ebcdic_name, 8);
}
-/*
- * print appropriate error message for segment_load()/segment_type()
- * return code
- */
-static void mon_segment_warn(int rc, char* seg_name)
-{
- switch (rc) {
- case -ENOENT:
- P_WARNING("cannot load/query segment %s, does not exist\n",
- seg_name);
- break;
- case -ENOSYS:
- P_WARNING("cannot load/query segment %s, not running on VM\n",
- seg_name);
- break;
- case -EIO:
- P_WARNING("cannot load/query segment %s, hardware error\n",
- seg_name);
- break;
- case -ENOTSUPP:
- P_WARNING("cannot load/query segment %s, is a multi-part "
- "segment\n", seg_name);
- break;
- case -ENOSPC:
- P_WARNING("cannot load/query segment %s, overlaps with "
- "storage\n", seg_name);
- break;
- case -EBUSY:
- P_WARNING("cannot load/query segment %s, overlaps with "
- "already loaded dcss\n", seg_name);
- break;
- case -EPERM:
- P_WARNING("cannot load/query segment %s, already loaded in "
- "incompatible mode\n", seg_name);
- break;
- case -ENOMEM:
- P_WARNING("cannot load/query segment %s, out of memory\n",
- seg_name);
- break;
- case -ERANGE:
- P_WARNING("cannot load/query segment %s, exceeds kernel "
- "mapping range\n", seg_name);
- break;
- default:
- P_WARNING("cannot load/query segment %s, return value %i\n",
- seg_name, rc);
- break;
- }
-}
-
static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
{
return *(u32 *) &monmsg->msg.rmmsg;
@@ -585,7 +535,7 @@ static int __init mon_init(void)
rc = segment_type(mon_dcss_name);
if (rc < 0) {
- mon_segment_warn(rc, mon_dcss_name);
+ segment_warning(rc, mon_dcss_name);
goto out_iucv;
}
if (rc != SEG_TYPE_SC) {
@@ -598,7 +548,7 @@ static int __init mon_init(void)
rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
&mon_dcss_start, &mon_dcss_end);
if (rc < 0) {
- mon_segment_warn(rc, mon_dcss_name);
+ segment_warning(rc, mon_dcss_name);
rc = -EINVAL;
goto out_iucv;
}
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index b8f35bc52b7b..9e784d5f7f57 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -10,6 +10,7 @@
#include <linux/cpu.h>
#include <linux/sysdev.h>
#include <linux/workqueue.h>
+#include <asm/smp.h>
#include "sclp.h"
#define TAG "sclp_config: "
@@ -19,9 +20,11 @@ struct conf_mgm_data {
u8 ev_qualifier;
} __attribute__((packed));
+#define EV_QUAL_CPU_CHANGE 1
#define EV_QUAL_CAP_CHANGE 3
static struct work_struct sclp_cpu_capability_work;
+static struct work_struct sclp_cpu_change_work;
static void sclp_cpu_capability_notify(struct work_struct *work)
{
@@ -37,13 +40,24 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
put_online_cpus();
}
+static void sclp_cpu_change_notify(struct work_struct *work)
+{
+ smp_rescan_cpus();
+}
+
static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
{
struct conf_mgm_data *cdata;
cdata = (struct conf_mgm_data *)(evbuf + 1);
- if (cdata->ev_qualifier == EV_QUAL_CAP_CHANGE)
+ switch (cdata->ev_qualifier) {
+ case EV_QUAL_CPU_CHANGE:
+ schedule_work(&sclp_cpu_change_work);
+ break;
+ case EV_QUAL_CAP_CHANGE:
schedule_work(&sclp_cpu_capability_work);
+ break;
+ }
}
static struct sclp_register sclp_conf_register =
@@ -57,6 +71,7 @@ static int __init sclp_conf_init(void)
int rc;
INIT_WORK(&sclp_cpu_capability_work, sclp_cpu_capability_notify);
+ INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
rc = sclp_register(&sclp_conf_register);
if (rc) {
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 2e616e33891d..40b11521cd20 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -332,7 +332,7 @@ sclp_tty_write_string(const unsigned char *str, int count)
if (sclp_ttybuf == NULL) {
while (list_empty(&sclp_tty_pages)) {
spin_unlock_irqrestore(&sclp_tty_lock, flags);
- if (in_atomic())
+ if (in_interrupt())
sclp_sync_wait();
else
wait_event(sclp_tty_waitq,
@@ -412,14 +412,14 @@ sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
* - including previous characters from sclp_tty_put_char() and strings from
* sclp_write() without final '\n' - will be written.
*/
-static void
+static int
sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
{
sclp_tty_chars[sclp_tty_chars_count++] = ch;
if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
sclp_tty_chars_count = 0;
- }
+ } return 1;
}
/*
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index f7b258dfd52c..35707c04e613 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -383,7 +383,7 @@ sclp_vt220_timeout(unsigned long data)
*/
static int
__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
- int convertlf)
+ int convertlf, int may_schedule)
{
unsigned long flags;
void *page;
@@ -398,9 +398,8 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
/* Create a sclp output buffer if none exists yet */
if (sclp_vt220_current_request == NULL) {
while (list_empty(&sclp_vt220_empty)) {
- spin_unlock_irqrestore(&sclp_vt220_lock,
- flags);
- if (in_atomic())
+ spin_unlock_irqrestore(&sclp_vt220_lock, flags);
+ if (in_interrupt() || !may_schedule)
sclp_sync_wait();
else
wait_event(sclp_vt220_waitq,
@@ -450,7 +449,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
static int
sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
- return __sclp_vt220_write(buf, count, 1, 0);
+ return __sclp_vt220_write(buf, count, 1, 0, 1);
}
#define SCLP_VT220_SESSION_ENDED 0x01
@@ -525,11 +524,15 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
* NOTE: include/linux/tty_driver.h specifies that a character should be
* ignored if there is no room in the queue. This driver implements a different
* semantic in that it will block when there is no more room left.
+ *
+ * FIXME: putchar can currently be called from BH and other non blocking
+ * handlers so this semantic isn't a good idea.
*/
-static void
+static int
sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
{
- __sclp_vt220_write(&ch, 1, 0, 0);
+ __sclp_vt220_write(&ch, 1, 0, 0, 1);
+ return 1;
}
/*
@@ -746,7 +749,7 @@ __initcall(sclp_vt220_tty_init);
static void
sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
{
- __sclp_vt220_write((const unsigned char *) buf, count, 1, 1);
+ __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
}
static struct tty_driver *
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 5b47e9cce75f..874adf365e46 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -394,7 +394,7 @@ tape_34xx_unit_check(struct tape_device *device, struct tape_request *request,
return tape_34xx_erp_failed(request, -ENOSPC);
default:
PRINT_ERR("Invalid op in %s:%i\n",
- __FUNCTION__, __LINE__);
+ __func__, __LINE__);
return tape_34xx_erp_failed(request, 0);
}
}
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index b830a8cbef78..ebe84067bae9 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -83,9 +83,9 @@ tapechar_setup_device(struct tape_device * device)
void
tapechar_cleanup_device(struct tape_device *device)
{
- unregister_tape_dev(device->rt);
+ unregister_tape_dev(&device->cdev->dev, device->rt);
device->rt = NULL;
- unregister_tape_dev(device->nt);
+ unregister_tape_dev(&device->cdev->dev, device->nt);
device->nt = NULL;
}
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index aa7f166f4034..6dfdb7c17981 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -99,11 +99,10 @@ fail_with_tcd:
}
EXPORT_SYMBOL(register_tape_dev);
-void unregister_tape_dev(struct tape_class_device *tcd)
+void unregister_tape_dev(struct device *device, struct tape_class_device *tcd)
{
if (tcd != NULL && !IS_ERR(tcd)) {
- sysfs_remove_link(&tcd->class_device->kobj,
- tcd->mode_name);
+ sysfs_remove_link(&device->kobj, tcd->mode_name);
device_destroy(tape_class, tcd->char_device->dev);
cdev_del(tcd->char_device);
kfree(tcd);
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index e2b5ac918acf..707b7f48c232 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -56,6 +56,6 @@ struct tape_class_device *register_tape_dev(
char * device_name,
char * node_name
);
-void unregister_tape_dev(struct tape_class_device *tcd);
+void unregister_tape_dev(struct device *device, struct tape_class_device *tcd);
#endif /* __TAPE_CLASS_H__ */
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index c9b96d51b28f..e7c888c14e71 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -111,6 +111,7 @@ static int tape_proc_open(struct inode *inode, struct file *file)
static const struct file_operations tape_proc_ops =
{
+ .owner = THIS_MODULE,
.open = tape_proc_open,
.read = seq_read,
.llseek = seq_lseek,
@@ -124,14 +125,12 @@ void
tape_proc_init(void)
{
tape_proc_devices =
- create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR,
- &proc_root);
+ proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
+ &tape_proc_ops);
if (tape_proc_devices == NULL) {
PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
return;
}
- tape_proc_devices->proc_fops = &tape_proc_ops;
- tape_proc_devices->owner = THIS_MODULE;
}
/*
@@ -141,5 +140,5 @@ void
tape_proc_cleanup(void)
{
if (tape_proc_devices != NULL)
- remove_proc_entry ("tapedevices", &proc_root);
+ remove_proc_entry ("tapedevices", NULL);
}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 70b1980a08b6..c1f2adefad41 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -965,7 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
* Insert character into the screen at the current position with the
* current color and highlight. This function does NOT do cursor movement.
*/
-static void
+static int
tty3270_put_character(struct tty3270 *tp, char ch)
{
struct tty3270_line *line;
@@ -986,6 +986,7 @@ tty3270_put_character(struct tty3270 *tp, char ch)
cell->character = tp->view.ascebc[(unsigned int) ch];
cell->highlight = tp->highlight;
cell->f_color = tp->f_color;
+ return 1;
}
/*
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 7689b500a104..83ae9a852f00 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -100,7 +100,8 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
urd->reclen = cdev->id.driver_info;
ccw_device_get_id(cdev, &urd->dev_id);
mutex_init(&urd->io_mutex);
- mutex_init(&urd->open_mutex);
+ init_waitqueue_head(&urd->wait);
+ spin_lock_init(&urd->open_lock);
atomic_set(&urd->ref_count, 1);
urd->cdev = cdev;
get_device(&cdev->dev);
@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file)
if (!urd)
return -ENXIO;
- if (file->f_flags & O_NONBLOCK) {
- if (!mutex_trylock(&urd->open_mutex)) {
+ spin_lock(&urd->open_lock);
+ while (urd->open_flag) {
+ spin_unlock(&urd->open_lock);
+ if (file->f_flags & O_NONBLOCK) {
rc = -EBUSY;
goto fail_put;
}
- } else {
- if (mutex_lock_interruptible(&urd->open_mutex)) {
+ if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
rc = -ERESTARTSYS;
goto fail_put;
}
+ spin_lock(&urd->open_lock);
}
+ urd->open_flag++;
+ spin_unlock(&urd->open_lock);
TRACE("ur_open\n");
@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file)
fail_urfile_free:
urfile_free(urf);
fail_unlock:
- mutex_unlock(&urd->open_mutex);
+ spin_lock(&urd->open_lock);
+ urd->open_flag--;
+ spin_unlock(&urd->open_lock);
fail_put:
urdev_put(urd);
return rc;
@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file)
struct urfile *urf = file->private_data;
TRACE("ur_release\n");
- mutex_unlock(&urf->urd->open_mutex);
+ spin_lock(&urf->urd->open_lock);
+ urf->urd->open_flag--;
+ spin_unlock(&urf->urd->open_lock);
+ wake_up_interruptible(&urf->urd->wait);
urdev_put(urf->urd);
urfile_free(urf);
return 0;
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h
index fa959644735a..fa320ad4593d 100644
--- a/drivers/s390/char/vmur.h
+++ b/drivers/s390/char/vmur.h
@@ -62,7 +62,6 @@ struct file_control_block {
struct urdev {
struct ccw_device *cdev; /* Backpointer to ccw device */
struct mutex io_mutex; /* Serialises device IO */
- struct mutex open_mutex; /* Serialises access to device */
struct completion *io_done; /* do_ur_io waits; irq completes */
struct device *device;
struct cdev *char_device;
@@ -71,6 +70,9 @@ struct urdev {
int class; /* VM device class */
int io_request_rc; /* return code from I/O request */
atomic_t ref_count; /* reference counter */
+ wait_queue_head_t wait; /* wait queue to serialize open */
+ int open_flag; /* "urdev is open" flag */
+ spinlock_t open_lock; /* serialize critical sections */
};
/*
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 6f40facb1c4d..19f8389291b6 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -96,7 +96,7 @@ static int vmwdt_keepalive(void)
if (ret) {
printk(KERN_WARNING "%s: problem setting interval %d, "
- "cmd %s\n", __FUNCTION__, vmwdt_interval,
+ "cmd %s\n", __func__, vmwdt_interval,
vmwdt_cmd);
}
return ret;
@@ -107,7 +107,7 @@ static int vmwdt_disable(void)
int ret = __diag288(wdt_cancel, 0, "", 0);
if (ret) {
printk(KERN_WARNING "%s: problem disabling watchdog\n",
- __FUNCTION__);
+ __func__);
}
return ret;
}
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index f523501e6e6c..bbbd14e9d48f 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -224,7 +224,7 @@ static int __init init_cpu_info(enum arch_id arch)
sa = kmalloc(sizeof(*sa), GFP_KERNEL);
if (!sa) {
- ERROR_MSG("kmalloc failed: %s: %i\n",__FUNCTION__, __LINE__);
+ ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
return -ENOMEM;
}
if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {