aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3215.c38
-rw-r--r--drivers/s390/char/con3270.c6
-rw-r--r--drivers/s390/char/fs3270.c34
-rw-r--r--drivers/s390/char/monreader.c78
-rw-r--r--drivers/s390/char/monwriter.c3
-rw-r--r--drivers/s390/char/raw3270.c28
-rw-r--r--drivers/s390/char/sclp.c12
-rw-r--r--drivers/s390/char/sclp_cmd.c343
-rw-r--r--drivers/s390/char/sclp_con.c5
-rw-r--r--drivers/s390/char/sclp_config.c17
-rw-r--r--drivers/s390/char/sclp_cpi_sys.c57
-rw-r--r--drivers/s390/char/sclp_quiesce.c8
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_sdias.c4
-rw-r--r--drivers/s390/char/sclp_tty.c261
-rw-r--r--drivers/s390/char/sclp_tty.h53
-rw-r--r--drivers/s390/char/sclp_vt220.c62
-rw-r--r--drivers/s390/char/tape_34xx.c12
-rw-r--r--drivers/s390/char/tape_3590.c21
-rw-r--r--drivers/s390/char/tape_char.c12
-rw-r--r--drivers/s390/char/tape_core.c15
-rw-r--r--drivers/s390/char/tty3270.c9
-rw-r--r--drivers/s390/char/vmcp.c41
-rw-r--r--drivers/s390/char/vmlogrdr.c37
-rw-r--r--drivers/s390/char/vmur.c27
-rw-r--r--drivers/s390/char/vmwatchdog.c23
-rw-r--r--drivers/s390/char/zcore.c132
27 files changed, 700 insertions, 640 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 3e5653c92f4b..d3ec9b55ab35 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -93,9 +93,6 @@ struct raw3215_info {
93 struct raw3215_req *queued_write;/* pointer to queued write requests */ 93 struct raw3215_req *queued_write;/* pointer to queued write requests */
94 wait_queue_head_t empty_wait; /* wait queue for flushing */ 94 wait_queue_head_t empty_wait; /* wait queue for flushing */
95 struct timer_list timer; /* timer for delayed output */ 95 struct timer_list timer; /* timer for delayed output */
96 char *message; /* pending message from raw3215_irq */
97 int msg_dstat; /* dstat for pending message */
98 int msg_cstat; /* cstat for pending message */
99 int line_pos; /* position on the line (for tabs) */ 96 int line_pos; /* position on the line (for tabs) */
100 char ubuffer[80]; /* copy_from_user buffer */ 97 char ubuffer[80]; /* copy_from_user buffer */
101}; 98};
@@ -359,11 +356,6 @@ raw3215_tasklet(void *data)
359 raw3215_mk_write_req(raw); 356 raw3215_mk_write_req(raw);
360 raw3215_try_io(raw); 357 raw3215_try_io(raw);
361 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 358 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
362 /* Check for pending message from raw3215_irq */
363 if (raw->message != NULL) {
364 printk(raw->message, raw->msg_dstat, raw->msg_cstat);
365 raw->message = NULL;
366 }
367 tty = raw->tty; 359 tty = raw->tty;
368 if (tty != NULL && 360 if (tty != NULL &&
369 RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) { 361 RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
@@ -381,20 +373,14 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
381 struct raw3215_req *req; 373 struct raw3215_req *req;
382 struct tty_struct *tty; 374 struct tty_struct *tty;
383 int cstat, dstat; 375 int cstat, dstat;
384 int count, slen; 376 int count;
385 377
386 raw = cdev->dev.driver_data; 378 raw = cdev->dev.driver_data;
387 req = (struct raw3215_req *) intparm; 379 req = (struct raw3215_req *) intparm;
388 cstat = irb->scsw.cstat; 380 cstat = irb->scsw.cmd.cstat;
389 dstat = irb->scsw.dstat; 381 dstat = irb->scsw.cmd.dstat;
390 if (cstat != 0) { 382 if (cstat != 0)
391 raw->message = KERN_WARNING
392 "Got nonzero channel status in raw3215_irq "
393 "(dev sts 0x%2x, sch sts 0x%2x)";
394 raw->msg_dstat = dstat;
395 raw->msg_cstat = cstat;
396 tasklet_schedule(&raw->tasklet); 383 tasklet_schedule(&raw->tasklet);
397 }
398 if (dstat & 0x01) { /* we got a unit exception */ 384 if (dstat & 0x01) { /* we got a unit exception */
399 dstat &= ~0x01; /* we can ignore it */ 385 dstat &= ~0x01; /* we can ignore it */
400 } 386 }
@@ -404,8 +390,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
404 break; 390 break;
405 /* Attention interrupt, someone hit the enter key */ 391 /* Attention interrupt, someone hit the enter key */
406 raw3215_mk_read_req(raw); 392 raw3215_mk_read_req(raw);
407 if (MACHINE_IS_P390)
408 memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);
409 tasklet_schedule(&raw->tasklet); 393 tasklet_schedule(&raw->tasklet);
410 break; 394 break;
411 case 0x08: 395 case 0x08:
@@ -415,7 +399,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
415 return; /* That shouldn't happen ... */ 399 return; /* That shouldn't happen ... */
416 if (req->type == RAW3215_READ) { 400 if (req->type == RAW3215_READ) {
417 /* store residual count, then wait for device end */ 401 /* store residual count, then wait for device end */
418 req->residual = irb->scsw.count; 402 req->residual = irb->scsw.cmd.count;
419 } 403 }
420 if (dstat == 0x08) 404 if (dstat == 0x08)
421 break; 405 break;
@@ -428,11 +412,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
428 412
429 tty = raw->tty; 413 tty = raw->tty;
430 count = 160 - req->residual; 414 count = 160 - req->residual;
431 if (MACHINE_IS_P390) {
432 slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE);
433 if (count > slen)
434 count = slen;
435 } else
436 EBCASC(raw->inbuf, count); 415 EBCASC(raw->inbuf, count);
437 cchar = ctrlchar_handle(raw->inbuf, count, tty); 416 cchar = ctrlchar_handle(raw->inbuf, count, tty);
438 switch (cchar & CTRLCHAR_MASK) { 417 switch (cchar & CTRLCHAR_MASK) {
@@ -481,11 +460,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
481 raw->flags &= ~RAW3215_WORKING; 460 raw->flags &= ~RAW3215_WORKING;
482 raw3215_free_req(req); 461 raw3215_free_req(req);
483 } 462 }
484 raw->message = KERN_WARNING
485 "Spurious interrupt in in raw3215_irq "
486 "(dev sts 0x%2x, sch sts 0x%2x)";
487 raw->msg_dstat = dstat;
488 raw->msg_cstat = cstat;
489 tasklet_schedule(&raw->tasklet); 463 tasklet_schedule(&raw->tasklet);
490 } 464 }
491 return; 465 return;
@@ -883,7 +857,6 @@ con3215_init(void)
883 free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE); 857 free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE);
884 free_bootmem((unsigned long) raw, sizeof(struct raw3215_info)); 858 free_bootmem((unsigned long) raw, sizeof(struct raw3215_info));
885 raw3215[0] = NULL; 859 raw3215[0] = NULL;
886 printk("Couldn't find a 3215 console device\n");
887 return -ENODEV; 860 return -ENODEV;
888 } 861 }
889 register_console(&con3215); 862 register_console(&con3215);
@@ -1157,7 +1130,6 @@ tty3215_init(void)
1157 tty_set_operations(driver, &tty3215_ops); 1130 tty_set_operations(driver, &tty3215_ops);
1158 ret = tty_register_driver(driver); 1131 ret = tty_register_driver(driver);
1159 if (ret) { 1132 if (ret) {
1160 printk("Couldn't register tty3215 driver\n");
1161 put_tty_driver(driver); 1133 put_tty_driver(driver);
1162 return ret; 1134 return ret;
1163 } 1135 }
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 0b040557db02..3c07974886ed 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -411,15 +411,15 @@ static int
411con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb) 411con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
412{ 412{
413 /* Handle ATTN. Schedule tasklet to read aid. */ 413 /* Handle ATTN. Schedule tasklet to read aid. */
414 if (irb->scsw.dstat & DEV_STAT_ATTENTION) 414 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION)
415 con3270_issue_read(cp); 415 con3270_issue_read(cp);
416 416
417 if (rq) { 417 if (rq) {
418 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) 418 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
419 rq->rc = -EIO; 419 rq->rc = -EIO;
420 else 420 else
421 /* Normal end. Copy residual count. */ 421 /* Normal end. Copy residual count. */
422 rq->rescnt = irb->scsw.count; 422 rq->rescnt = irb->scsw.cmd.count;
423 } 423 }
424 return RAW3270_IO_DONE; 424 return RAW3270_IO_DONE;
425} 425}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index ef36f2132aa4..d18e6d2e0b49 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -14,6 +14,7 @@
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#include <linux/smp_lock.h>
17 18
18#include <asm/ccwdev.h> 19#include <asm/ccwdev.h>
19#include <asm/cio.h> 20#include <asm/cio.h>
@@ -216,17 +217,17 @@ static int
216fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb) 217fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
217{ 218{
218 /* Handle ATTN. Set indication and wake waiters for attention. */ 219 /* Handle ATTN. Set indication and wake waiters for attention. */
219 if (irb->scsw.dstat & DEV_STAT_ATTENTION) { 220 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
220 fp->attention = 1; 221 fp->attention = 1;
221 wake_up(&fp->wait); 222 wake_up(&fp->wait);
222 } 223 }
223 224
224 if (rq) { 225 if (rq) {
225 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) 226 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
226 rq->rc = -EIO; 227 rq->rc = -EIO;
227 else 228 else
228 /* Normal end. Copy residual count. */ 229 /* Normal end. Copy residual count. */
229 rq->rescnt = irb->scsw.count; 230 rq->rescnt = irb->scsw.cmd.count;
230 } 231 }
231 return RAW3270_IO_DONE; 232 return RAW3270_IO_DONE;
232} 233}
@@ -421,6 +422,7 @@ fs3270_open(struct inode *inode, struct file *filp)
421 422
422 if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR) 423 if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR)
423 return -ENODEV; 424 return -ENODEV;
425 lock_kernel();
424 minor = iminor(filp->f_path.dentry->d_inode); 426 minor = iminor(filp->f_path.dentry->d_inode);
425 /* Check for minor 0 multiplexer. */ 427 /* Check for minor 0 multiplexer. */
426 if (minor == 0) { 428 if (minor == 0) {
@@ -429,7 +431,8 @@ fs3270_open(struct inode *inode, struct file *filp)
429 tty = get_current_tty(); 431 tty = get_current_tty();
430 if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { 432 if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) {
431 mutex_unlock(&tty_mutex); 433 mutex_unlock(&tty_mutex);
432 return -ENODEV; 434 rc = -ENODEV;
435 goto out;
433 } 436 }
434 minor = tty->index + RAW3270_FIRSTMINOR; 437 minor = tty->index + RAW3270_FIRSTMINOR;
435 mutex_unlock(&tty_mutex); 438 mutex_unlock(&tty_mutex);
@@ -438,19 +441,22 @@ fs3270_open(struct inode *inode, struct file *filp)
438 fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); 441 fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor);
439 if (!IS_ERR(fp)) { 442 if (!IS_ERR(fp)) {
440 raw3270_put_view(&fp->view); 443 raw3270_put_view(&fp->view);
441 return -EBUSY; 444 rc = -EBUSY;
445 goto out;
442 } 446 }
443 /* Allocate fullscreen view structure. */ 447 /* Allocate fullscreen view structure. */
444 fp = fs3270_alloc_view(); 448 fp = fs3270_alloc_view();
445 if (IS_ERR(fp)) 449 if (IS_ERR(fp)) {
446 return PTR_ERR(fp); 450 rc = PTR_ERR(fp);
451 goto out;
452 }
447 453
448 init_waitqueue_head(&fp->wait); 454 init_waitqueue_head(&fp->wait);
449 fp->fs_pid = get_pid(task_pid(current)); 455 fp->fs_pid = get_pid(task_pid(current));
450 rc = raw3270_add_view(&fp->view, &fs3270_fn, minor); 456 rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
451 if (rc) { 457 if (rc) {
452 fs3270_free_view(&fp->view); 458 fs3270_free_view(&fp->view);
453 return rc; 459 goto out;
454 } 460 }
455 461
456 /* Allocate idal-buffer. */ 462 /* Allocate idal-buffer. */
@@ -458,7 +464,8 @@ fs3270_open(struct inode *inode, struct file *filp)
458 if (IS_ERR(ib)) { 464 if (IS_ERR(ib)) {
459 raw3270_put_view(&fp->view); 465 raw3270_put_view(&fp->view);
460 raw3270_del_view(&fp->view); 466 raw3270_del_view(&fp->view);
461 return PTR_ERR(fp); 467 rc = PTR_ERR(fp);
468 goto out;
462 } 469 }
463 fp->rdbuf = ib; 470 fp->rdbuf = ib;
464 471
@@ -466,9 +473,11 @@ fs3270_open(struct inode *inode, struct file *filp)
466 if (rc) { 473 if (rc) {
467 raw3270_put_view(&fp->view); 474 raw3270_put_view(&fp->view);
468 raw3270_del_view(&fp->view); 475 raw3270_del_view(&fp->view);
469 return rc; 476 goto out;
470 } 477 }
471 filp->private_data = fp; 478 filp->private_data = fp;
479out:
480 unlock_kernel();
472 return 0; 481 return 0;
473} 482}
474 483
@@ -512,11 +521,8 @@ fs3270_init(void)
512 int rc; 521 int rc;
513 522
514 rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); 523 rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
515 if (rc) { 524 if (rc)
516 printk(KERN_ERR "fs3270 can't get major number %d: errno %d\n",
517 IBM_FS3270_MAJOR, rc);
518 return rc; 525 return rc;
519 }
520 return 0; 526 return 0;
521} 527}
522 528
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 1e1f50655bbf..35fd8dfcaaa6 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,14 +3,14 @@
3 * 3 *
4 * Character device driver for reading z/VM *MONITOR service records. 4 * Character device driver for reading z/VM *MONITOR service records.
5 * 5 *
6 * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH. 6 * Copyright IBM Corp. 2004, 2008
7 * 7 * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
8 * Author: Gerald Schaefer <geraldsc@de.ibm.com>
9 */ 8 */
10 9
11#include <linux/module.h> 10#include <linux/module.h>
12#include <linux/moduleparam.h> 11#include <linux/moduleparam.h>
13#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/smp_lock.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -18,12 +18,11 @@
18#include <linux/ctype.h> 18#include <linux/ctype.h>
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/poll.h>
22#include <net/iucv/iucv.h>
21#include <asm/uaccess.h> 23#include <asm/uaccess.h>
22#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
23#include <asm/extmem.h> 25#include <asm/extmem.h>
24#include <linux/poll.h>
25#include <net/iucv/iucv.h>
26
27 26
28//#define MON_DEBUG /* Debug messages on/off */ 27//#define MON_DEBUG /* Debug messages on/off */
29 28
@@ -152,10 +151,7 @@ static int mon_check_mca(struct mon_msg *monmsg)
152 (mon_mca_end(monmsg) > mon_dcss_end) || 151 (mon_mca_end(monmsg) > mon_dcss_end) ||
153 (mon_mca_start(monmsg) < mon_dcss_start) || 152 (mon_mca_start(monmsg) < mon_dcss_start) ||
154 ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) 153 ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
155 {
156 P_DEBUG("READ, IGNORED INVALID MCA\n\n");
157 return -EINVAL; 154 return -EINVAL;
158 }
159 return 0; 155 return 0;
160} 156}
161 157
@@ -164,10 +160,6 @@ static int mon_send_reply(struct mon_msg *monmsg,
164{ 160{
165 int rc; 161 int rc;
166 162
167 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
168 "0x%08X\n\n",
169 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
170
171 rc = iucv_message_reply(monpriv->path, &monmsg->msg, 163 rc = iucv_message_reply(monpriv->path, &monmsg->msg,
172 IUCV_IPRMDATA, NULL, 0); 164 IUCV_IPRMDATA, NULL, 0);
173 atomic_dec(&monpriv->msglim_count); 165 atomic_dec(&monpriv->msglim_count);
@@ -202,15 +194,12 @@ static struct mon_private *mon_alloc_mem(void)
202 struct mon_private *monpriv; 194 struct mon_private *monpriv;
203 195
204 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 196 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
205 if (!monpriv) { 197 if (!monpriv)
206 P_ERROR("no memory for monpriv\n");
207 return NULL; 198 return NULL;
208 }
209 for (i = 0; i < MON_MSGLIM; i++) { 199 for (i = 0; i < MON_MSGLIM; i++) {
210 monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), 200 monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg),
211 GFP_KERNEL); 201 GFP_KERNEL);
212 if (!monpriv->msg_array[i]) { 202 if (!monpriv->msg_array[i]) {
213 P_ERROR("open, no memory for msg_array\n");
214 mon_free_mem(monpriv); 203 mon_free_mem(monpriv);
215 return NULL; 204 return NULL;
216 } 205 }
@@ -218,41 +207,10 @@ static struct mon_private *mon_alloc_mem(void)
218 return monpriv; 207 return monpriv;
219} 208}
220 209
221static inline void mon_read_debug(struct mon_msg *monmsg,
222 struct mon_private *monpriv)
223{
224#ifdef MON_DEBUG
225 u8 msg_type[2], mca_type;
226 unsigned long records_len;
227
228 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
229
230 memcpy(msg_type, &monmsg->msg.class, 2);
231 EBCASC(msg_type, 2);
232 mca_type = mon_mca_type(monmsg, 0);
233 EBCASC(&mca_type, 1);
234
235 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
236 monpriv->read_index, monpriv->write_index);
237 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
238 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
239 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
240 msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
241 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
242 P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n",
243 mon_mca_start(monmsg), mon_mca_end(monmsg));
244 P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n",
245 mon_rec_start(monmsg), mon_rec_end(monmsg), records_len);
246 if (mon_mca_size(monmsg) > 12)
247 P_DEBUG("READ, MORE THAN ONE MCA\n\n");
248#endif
249}
250
251static inline void mon_next_mca(struct mon_msg *monmsg) 210static inline void mon_next_mca(struct mon_msg *monmsg)
252{ 211{
253 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) 212 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
254 return; 213 return;
255 P_DEBUG("READ, NEXT MCA\n\n");
256 monmsg->mca_offset += 12; 214 monmsg->mca_offset += 12;
257 monmsg->pos = 0; 215 monmsg->pos = 0;
258} 216}
@@ -269,7 +227,6 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv)
269 monmsg->msglim_reached = 0; 227 monmsg->msglim_reached = 0;
270 monmsg->pos = 0; 228 monmsg->pos = 0;
271 monmsg->mca_offset = 0; 229 monmsg->mca_offset = 0;
272 P_WARNING("read, message limit reached\n");
273 monpriv->read_index = (monpriv->read_index + 1) % 230 monpriv->read_index = (monpriv->read_index + 1) %
274 MON_MSGLIM; 231 MON_MSGLIM;
275 atomic_dec(&monpriv->read_ready); 232 atomic_dec(&monpriv->read_ready);
@@ -286,10 +243,6 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
286{ 243{
287 struct mon_private *monpriv = path->private; 244 struct mon_private *monpriv = path->private;
288 245
289 P_DEBUG("IUCV connection completed\n");
290 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
291 "0x%02X, Sample = 0x%02X\n",
292 ipuser[0], ipuser[1], ipuser[2]);
293 atomic_set(&monpriv->iucv_connected, 1); 246 atomic_set(&monpriv->iucv_connected, 1);
294 wake_up(&mon_conn_wait_queue); 247 wake_up(&mon_conn_wait_queue);
295} 248}
@@ -310,7 +263,6 @@ static void mon_iucv_message_pending(struct iucv_path *path,
310{ 263{
311 struct mon_private *monpriv = path->private; 264 struct mon_private *monpriv = path->private;
312 265
313 P_DEBUG("IUCV message pending\n");
314 memcpy(&monpriv->msg_array[monpriv->write_index]->msg, 266 memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
315 msg, sizeof(*msg)); 267 msg, sizeof(*msg));
316 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { 268 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
@@ -340,6 +292,7 @@ static int mon_open(struct inode *inode, struct file *filp)
340 /* 292 /*
341 * only one user allowed 293 * only one user allowed
342 */ 294 */
295 lock_kernel();
343 rc = -EBUSY; 296 rc = -EBUSY;
344 if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 297 if (test_and_set_bit(MON_IN_USE, &mon_in_use))
345 goto out; 298 goto out;
@@ -375,8 +328,8 @@ static int mon_open(struct inode *inode, struct file *filp)
375 rc = -EIO; 328 rc = -EIO;
376 goto out_path; 329 goto out_path;
377 } 330 }
378 P_INFO("open, established connection to *MONITOR service\n\n");
379 filp->private_data = monpriv; 331 filp->private_data = monpriv;
332 unlock_kernel();
380 return nonseekable_open(inode, filp); 333 return nonseekable_open(inode, filp);
381 334
382out_path: 335out_path:
@@ -386,6 +339,7 @@ out_priv:
386out_use: 339out_use:
387 clear_bit(MON_IN_USE, &mon_in_use); 340 clear_bit(MON_IN_USE, &mon_in_use);
388out: 341out:
342 unlock_kernel();
389 return rc; 343 return rc;
390} 344}
391 345
@@ -400,8 +354,6 @@ static int mon_close(struct inode *inode, struct file *filp)
400 rc = iucv_path_sever(monpriv->path, user_data_sever); 354 rc = iucv_path_sever(monpriv->path, user_data_sever);
401 if (rc) 355 if (rc)
402 P_ERROR("close, iucv_sever failed with rc = %i\n", rc); 356 P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
403 else
404 P_INFO("close, terminated connection to *MONITOR service\n");
405 357
406 atomic_set(&monpriv->iucv_severed, 0); 358 atomic_set(&monpriv->iucv_severed, 0);
407 atomic_set(&monpriv->iucv_connected, 0); 359 atomic_set(&monpriv->iucv_connected, 0);
@@ -442,10 +394,8 @@ static ssize_t mon_read(struct file *filp, char __user *data,
442 monmsg = monpriv->msg_array[monpriv->read_index]; 394 monmsg = monpriv->msg_array[monpriv->read_index];
443 } 395 }
444 396
445 if (!monmsg->pos) { 397 if (!monmsg->pos)
446 monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; 398 monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset;
447 mon_read_debug(monmsg, monpriv);
448 }
449 if (mon_check_mca(monmsg)) 399 if (mon_check_mca(monmsg))
450 goto reply; 400 goto reply;
451 401
@@ -531,7 +481,6 @@ static int __init mon_init(void)
531 P_ERROR("failed to register with iucv driver\n"); 481 P_ERROR("failed to register with iucv driver\n");
532 return rc; 482 return rc;
533 } 483 }
534 P_INFO("open, registered with IUCV\n");
535 484
536 rc = segment_type(mon_dcss_name); 485 rc = segment_type(mon_dcss_name);
537 if (rc < 0) { 486 if (rc < 0) {
@@ -555,13 +504,8 @@ static int __init mon_init(void)
555 dcss_mkname(mon_dcss_name, &user_data_connect[8]); 504 dcss_mkname(mon_dcss_name, &user_data_connect[8]);
556 505
557 rc = misc_register(&mon_dev); 506 rc = misc_register(&mon_dev);
558 if (rc < 0 ) { 507 if (rc < 0 )
559 P_ERROR("misc_register failed, rc = %i\n", rc);
560 goto out; 508 goto out;
561 }
562 P_INFO("Loaded segment %s from %p to %p, size = %lu Byte\n",
563 mon_dcss_name, (void *) mon_dcss_start, (void *) mon_dcss_end,
564 mon_dcss_end - mon_dcss_start + 1);
565 return 0; 509 return 0;
566 510
567out: 511out:
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index a86c0534cd49..4d71aa8c1a79 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -12,6 +12,7 @@
12#include <linux/moduleparam.h> 12#include <linux/moduleparam.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/smp_lock.h>
15#include <linux/types.h> 16#include <linux/types.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
17#include <linux/miscdevice.h> 18#include <linux/miscdevice.h>
@@ -179,10 +180,12 @@ static int monwrite_open(struct inode *inode, struct file *filp)
179 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 180 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
180 if (!monpriv) 181 if (!monpriv)
181 return -ENOMEM; 182 return -ENOMEM;
183 lock_kernel();
182 INIT_LIST_HEAD(&monpriv->list); 184 INIT_LIST_HEAD(&monpriv->list);
183 monpriv->hdr_to_read = sizeof(monpriv->hdr); 185 monpriv->hdr_to_read = sizeof(monpriv->hdr);
184 mutex_init(&monpriv->thread_mutex); 186 mutex_init(&monpriv->thread_mutex);
185 filp->private_data = monpriv; 187 filp->private_data = monpriv;
188 unlock_kernel();
186 return nonseekable_open(inode, filp); 189 return nonseekable_open(inode, filp);
187} 190}
188 191
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 848ef7e8523f..81a96e019080 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -153,19 +153,10 @@ struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size)
153 struct raw3270_request *rq; 153 struct raw3270_request *rq;
154 154
155 rq = alloc_bootmem_low(sizeof(struct raw3270)); 155 rq = alloc_bootmem_low(sizeof(struct raw3270));
156 if (!rq)
157 return ERR_PTR(-ENOMEM);
158 memset(rq, 0, sizeof(struct raw3270_request));
159 156
160 /* alloc output buffer. */ 157 /* alloc output buffer. */
161 if (size > 0) { 158 if (size > 0)
162 rq->buffer = alloc_bootmem_low(size); 159 rq->buffer = alloc_bootmem_low(size);
163 if (!rq->buffer) {
164 free_bootmem((unsigned long) rq,
165 sizeof(struct raw3270));
166 return ERR_PTR(-ENOMEM);
167 }
168 }
169 rq->size = size; 160 rq->size = size;
170 INIT_LIST_HEAD(&rq->list); 161 INIT_LIST_HEAD(&rq->list);
171 162
@@ -372,17 +363,17 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
372 363
373 if (IS_ERR(irb)) 364 if (IS_ERR(irb))
374 rc = RAW3270_IO_RETRY; 365 rc = RAW3270_IO_RETRY;
375 else if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) { 366 else if (irb->scsw.cmd.fctl & SCSW_FCTL_HALT_FUNC) {
376 rq->rc = -EIO; 367 rq->rc = -EIO;
377 rc = RAW3270_IO_DONE; 368 rc = RAW3270_IO_DONE;
378 } else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END | 369 } else if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END |
379 DEV_STAT_UNIT_EXCEP)) { 370 DEV_STAT_UNIT_EXCEP)) {
380 /* Handle CE-DE-UE and subsequent UDE */ 371 /* Handle CE-DE-UE and subsequent UDE */
381 set_bit(RAW3270_FLAGS_BUSY, &rp->flags); 372 set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
382 rc = RAW3270_IO_BUSY; 373 rc = RAW3270_IO_BUSY;
383 } else if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) { 374 } else if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
384 /* Wait for UDE if busy flag is set. */ 375 /* Wait for UDE if busy flag is set. */
385 if (irb->scsw.dstat & DEV_STAT_DEV_END) { 376 if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
386 clear_bit(RAW3270_FLAGS_BUSY, &rp->flags); 377 clear_bit(RAW3270_FLAGS_BUSY, &rp->flags);
387 /* Got it, now retry. */ 378 /* Got it, now retry. */
388 rc = RAW3270_IO_RETRY; 379 rc = RAW3270_IO_RETRY;
@@ -497,7 +488,7 @@ raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
497 * Unit-Check Processing: 488 * Unit-Check Processing:
498 * Expect Command Reject or Intervention Required. 489 * Expect Command Reject or Intervention Required.
499 */ 490 */
500 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) { 491 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
501 /* Request finished abnormally. */ 492 /* Request finished abnormally. */
502 if (irb->ecw[0] & SNS0_INTERVENTION_REQ) { 493 if (irb->ecw[0] & SNS0_INTERVENTION_REQ) {
503 set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags); 494 set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags);
@@ -505,16 +496,16 @@ raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
505 } 496 }
506 } 497 }
507 if (rq) { 498 if (rq) {
508 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) { 499 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
509 if (irb->ecw[0] & SNS0_CMD_REJECT) 500 if (irb->ecw[0] & SNS0_CMD_REJECT)
510 rq->rc = -EOPNOTSUPP; 501 rq->rc = -EOPNOTSUPP;
511 else 502 else
512 rq->rc = -EIO; 503 rq->rc = -EIO;
513 } else 504 } else
514 /* Request finished normally. Copy residual count. */ 505 /* Request finished normally. Copy residual count. */
515 rq->rescnt = irb->scsw.count; 506 rq->rescnt = irb->scsw.cmd.count;
516 } 507 }
517 if (irb->scsw.dstat & DEV_STAT_ATTENTION) { 508 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
518 set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags); 509 set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags);
519 wake_up(&raw3270_wait_queue); 510 wake_up(&raw3270_wait_queue);
520 } 511 }
@@ -619,7 +610,6 @@ __raw3270_size_device_vm(struct raw3270 *rp)
619 rp->cols = 132; 610 rp->cols = 132;
620 break; 611 break;
621 default: 612 default:
622 printk(KERN_WARNING "vrdccrmd is 0x%.8x\n", model);
623 rc = -EOPNOTSUPP; 613 rc = -EOPNOTSUPP;
624 break; 614 break;
625 } 615 }
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 2c7a1ee6b041..3c8b25e6c345 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -506,6 +506,8 @@ sclp_state_change_cb(struct evbuf_header *evbuf)
506 if (scbuf->validity_sclp_send_mask) 506 if (scbuf->validity_sclp_send_mask)
507 sclp_send_mask = scbuf->sclp_send_mask; 507 sclp_send_mask = scbuf->sclp_send_mask;
508 spin_unlock_irqrestore(&sclp_lock, flags); 508 spin_unlock_irqrestore(&sclp_lock, flags);
509 if (scbuf->validity_sclp_active_facility_mask)
510 sclp_facilities = scbuf->sclp_active_facility_mask;
509 sclp_dispatch_state_change(); 511 sclp_dispatch_state_change();
510} 512}
511 513
@@ -782,11 +784,9 @@ sclp_check_handler(__u16 code)
782 /* Is this the interrupt we are waiting for? */ 784 /* Is this the interrupt we are waiting for? */
783 if (finished_sccb == 0) 785 if (finished_sccb == 0)
784 return; 786 return;
785 if (finished_sccb != (u32) (addr_t) sclp_init_sccb) { 787 if (finished_sccb != (u32) (addr_t) sclp_init_sccb)
786 printk(KERN_WARNING SCLP_HEADER "unsolicited interrupt " 788 panic("sclp: unsolicited interrupt for buffer at 0x%x\n",
787 "for buffer at 0x%x\n", finished_sccb); 789 finished_sccb);
788 return;
789 }
790 spin_lock(&sclp_lock); 790 spin_lock(&sclp_lock);
791 if (sclp_running_state == sclp_running_state_running) { 791 if (sclp_running_state == sclp_running_state_running) {
792 sclp_init_req.status = SCLP_REQ_DONE; 792 sclp_init_req.status = SCLP_REQ_DONE;
@@ -883,8 +883,6 @@ sclp_init(void)
883 unsigned long flags; 883 unsigned long flags;
884 int rc; 884 int rc;
885 885
886 if (!MACHINE_HAS_SCLP)
887 return -ENODEV;
888 spin_lock_irqsave(&sclp_lock, flags); 886 spin_lock_irqsave(&sclp_lock, flags);
889 /* Check for previous or running initialization */ 887 /* Check for previous or running initialization */
890 if (sclp_init_state != sclp_init_state_uninitialized) { 888 if (sclp_init_state != sclp_init_state_uninitialized) {
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index b5c23396f8fe..0c2b77493db4 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -11,6 +11,9 @@
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/string.h> 13#include <linux/string.h>
14#include <linux/mm.h>
15#include <linux/mmzone.h>
16#include <linux/memory.h>
14#include <asm/chpid.h> 17#include <asm/chpid.h>
15#include <asm/sclp.h> 18#include <asm/sclp.h>
16#include "sclp.h" 19#include "sclp.h"
@@ -43,6 +46,8 @@ static int __initdata early_read_info_sccb_valid;
43 46
44u64 sclp_facilities; 47u64 sclp_facilities;
45static u8 sclp_fac84; 48static u8 sclp_fac84;
49static unsigned long long rzm;
50static unsigned long long rnmax;
46 51
47static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) 52static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
48{ 53{
@@ -62,7 +67,7 @@ out:
62 return rc; 67 return rc;
63} 68}
64 69
65void __init sclp_read_info_early(void) 70static void __init sclp_read_info_early(void)
66{ 71{
67 int rc; 72 int rc;
68 int i; 73 int i;
@@ -92,34 +97,33 @@ void __init sclp_read_info_early(void)
92 97
93void __init sclp_facilities_detect(void) 98void __init sclp_facilities_detect(void)
94{ 99{
100 struct read_info_sccb *sccb;
101
102 sclp_read_info_early();
95 if (!early_read_info_sccb_valid) 103 if (!early_read_info_sccb_valid)
96 return; 104 return;
97 sclp_facilities = early_read_info_sccb.facilities; 105
98 sclp_fac84 = early_read_info_sccb.fac84; 106 sccb = &early_read_info_sccb;
107 sclp_facilities = sccb->facilities;
108 sclp_fac84 = sccb->fac84;
109 rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
110 rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
111 rzm <<= 20;
99} 112}
100 113
101unsigned long long __init sclp_memory_detect(void) 114unsigned long long sclp_get_rnmax(void)
102{ 115{
103 unsigned long long memsize; 116 return rnmax;
104 struct read_info_sccb *sccb; 117}
105 118
106 if (!early_read_info_sccb_valid) 119unsigned long long sclp_get_rzm(void)
107 return 0; 120{
108 sccb = &early_read_info_sccb; 121 return rzm;
109 if (sccb->rnsize)
110 memsize = sccb->rnsize << 20;
111 else
112 memsize = sccb->rnsize2 << 20;
113 if (sccb->rnmax)
114 memsize *= sccb->rnmax;
115 else
116 memsize *= sccb->rnmax2;
117 return memsize;
118} 122}
119 123
120/* 124/*
121 * This function will be called after sclp_memory_detect(), which gets called 125 * This function will be called after sclp_facilities_detect(), which gets
122 * early from early.c code. Therefore the sccb should have valid contents. 126 * called from early.c code. Therefore the sccb should have valid contents.
123 */ 127 */
124void __init sclp_get_ipl_info(struct sclp_ipl_info *info) 128void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
125{ 129{
@@ -278,6 +282,305 @@ int sclp_cpu_deconfigure(u8 cpu)
278 return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8); 282 return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
279} 283}
280 284
285#ifdef CONFIG_MEMORY_HOTPLUG
286
287static DEFINE_MUTEX(sclp_mem_mutex);
288static LIST_HEAD(sclp_mem_list);
289static u8 sclp_max_storage_id;
290static unsigned long sclp_storage_ids[256 / BITS_PER_LONG];
291
292struct memory_increment {
293 struct list_head list;
294 u16 rn;
295 int standby;
296 int usecount;
297};
298
299struct assign_storage_sccb {
300 struct sccb_header header;
301 u16 rn;
302} __packed;
303
304static unsigned long long rn2addr(u16 rn)
305{
306 return (unsigned long long) (rn - 1) * rzm;
307}
308
309static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
310{
311 struct assign_storage_sccb *sccb;
312 int rc;
313
314 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
315 if (!sccb)
316 return -ENOMEM;
317 sccb->header.length = PAGE_SIZE;
318 sccb->rn = rn;
319 rc = do_sync_request(cmd, sccb);
320 if (rc)
321 goto out;
322 switch (sccb->header.response_code) {
323 case 0x0020:
324 case 0x0120:
325 break;
326 default:
327 rc = -EIO;
328 break;
329 }
330out:
331 free_page((unsigned long) sccb);
332 return rc;
333}
334
335static int sclp_assign_storage(u16 rn)
336{
337 return do_assign_storage(0x000d0001, rn);
338}
339
340static int sclp_unassign_storage(u16 rn)
341{
342 return do_assign_storage(0x000c0001, rn);
343}
344
345struct attach_storage_sccb {
346 struct sccb_header header;
347 u16 :16;
348 u16 assigned;
349 u32 :32;
350 u32 entries[0];
351} __packed;
352
353static int sclp_attach_storage(u8 id)
354{
355 struct attach_storage_sccb *sccb;
356 int rc;
357 int i;
358
359 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
360 if (!sccb)
361 return -ENOMEM;
362 sccb->header.length = PAGE_SIZE;
363 rc = do_sync_request(0x00080001 | id << 8, sccb);
364 if (rc)
365 goto out;
366 switch (sccb->header.response_code) {
367 case 0x0020:
368 set_bit(id, sclp_storage_ids);
369 for (i = 0; i < sccb->assigned; i++)
370 sclp_unassign_storage(sccb->entries[i] >> 16);
371 break;
372 default:
373 rc = -EIO;
374 break;
375 }
376out:
377 free_page((unsigned long) sccb);
378 return rc;
379}
380
381static int sclp_mem_change_state(unsigned long start, unsigned long size,
382 int online)
383{
384 struct memory_increment *incr;
385 unsigned long long istart;
386 int rc = 0;
387
388 list_for_each_entry(incr, &sclp_mem_list, list) {
389 istart = rn2addr(incr->rn);
390 if (start + size - 1 < istart)
391 break;
392 if (start > istart + rzm - 1)
393 continue;
394 if (online) {
395 if (incr->usecount++)
396 continue;
397 /*
398 * Don't break the loop if one assign fails. Loop may
399 * be walked again on CANCEL and we can't save
400 * information if state changed before or not.
401 * So continue and increase usecount for all increments.
402 */
403 rc |= sclp_assign_storage(incr->rn);
404 } else {
405 if (--incr->usecount)
406 continue;
407 sclp_unassign_storage(incr->rn);
408 }
409 }
410 return rc ? -EIO : 0;
411}
412
413static int sclp_mem_notifier(struct notifier_block *nb,
414 unsigned long action, void *data)
415{
416 unsigned long start, size;
417 struct memory_notify *arg;
418 unsigned char id;
419 int rc = 0;
420
421 arg = data;
422 start = arg->start_pfn << PAGE_SHIFT;
423 size = arg->nr_pages << PAGE_SHIFT;
424 mutex_lock(&sclp_mem_mutex);
425 for (id = 0; id <= sclp_max_storage_id; id++)
426 if (!test_bit(id, sclp_storage_ids))
427 sclp_attach_storage(id);
428 switch (action) {
429 case MEM_ONLINE:
430 break;
431 case MEM_GOING_ONLINE:
432 rc = sclp_mem_change_state(start, size, 1);
433 break;
434 case MEM_CANCEL_ONLINE:
435 sclp_mem_change_state(start, size, 0);
436 break;
437 default:
438 rc = -EINVAL;
439 break;
440 }
441 mutex_unlock(&sclp_mem_mutex);
442 return rc ? NOTIFY_BAD : NOTIFY_OK;
443}
444
445static struct notifier_block sclp_mem_nb = {
446 .notifier_call = sclp_mem_notifier,
447};
448
449static void __init add_memory_merged(u16 rn)
450{
451 static u16 first_rn, num;
452 unsigned long long start, size;
453
454 if (rn && first_rn && (first_rn + num == rn)) {
455 num++;
456 return;
457 }
458 if (!first_rn)
459 goto skip_add;
460 start = rn2addr(first_rn);
461 size = (unsigned long long ) num * rzm;
462 if (start >= VMEM_MAX_PHYS)
463 goto skip_add;
464 if (start + size > VMEM_MAX_PHYS)
465 size = VMEM_MAX_PHYS - start;
466 add_memory(0, start, size);
467skip_add:
468 first_rn = rn;
469 num = 1;
470}
471
472static void __init sclp_add_standby_memory(void)
473{
474 struct memory_increment *incr;
475
476 list_for_each_entry(incr, &sclp_mem_list, list)
477 if (incr->standby)
478 add_memory_merged(incr->rn);
479 add_memory_merged(0);
480}
481
482static void __init insert_increment(u16 rn, int standby, int assigned)
483{
484 struct memory_increment *incr, *new_incr;
485 struct list_head *prev;
486 u16 last_rn;
487
488 new_incr = kzalloc(sizeof(*new_incr), GFP_KERNEL);
489 if (!new_incr)
490 return;
491 new_incr->rn = rn;
492 new_incr->standby = standby;
493 last_rn = 0;
494 prev = &sclp_mem_list;
495 list_for_each_entry(incr, &sclp_mem_list, list) {
496 if (assigned && incr->rn > rn)
497 break;
498 if (!assigned && incr->rn - last_rn > 1)
499 break;
500 last_rn = incr->rn;
501 prev = &incr->list;
502 }
503 if (!assigned)
504 new_incr->rn = last_rn + 1;
505 if (new_incr->rn > rnmax) {
506 kfree(new_incr);
507 return;
508 }
509 list_add(&new_incr->list, prev);
510}
511
512struct read_storage_sccb {
513 struct sccb_header header;
514 u16 max_id;
515 u16 assigned;
516 u16 standby;
517 u16 :16;
518 u32 entries[0];
519} __packed;
520
521static int __init sclp_detect_standby_memory(void)
522{
523 struct read_storage_sccb *sccb;
524 int i, id, assigned, rc;
525
526 if (!early_read_info_sccb_valid)
527 return 0;
528 if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
529 return 0;
530 rc = -ENOMEM;
531 sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
532 if (!sccb)
533 goto out;
534 assigned = 0;
535 for (id = 0; id <= sclp_max_storage_id; id++) {
536 memset(sccb, 0, PAGE_SIZE);
537 sccb->header.length = PAGE_SIZE;
538 rc = do_sync_request(0x00040001 | id << 8, sccb);
539 if (rc)
540 goto out;
541 switch (sccb->header.response_code) {
542 case 0x0010:
543 set_bit(id, sclp_storage_ids);
544 for (i = 0; i < sccb->assigned; i++) {
545 if (!sccb->entries[i])
546 continue;
547 assigned++;
548 insert_increment(sccb->entries[i] >> 16, 0, 1);
549 }
550 break;
551 case 0x0310:
552 break;
553 case 0x0410:
554 for (i = 0; i < sccb->assigned; i++) {
555 if (!sccb->entries[i])
556 continue;
557 assigned++;
558 insert_increment(sccb->entries[i] >> 16, 1, 1);
559 }
560 break;
561 default:
562 rc = -EIO;
563 break;
564 }
565 if (!rc)
566 sclp_max_storage_id = sccb->max_id;
567 }
568 if (rc || list_empty(&sclp_mem_list))
569 goto out;
570 for (i = 1; i <= rnmax - assigned; i++)
571 insert_increment(0, 1, 0);
572 rc = register_memory_notifier(&sclp_mem_nb);
573 if (rc)
574 goto out;
575 sclp_add_standby_memory();
576out:
577 free_page((unsigned long) sccb);
578 return rc;
579}
580__initcall(sclp_detect_standby_memory);
581
582#endif /* CONFIG_MEMORY_HOTPLUG */
583
281/* 584/*
282 * Channel path configuration related functions. 585 * Channel path configuration related functions.
283 */ 586 */
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index ead1043d788e..7e619c534bf4 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -14,14 +14,13 @@
14#include <linux/timer.h> 14#include <linux/timer.h>
15#include <linux/jiffies.h> 15#include <linux/jiffies.h>
16#include <linux/bootmem.h> 16#include <linux/bootmem.h>
17#include <linux/termios.h>
17#include <linux/err.h> 18#include <linux/err.h>
18 19
19#include "sclp.h" 20#include "sclp.h"
20#include "sclp_rw.h" 21#include "sclp_rw.h"
21#include "sclp_tty.h" 22#include "sclp_tty.h"
22 23
23#define SCLP_CON_PRINT_HEADER "sclp console driver: "
24
25#define sclp_console_major 4 /* TTYAUX_MAJOR */ 24#define sclp_console_major 4 /* TTYAUX_MAJOR */
26#define sclp_console_minor 64 25#define sclp_console_minor 64
27#define sclp_console_name "ttyS" 26#define sclp_console_name "ttyS"
@@ -222,8 +221,6 @@ sclp_console_init(void)
222 INIT_LIST_HEAD(&sclp_con_pages); 221 INIT_LIST_HEAD(&sclp_con_pages);
223 for (i = 0; i < MAX_CONSOLE_PAGES; i++) { 222 for (i = 0; i < MAX_CONSOLE_PAGES; i++) {
224 page = alloc_bootmem_low_pages(PAGE_SIZE); 223 page = alloc_bootmem_low_pages(PAGE_SIZE);
225 if (page == NULL)
226 return -ENOMEM;
227 list_add_tail((struct list_head *) page, &sclp_con_pages); 224 list_add_tail((struct list_head *) page, &sclp_con_pages);
228 } 225 }
229 INIT_LIST_HEAD(&sclp_con_outqueue); 226 INIT_LIST_HEAD(&sclp_con_outqueue);
diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c
index ad05a87bc480..fff4ff485d9b 100644
--- a/drivers/s390/char/sclp_config.c
+++ b/drivers/s390/char/sclp_config.c
@@ -8,6 +8,7 @@
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/cpu.h> 10#include <linux/cpu.h>
11#include <linux/kthread.h>
11#include <linux/sysdev.h> 12#include <linux/sysdev.h>
12#include <linux/workqueue.h> 13#include <linux/workqueue.h>
13#include <asm/smp.h> 14#include <asm/smp.h>
@@ -40,9 +41,19 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
40 put_online_cpus(); 41 put_online_cpus();
41} 42}
42 43
43static void __ref sclp_cpu_change_notify(struct work_struct *work) 44static int sclp_cpu_kthread(void *data)
44{ 45{
45 smp_rescan_cpus(); 46 smp_rescan_cpus();
47 return 0;
48}
49
50static void __ref sclp_cpu_change_notify(struct work_struct *work)
51{
52 /* Can't call smp_rescan_cpus() from workqueue context since it may
53 * deadlock in case of cpu hotplug. So we have to create a kernel
54 * thread in order to call it.
55 */
56 kthread_run(sclp_cpu_kthread, NULL, "cpu_rescan");
46} 57}
47 58
48static void sclp_conf_receiver_fn(struct evbuf_header *evbuf) 59static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
@@ -74,10 +85,8 @@ static int __init sclp_conf_init(void)
74 INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify); 85 INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
75 86
76 rc = sclp_register(&sclp_conf_register); 87 rc = sclp_register(&sclp_conf_register);
77 if (rc) { 88 if (rc)
78 printk(KERN_ERR TAG "failed to register (%d).\n", rc);
79 return rc; 89 return rc;
80 }
81 90
82 if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) { 91 if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) {
83 printk(KERN_WARNING TAG "no configuration management.\n"); 92 printk(KERN_WARNING TAG "no configuration management.\n");
diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c
index 9f37456222e9..d887bd261d28 100644
--- a/drivers/s390/char/sclp_cpi_sys.c
+++ b/drivers/s390/char/sclp_cpi_sys.c
@@ -27,6 +27,8 @@
27#define CPI_LENGTH_NAME 8 27#define CPI_LENGTH_NAME 8
28#define CPI_LENGTH_LEVEL 16 28#define CPI_LENGTH_LEVEL 16
29 29
30static DEFINE_MUTEX(sclp_cpi_mutex);
31
30struct cpi_evbuf { 32struct cpi_evbuf {
31 struct evbuf_header header; 33 struct evbuf_header header;
32 u8 id_format; 34 u8 id_format;
@@ -124,21 +126,15 @@ static int cpi_req(void)
124 int response; 126 int response;
125 127
126 rc = sclp_register(&sclp_cpi_event); 128 rc = sclp_register(&sclp_cpi_event);
127 if (rc) { 129 if (rc)
128 printk(KERN_WARNING "cpi: could not register "
129 "to hardware console.\n");
130 goto out; 130 goto out;
131 }
132 if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { 131 if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) {
133 printk(KERN_WARNING "cpi: no control program "
134 "identification support\n");
135 rc = -EOPNOTSUPP; 132 rc = -EOPNOTSUPP;
136 goto out_unregister; 133 goto out_unregister;
137 } 134 }
138 135
139 req = cpi_prepare_req(); 136 req = cpi_prepare_req();
140 if (IS_ERR(req)) { 137 if (IS_ERR(req)) {
141 printk(KERN_WARNING "cpi: could not allocate request\n");
142 rc = PTR_ERR(req); 138 rc = PTR_ERR(req);
143 goto out_unregister; 139 goto out_unregister;
144 } 140 }
@@ -148,10 +144,8 @@ static int cpi_req(void)
148 144
149 /* Add request to sclp queue */ 145 /* Add request to sclp queue */
150 rc = sclp_add_request(req); 146 rc = sclp_add_request(req);
151 if (rc) { 147 if (rc)
152 printk(KERN_WARNING "cpi: could not start request\n");
153 goto out_free_req; 148 goto out_free_req;
154 }
155 149
156 wait_for_completion(&completion); 150 wait_for_completion(&completion);
157 151
@@ -223,7 +217,12 @@ static void set_string(char *attr, const char *value)
223static ssize_t system_name_show(struct kobject *kobj, 217static ssize_t system_name_show(struct kobject *kobj,
224 struct kobj_attribute *attr, char *page) 218 struct kobj_attribute *attr, char *page)
225{ 219{
226 return snprintf(page, PAGE_SIZE, "%s\n", system_name); 220 int rc;
221
222 mutex_lock(&sclp_cpi_mutex);
223 rc = snprintf(page, PAGE_SIZE, "%s\n", system_name);
224 mutex_unlock(&sclp_cpi_mutex);
225 return rc;
227} 226}
228 227
229static ssize_t system_name_store(struct kobject *kobj, 228static ssize_t system_name_store(struct kobject *kobj,
@@ -237,7 +236,9 @@ static ssize_t system_name_store(struct kobject *kobj,
237 if (rc) 236 if (rc)
238 return rc; 237 return rc;
239 238
239 mutex_lock(&sclp_cpi_mutex);
240 set_string(system_name, buf); 240 set_string(system_name, buf);
241 mutex_unlock(&sclp_cpi_mutex);
241 242
242 return len; 243 return len;
243} 244}
@@ -248,7 +249,12 @@ static struct kobj_attribute system_name_attr =
248static ssize_t sysplex_name_show(struct kobject *kobj, 249static ssize_t sysplex_name_show(struct kobject *kobj,
249 struct kobj_attribute *attr, char *page) 250 struct kobj_attribute *attr, char *page)
250{ 251{
251 return snprintf(page, PAGE_SIZE, "%s\n", sysplex_name); 252 int rc;
253
254 mutex_lock(&sclp_cpi_mutex);
255 rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name);
256 mutex_unlock(&sclp_cpi_mutex);
257 return rc;
252} 258}
253 259
254static ssize_t sysplex_name_store(struct kobject *kobj, 260static ssize_t sysplex_name_store(struct kobject *kobj,
@@ -262,7 +268,9 @@ static ssize_t sysplex_name_store(struct kobject *kobj,
262 if (rc) 268 if (rc)
263 return rc; 269 return rc;
264 270
271 mutex_lock(&sclp_cpi_mutex);
265 set_string(sysplex_name, buf); 272 set_string(sysplex_name, buf);
273 mutex_unlock(&sclp_cpi_mutex);
266 274
267 return len; 275 return len;
268} 276}
@@ -273,7 +281,12 @@ static struct kobj_attribute sysplex_name_attr =
273static ssize_t system_type_show(struct kobject *kobj, 281static ssize_t system_type_show(struct kobject *kobj,
274 struct kobj_attribute *attr, char *page) 282 struct kobj_attribute *attr, char *page)
275{ 283{
276 return snprintf(page, PAGE_SIZE, "%s\n", system_type); 284 int rc;
285
286 mutex_lock(&sclp_cpi_mutex);
287 rc = snprintf(page, PAGE_SIZE, "%s\n", system_type);
288 mutex_unlock(&sclp_cpi_mutex);
289 return rc;
277} 290}
278 291
279static ssize_t system_type_store(struct kobject *kobj, 292static ssize_t system_type_store(struct kobject *kobj,
@@ -287,7 +300,9 @@ static ssize_t system_type_store(struct kobject *kobj,
287 if (rc) 300 if (rc)
288 return rc; 301 return rc;
289 302
303 mutex_lock(&sclp_cpi_mutex);
290 set_string(system_type, buf); 304 set_string(system_type, buf);
305 mutex_unlock(&sclp_cpi_mutex);
291 306
292 return len; 307 return len;
293} 308}
@@ -298,8 +313,11 @@ static struct kobj_attribute system_type_attr =
298static ssize_t system_level_show(struct kobject *kobj, 313static ssize_t system_level_show(struct kobject *kobj,
299 struct kobj_attribute *attr, char *page) 314 struct kobj_attribute *attr, char *page)
300{ 315{
301 unsigned long long level = system_level; 316 unsigned long long level;
302 317
318 mutex_lock(&sclp_cpi_mutex);
319 level = system_level;
320 mutex_unlock(&sclp_cpi_mutex);
303 return snprintf(page, PAGE_SIZE, "%#018llx\n", level); 321 return snprintf(page, PAGE_SIZE, "%#018llx\n", level);
304} 322}
305 323
@@ -320,8 +338,9 @@ static ssize_t system_level_store(struct kobject *kobj,
320 if (*endp) 338 if (*endp)
321 return -EINVAL; 339 return -EINVAL;
322 340
341 mutex_lock(&sclp_cpi_mutex);
323 system_level = level; 342 system_level = level;
324 343 mutex_unlock(&sclp_cpi_mutex);
325 return len; 344 return len;
326} 345}
327 346
@@ -334,7 +353,9 @@ static ssize_t set_store(struct kobject *kobj,
334{ 353{
335 int rc; 354 int rc;
336 355
356 mutex_lock(&sclp_cpi_mutex);
337 rc = cpi_req(); 357 rc = cpi_req();
358 mutex_unlock(&sclp_cpi_mutex);
338 if (rc) 359 if (rc)
339 return rc; 360 return rc;
340 361
@@ -373,12 +394,16 @@ int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type,
373 if (rc) 394 if (rc)
374 return rc; 395 return rc;
375 396
397 mutex_lock(&sclp_cpi_mutex);
376 set_string(system_name, system); 398 set_string(system_name, system);
377 set_string(sysplex_name, sysplex); 399 set_string(sysplex_name, sysplex);
378 set_string(system_type, type); 400 set_string(system_type, type);
379 system_level = level; 401 system_level = level;
380 402
381 return cpi_req(); 403 rc = cpi_req();
404 mutex_unlock(&sclp_cpi_mutex);
405
406 return rc;
382} 407}
383EXPORT_SYMBOL(sclp_cpi_set_data); 408EXPORT_SYMBOL(sclp_cpi_set_data);
384 409
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 45ff25e787cb..84c191c1cd62 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -51,13 +51,7 @@ static struct sclp_register sclp_quiesce_event = {
51static int __init 51static int __init
52sclp_quiesce_init(void) 52sclp_quiesce_init(void)
53{ 53{
54 int rc; 54 return sclp_register(&sclp_quiesce_event);
55
56 rc = sclp_register(&sclp_quiesce_event);
57 if (rc)
58 printk(KERN_WARNING "sclp: could not register quiesce handler "
59 "(rc=%d)\n", rc);
60 return rc;
61} 55}
62 56
63module_init(sclp_quiesce_init); 57module_init(sclp_quiesce_init);
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index da09781b32f7..710af42603f8 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -19,8 +19,6 @@
19#include "sclp.h" 19#include "sclp.h"
20#include "sclp_rw.h" 20#include "sclp_rw.h"
21 21
22#define SCLP_RW_PRINT_HEADER "sclp low level driver: "
23
24/* 22/*
25 * The room for the SCCB (only for writing) is not equal to a pages size 23 * The room for the SCCB (only for writing) is not equal to a pages size
26 * (as it is specified as the maximum size in the SCLP documentation) 24 * (as it is specified as the maximum size in the SCLP documentation)
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c
index 1c064976b32b..8b854857ba07 100644
--- a/drivers/s390/char/sclp_sdias.c
+++ b/drivers/s390/char/sclp_sdias.c
@@ -239,10 +239,8 @@ int __init sclp_sdias_init(void)
239 debug_register_view(sdias_dbf, &debug_sprintf_view); 239 debug_register_view(sdias_dbf, &debug_sprintf_view);
240 debug_set_level(sdias_dbf, 6); 240 debug_set_level(sdias_dbf, 6);
241 rc = sclp_register(&sclp_sdias_register); 241 rc = sclp_register(&sclp_sdias_register);
242 if (rc) { 242 if (rc)
243 ERROR_MSG("sclp register failed\n");
244 return rc; 243 return rc;
245 }
246 init_waitqueue_head(&sdias_wq); 244 init_waitqueue_head(&sdias_wq);
247 TRACE("init done\n"); 245 TRACE("init done\n");
248 return 0; 246 return 0;
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 40b11521cd20..434ba04b1309 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -13,7 +13,6 @@
13#include <linux/tty.h> 13#include <linux/tty.h>
14#include <linux/tty_driver.h> 14#include <linux/tty_driver.h>
15#include <linux/tty_flip.h> 15#include <linux/tty_flip.h>
16#include <linux/wait.h>
17#include <linux/slab.h> 16#include <linux/slab.h>
18#include <linux/err.h> 17#include <linux/err.h>
19#include <linux/init.h> 18#include <linux/init.h>
@@ -25,8 +24,6 @@
25#include "sclp_rw.h" 24#include "sclp_rw.h"
26#include "sclp_tty.h" 25#include "sclp_tty.h"
27 26
28#define SCLP_TTY_PRINT_HEADER "sclp tty driver: "
29
30/* 27/*
31 * size of a buffer that collects single characters coming in 28 * size of a buffer that collects single characters coming in
32 * via sclp_tty_put_char() 29 * via sclp_tty_put_char()
@@ -50,8 +47,6 @@ static int sclp_tty_buffer_count;
50static struct sclp_buffer *sclp_ttybuf; 47static struct sclp_buffer *sclp_ttybuf;
51/* Timer for delayed output of console messages. */ 48/* Timer for delayed output of console messages. */
52static struct timer_list sclp_tty_timer; 49static struct timer_list sclp_tty_timer;
53/* Waitqueue to wait for buffers to get empty. */
54static wait_queue_head_t sclp_tty_waitq;
55 50
56static struct tty_struct *sclp_tty; 51static struct tty_struct *sclp_tty;
57static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; 52static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
@@ -59,19 +54,11 @@ static unsigned short int sclp_tty_chars_count;
59 54
60struct tty_driver *sclp_tty_driver; 55struct tty_driver *sclp_tty_driver;
61 56
62static struct sclp_ioctls sclp_ioctls; 57static int sclp_tty_tolower;
63static struct sclp_ioctls sclp_ioctls_init = 58static int sclp_tty_columns = 80;
64{ 59
65 8, /* 1 hor. tab. = 8 spaces */ 60#define SPACES_PER_TAB 8
66 0, /* no echo of input by this driver */ 61#define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */
67 80, /* 80 characters/line */
68 1, /* write after 1/10 s without final new line */
69 MAX_KMEM_PAGES, /* quick fix: avoid __alloc_pages */
70 MAX_KMEM_PAGES, /* take 32/64 pages from kernel memory, */
71 0, /* do not convert to lower case */
72 0x6c /* to seprate upper and lower case */
73 /* ('%' in EBCDIC) */
74};
75 62
76/* This routine is called whenever we try to open a SCLP terminal. */ 63/* This routine is called whenever we try to open a SCLP terminal. */
77static int 64static int
@@ -92,136 +79,6 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
92 sclp_tty = NULL; 79 sclp_tty = NULL;
93} 80}
94 81
95/* execute commands to control the i/o behaviour of the SCLP tty at runtime */
96static int
97sclp_tty_ioctl(struct tty_struct *tty, struct file * file,
98 unsigned int cmd, unsigned long arg)
99{
100 unsigned long flags;
101 unsigned int obuf;
102 int check;
103 int rc;
104
105 if (tty->flags & (1 << TTY_IO_ERROR))
106 return -EIO;
107 rc = 0;
108 check = 0;
109 switch (cmd) {
110 case TIOCSCLPSHTAB:
111 /* set width of horizontal tab */
112 if (get_user(sclp_ioctls.htab, (unsigned short __user *) arg))
113 rc = -EFAULT;
114 else
115 check = 1;
116 break;
117 case TIOCSCLPGHTAB:
118 /* get width of horizontal tab */
119 if (put_user(sclp_ioctls.htab, (unsigned short __user *) arg))
120 rc = -EFAULT;
121 break;
122 case TIOCSCLPSECHO:
123 /* enable/disable echo of input */
124 if (get_user(sclp_ioctls.echo, (unsigned char __user *) arg))
125 rc = -EFAULT;
126 break;
127 case TIOCSCLPGECHO:
128 /* Is echo of input enabled ? */
129 if (put_user(sclp_ioctls.echo, (unsigned char __user *) arg))
130 rc = -EFAULT;
131 break;
132 case TIOCSCLPSCOLS:
133 /* set number of columns for output */
134 if (get_user(sclp_ioctls.columns, (unsigned short __user *) arg))
135 rc = -EFAULT;
136 else
137 check = 1;
138 break;
139 case TIOCSCLPGCOLS:
140 /* get number of columns for output */
141 if (put_user(sclp_ioctls.columns, (unsigned short __user *) arg))
142 rc = -EFAULT;
143 break;
144 case TIOCSCLPSNL:
145 /* enable/disable writing without final new line character */
146 if (get_user(sclp_ioctls.final_nl, (signed char __user *) arg))
147 rc = -EFAULT;
148 break;
149 case TIOCSCLPGNL:
150 /* Is writing without final new line character enabled ? */
151 if (put_user(sclp_ioctls.final_nl, (signed char __user *) arg))
152 rc = -EFAULT;
153 break;
154 case TIOCSCLPSOBUF:
155 /*
156 * set the maximum buffers size for output, will be rounded
157 * up to next 4kB boundary and stored as number of SCCBs
158 * (4kB Buffers) limitation: 256 x 4kB
159 */
160 if (get_user(obuf, (unsigned int __user *) arg) == 0) {
161 if (obuf & 0xFFF)
162 sclp_ioctls.max_sccb = (obuf >> 12) + 1;
163 else
164 sclp_ioctls.max_sccb = (obuf >> 12);
165 } else
166 rc = -EFAULT;
167 break;
168 case TIOCSCLPGOBUF:
169 /* get the maximum buffers size for output */
170 obuf = sclp_ioctls.max_sccb << 12;
171 if (put_user(obuf, (unsigned int __user *) arg))
172 rc = -EFAULT;
173 break;
174 case TIOCSCLPGKBUF:
175 /* get the number of buffers got from kernel at startup */
176 if (put_user(sclp_ioctls.kmem_sccb, (unsigned short __user *) arg))
177 rc = -EFAULT;
178 break;
179 case TIOCSCLPSCASE:
180 /* enable/disable conversion from upper to lower case */
181 if (get_user(sclp_ioctls.tolower, (unsigned char __user *) arg))
182 rc = -EFAULT;
183 break;
184 case TIOCSCLPGCASE:
185 /* Is conversion from upper to lower case of input enabled? */
186 if (put_user(sclp_ioctls.tolower, (unsigned char __user *) arg))
187 rc = -EFAULT;
188 break;
189 case TIOCSCLPSDELIM:
190 /*
191 * set special character used for separating upper and
192 * lower case, 0x00 disables this feature
193 */
194 if (get_user(sclp_ioctls.delim, (unsigned char __user *) arg))
195 rc = -EFAULT;
196 break;
197 case TIOCSCLPGDELIM:
198 /*
199 * get special character used for separating upper and
200 * lower case, 0x00 disables this feature
201 */
202 if (put_user(sclp_ioctls.delim, (unsigned char __user *) arg))
203 rc = -EFAULT;
204 break;
205 case TIOCSCLPSINIT:
206 /* set initial (default) sclp ioctls */
207 sclp_ioctls = sclp_ioctls_init;
208 check = 1;
209 break;
210 default:
211 rc = -ENOIOCTLCMD;
212 break;
213 }
214 if (check) {
215 spin_lock_irqsave(&sclp_tty_lock, flags);
216 if (sclp_ttybuf != NULL) {
217 sclp_set_htab(sclp_ttybuf, sclp_ioctls.htab);
218 sclp_set_columns(sclp_ttybuf, sclp_ioctls.columns);
219 }
220 spin_unlock_irqrestore(&sclp_tty_lock, flags);
221 }
222 return rc;
223}
224
225/* 82/*
226 * This routine returns the numbers of characters the tty driver 83 * This routine returns the numbers of characters the tty driver
227 * will accept for queuing to be written. This number is subject 84 * will accept for queuing to be written. This number is subject
@@ -268,7 +125,6 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
268 struct sclp_buffer, list); 125 struct sclp_buffer, list);
269 spin_unlock_irqrestore(&sclp_tty_lock, flags); 126 spin_unlock_irqrestore(&sclp_tty_lock, flags);
270 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); 127 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
271 wake_up(&sclp_tty_waitq);
272 /* check if the tty needs a wake up call */ 128 /* check if the tty needs a wake up call */
273 if (sclp_tty != NULL) { 129 if (sclp_tty != NULL) {
274 tty_wakeup(sclp_tty); 130 tty_wakeup(sclp_tty);
@@ -316,37 +172,37 @@ sclp_tty_timeout(unsigned long data)
316/* 172/*
317 * Write a string to the sclp tty. 173 * Write a string to the sclp tty.
318 */ 174 */
319static void 175static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail)
320sclp_tty_write_string(const unsigned char *str, int count)
321{ 176{
322 unsigned long flags; 177 unsigned long flags;
323 void *page; 178 void *page;
324 int written; 179 int written;
180 int overall_written;
325 struct sclp_buffer *buf; 181 struct sclp_buffer *buf;
326 182
327 if (count <= 0) 183 if (count <= 0)
328 return; 184 return 0;
185 overall_written = 0;
329 spin_lock_irqsave(&sclp_tty_lock, flags); 186 spin_lock_irqsave(&sclp_tty_lock, flags);
330 do { 187 do {
331 /* Create a sclp output buffer if none exists yet */ 188 /* Create a sclp output buffer if none exists yet */
332 if (sclp_ttybuf == NULL) { 189 if (sclp_ttybuf == NULL) {
333 while (list_empty(&sclp_tty_pages)) { 190 while (list_empty(&sclp_tty_pages)) {
334 spin_unlock_irqrestore(&sclp_tty_lock, flags); 191 spin_unlock_irqrestore(&sclp_tty_lock, flags);
335 if (in_interrupt()) 192 if (may_fail)
336 sclp_sync_wait(); 193 goto out;
337 else 194 else
338 wait_event(sclp_tty_waitq, 195 sclp_sync_wait();
339 !list_empty(&sclp_tty_pages));
340 spin_lock_irqsave(&sclp_tty_lock, flags); 196 spin_lock_irqsave(&sclp_tty_lock, flags);
341 } 197 }
342 page = sclp_tty_pages.next; 198 page = sclp_tty_pages.next;
343 list_del((struct list_head *) page); 199 list_del((struct list_head *) page);
344 sclp_ttybuf = sclp_make_buffer(page, 200 sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns,
345 sclp_ioctls.columns, 201 SPACES_PER_TAB);
346 sclp_ioctls.htab);
347 } 202 }
348 /* try to write the string to the current output buffer */ 203 /* try to write the string to the current output buffer */
349 written = sclp_write(sclp_ttybuf, str, count); 204 written = sclp_write(sclp_ttybuf, str, count);
205 overall_written += written;
350 if (written == count) 206 if (written == count)
351 break; 207 break;
352 /* 208 /*
@@ -363,27 +219,17 @@ sclp_tty_write_string(const unsigned char *str, int count)
363 count -= written; 219 count -= written;
364 } while (count > 0); 220 } while (count > 0);
365 /* Setup timer to output current console buffer after 1/10 second */ 221 /* Setup timer to output current console buffer after 1/10 second */
366 if (sclp_ioctls.final_nl) { 222 if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) &&
367 if (sclp_ttybuf != NULL && 223 !timer_pending(&sclp_tty_timer)) {
368 sclp_chars_in_buffer(sclp_ttybuf) != 0 && 224 init_timer(&sclp_tty_timer);
369 !timer_pending(&sclp_tty_timer)) { 225 sclp_tty_timer.function = sclp_tty_timeout;
370 init_timer(&sclp_tty_timer); 226 sclp_tty_timer.data = 0UL;
371 sclp_tty_timer.function = sclp_tty_timeout; 227 sclp_tty_timer.expires = jiffies + HZ/10;
372 sclp_tty_timer.data = 0UL; 228 add_timer(&sclp_tty_timer);
373 sclp_tty_timer.expires = jiffies + HZ/10;
374 add_timer(&sclp_tty_timer);
375 }
376 } else {
377 if (sclp_ttybuf != NULL &&
378 sclp_chars_in_buffer(sclp_ttybuf) != 0) {
379 buf = sclp_ttybuf;
380 sclp_ttybuf = NULL;
381 spin_unlock_irqrestore(&sclp_tty_lock, flags);
382 __sclp_ttybuf_emit(buf);
383 spin_lock_irqsave(&sclp_tty_lock, flags);
384 }
385 } 229 }
386 spin_unlock_irqrestore(&sclp_tty_lock, flags); 230 spin_unlock_irqrestore(&sclp_tty_lock, flags);
231out:
232 return overall_written;
387} 233}
388 234
389/* 235/*
@@ -395,11 +241,10 @@ static int
395sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) 241sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
396{ 242{
397 if (sclp_tty_chars_count > 0) { 243 if (sclp_tty_chars_count > 0) {
398 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); 244 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
399 sclp_tty_chars_count = 0; 245 sclp_tty_chars_count = 0;
400 } 246 }
401 sclp_tty_write_string(buf, count); 247 return sclp_tty_write_string(buf, count, 1);
402 return count;
403} 248}
404 249
405/* 250/*
@@ -417,9 +262,10 @@ sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
417{ 262{
418 sclp_tty_chars[sclp_tty_chars_count++] = ch; 263 sclp_tty_chars[sclp_tty_chars_count++] = ch;
419 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { 264 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
420 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); 265 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
421 sclp_tty_chars_count = 0; 266 sclp_tty_chars_count = 0;
422 } return 1; 267 }
268 return 1;
423} 269}
424 270
425/* 271/*
@@ -430,7 +276,7 @@ static void
430sclp_tty_flush_chars(struct tty_struct *tty) 276sclp_tty_flush_chars(struct tty_struct *tty)
431{ 277{
432 if (sclp_tty_chars_count > 0) { 278 if (sclp_tty_chars_count > 0) {
433 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); 279 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
434 sclp_tty_chars_count = 0; 280 sclp_tty_chars_count = 0;
435 } 281 }
436} 282}
@@ -469,7 +315,7 @@ static void
469sclp_tty_flush_buffer(struct tty_struct *tty) 315sclp_tty_flush_buffer(struct tty_struct *tty)
470{ 316{
471 if (sclp_tty_chars_count > 0) { 317 if (sclp_tty_chars_count > 0) {
472 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); 318 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
473 sclp_tty_chars_count = 0; 319 sclp_tty_chars_count = 0;
474 } 320 }
475} 321}
@@ -517,9 +363,7 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
517 * modifiy original string, 363 * modifiy original string,
518 * returns length of resulting string 364 * returns length of resulting string
519 */ 365 */
520static int 366static int sclp_switch_cases(unsigned char *buf, int count)
521sclp_switch_cases(unsigned char *buf, int count,
522 unsigned char delim, int tolower)
523{ 367{
524 unsigned char *ip, *op; 368 unsigned char *ip, *op;
525 int toggle; 369 int toggle;
@@ -529,9 +373,9 @@ sclp_switch_cases(unsigned char *buf, int count,
529 ip = op = buf; 373 ip = op = buf;
530 while (count-- > 0) { 374 while (count-- > 0) {
531 /* compare with special character */ 375 /* compare with special character */
532 if (*ip == delim) { 376 if (*ip == CASE_DELIMITER) {
533 /* followed by another special character? */ 377 /* followed by another special character? */
534 if (count && ip[1] == delim) { 378 if (count && ip[1] == CASE_DELIMITER) {
535 /* 379 /*
536 * ... then put a single copy of the special 380 * ... then put a single copy of the special
537 * character to the output string 381 * character to the output string
@@ -550,7 +394,7 @@ sclp_switch_cases(unsigned char *buf, int count,
550 /* not the special character */ 394 /* not the special character */
551 if (toggle) 395 if (toggle)
552 /* but case switching is on */ 396 /* but case switching is on */
553 if (tolower) 397 if (sclp_tty_tolower)
554 /* switch to uppercase */ 398 /* switch to uppercase */
555 *op++ = _ebc_toupper[(int) *ip++]; 399 *op++ = _ebc_toupper[(int) *ip++];
556 else 400 else
@@ -570,30 +414,12 @@ sclp_get_input(unsigned char *start, unsigned char *end)
570 int count; 414 int count;
571 415
572 count = end - start; 416 count = end - start;
573 /* 417 if (sclp_tty_tolower)
574 * if set in ioctl convert EBCDIC to lower case
575 * (modify original input in SCCB)
576 */
577 if (sclp_ioctls.tolower)
578 EBC_TOLOWER(start, count); 418 EBC_TOLOWER(start, count);
579 419 count = sclp_switch_cases(start, count);
580 /*
581 * if set in ioctl find out characters in lower or upper case
582 * (depends on current case) separated by a special character,
583 * works on EBCDIC
584 */
585 if (sclp_ioctls.delim)
586 count = sclp_switch_cases(start, count,
587 sclp_ioctls.delim,
588 sclp_ioctls.tolower);
589
590 /* convert EBCDIC to ASCII (modify original input in SCCB) */ 420 /* convert EBCDIC to ASCII (modify original input in SCCB) */
591 sclp_ebcasc_str(start, count); 421 sclp_ebcasc_str(start, count);
592 422
593 /* if set in ioctl write operators input to console */
594 if (sclp_ioctls.echo)
595 sclp_tty_write(sclp_tty, start, count);
596
597 /* transfer input to high level driver */ 423 /* transfer input to high level driver */
598 sclp_tty_input(start, count); 424 sclp_tty_input(start, count);
599} 425}
@@ -717,7 +543,6 @@ static const struct tty_operations sclp_ops = {
717 .write_room = sclp_tty_write_room, 543 .write_room = sclp_tty_write_room,
718 .chars_in_buffer = sclp_tty_chars_in_buffer, 544 .chars_in_buffer = sclp_tty_chars_in_buffer,
719 .flush_buffer = sclp_tty_flush_buffer, 545 .flush_buffer = sclp_tty_flush_buffer,
720 .ioctl = sclp_tty_ioctl,
721}; 546};
722 547
723static int __init 548static int __init
@@ -736,9 +561,6 @@ sclp_tty_init(void)
736 561
737 rc = sclp_rw_init(); 562 rc = sclp_rw_init();
738 if (rc) { 563 if (rc) {
739 printk(KERN_ERR SCLP_TTY_PRINT_HEADER
740 "could not register tty - "
741 "sclp_rw_init returned %d\n", rc);
742 put_tty_driver(driver); 564 put_tty_driver(driver);
743 return rc; 565 return rc;
744 } 566 }
@@ -754,7 +576,6 @@ sclp_tty_init(void)
754 } 576 }
755 INIT_LIST_HEAD(&sclp_tty_outqueue); 577 INIT_LIST_HEAD(&sclp_tty_outqueue);
756 spin_lock_init(&sclp_tty_lock); 578 spin_lock_init(&sclp_tty_lock);
757 init_waitqueue_head(&sclp_tty_waitq);
758 init_timer(&sclp_tty_timer); 579 init_timer(&sclp_tty_timer);
759 sclp_ttybuf = NULL; 580 sclp_ttybuf = NULL;
760 sclp_tty_buffer_count = 0; 581 sclp_tty_buffer_count = 0;
@@ -763,11 +584,10 @@ sclp_tty_init(void)
763 * save 4 characters for the CPU number 584 * save 4 characters for the CPU number
764 * written at start of each line by VM/CP 585 * written at start of each line by VM/CP
765 */ 586 */
766 sclp_ioctls_init.columns = 76; 587 sclp_tty_columns = 76;
767 /* case input lines to lowercase */ 588 /* case input lines to lowercase */
768 sclp_ioctls_init.tolower = 1; 589 sclp_tty_tolower = 1;
769 } 590 }
770 sclp_ioctls = sclp_ioctls_init;
771 sclp_tty_chars_count = 0; 591 sclp_tty_chars_count = 0;
772 sclp_tty = NULL; 592 sclp_tty = NULL;
773 593
@@ -792,9 +612,6 @@ sclp_tty_init(void)
792 tty_set_operations(driver, &sclp_ops); 612 tty_set_operations(driver, &sclp_ops);
793 rc = tty_register_driver(driver); 613 rc = tty_register_driver(driver);
794 if (rc) { 614 if (rc) {
795 printk(KERN_ERR SCLP_TTY_PRINT_HEADER
796 "could not register tty - "
797 "tty_register_driver returned %d\n", rc);
798 put_tty_driver(driver); 615 put_tty_driver(driver);
799 return rc; 616 return rc;
800 } 617 }
diff --git a/drivers/s390/char/sclp_tty.h b/drivers/s390/char/sclp_tty.h
index 0ce2c1fc5340..4b965b22fecd 100644
--- a/drivers/s390/char/sclp_tty.h
+++ b/drivers/s390/char/sclp_tty.h
@@ -11,61 +11,8 @@
11#ifndef __SCLP_TTY_H__ 11#ifndef __SCLP_TTY_H__
12#define __SCLP_TTY_H__ 12#define __SCLP_TTY_H__
13 13
14#include <linux/ioctl.h>
15#include <linux/termios.h>
16#include <linux/tty_driver.h> 14#include <linux/tty_driver.h>
17 15
18/* This is the type of data structures storing sclp ioctl setting. */
19struct sclp_ioctls {
20 unsigned short htab;
21 unsigned char echo;
22 unsigned short columns;
23 unsigned char final_nl;
24 unsigned short max_sccb;
25 unsigned short kmem_sccb; /* can't be modified at run time */
26 unsigned char tolower;
27 unsigned char delim;
28};
29
30/* must be unique, FIXME: must be added in Documentation/ioctl_number.txt */
31#define SCLP_IOCTL_LETTER 'B'
32
33/* set width of horizontal tabulator */
34#define TIOCSCLPSHTAB _IOW(SCLP_IOCTL_LETTER, 0, unsigned short)
35/* enable/disable echo of input (independent from line discipline) */
36#define TIOCSCLPSECHO _IOW(SCLP_IOCTL_LETTER, 1, unsigned char)
37/* set number of colums for output */
38#define TIOCSCLPSCOLS _IOW(SCLP_IOCTL_LETTER, 2, unsigned short)
39/* enable/disable writing without final new line character */
40#define TIOCSCLPSNL _IOW(SCLP_IOCTL_LETTER, 4, signed char)
41/* set the maximum buffers size for output, rounded up to next 4kB boundary */
42#define TIOCSCLPSOBUF _IOW(SCLP_IOCTL_LETTER, 5, unsigned short)
43/* set initial (default) sclp ioctls */
44#define TIOCSCLPSINIT _IO(SCLP_IOCTL_LETTER, 6)
45/* enable/disable conversion from upper to lower case of input */
46#define TIOCSCLPSCASE _IOW(SCLP_IOCTL_LETTER, 7, unsigned char)
47/* set special character used for separating upper and lower case, */
48/* 0x00 disables this feature */
49#define TIOCSCLPSDELIM _IOW(SCLP_IOCTL_LETTER, 9, unsigned char)
50
51/* get width of horizontal tabulator */
52#define TIOCSCLPGHTAB _IOR(SCLP_IOCTL_LETTER, 10, unsigned short)
53/* Is echo of input enabled ? (independent from line discipline) */
54#define TIOCSCLPGECHO _IOR(SCLP_IOCTL_LETTER, 11, unsigned char)
55/* get number of colums for output */
56#define TIOCSCLPGCOLS _IOR(SCLP_IOCTL_LETTER, 12, unsigned short)
57/* Is writing without final new line character enabled ? */
58#define TIOCSCLPGNL _IOR(SCLP_IOCTL_LETTER, 14, signed char)
59/* get the maximum buffers size for output */
60#define TIOCSCLPGOBUF _IOR(SCLP_IOCTL_LETTER, 15, unsigned short)
61/* Is conversion from upper to lower case of input enabled ? */
62#define TIOCSCLPGCASE _IOR(SCLP_IOCTL_LETTER, 17, unsigned char)
63/* get special character used for separating upper and lower case, */
64/* 0x00 disables this feature */
65#define TIOCSCLPGDELIM _IOR(SCLP_IOCTL_LETTER, 19, unsigned char)
66/* get the number of buffers/pages got from kernel at startup */
67#define TIOCSCLPGKBUF _IOR(SCLP_IOCTL_LETTER, 20, unsigned short)
68
69extern struct tty_driver *sclp_tty_driver; 16extern struct tty_driver *sclp_tty_driver;
70 17
71#endif /* __SCLP_TTY_H__ */ 18#endif /* __SCLP_TTY_H__ */
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 3e577f655b18..ad51738c4261 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -27,7 +27,6 @@
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include "sclp.h" 28#include "sclp.h"
29 29
30#define SCLP_VT220_PRINT_HEADER "sclp vt220 tty driver: "
31#define SCLP_VT220_MAJOR TTY_MAJOR 30#define SCLP_VT220_MAJOR TTY_MAJOR
32#define SCLP_VT220_MINOR 65 31#define SCLP_VT220_MINOR 65
33#define SCLP_VT220_DRIVER_NAME "sclp_vt220" 32#define SCLP_VT220_DRIVER_NAME "sclp_vt220"
@@ -82,8 +81,8 @@ static struct sclp_vt220_request *sclp_vt220_current_request;
82/* Number of characters in current request buffer */ 81/* Number of characters in current request buffer */
83static int sclp_vt220_buffered_chars; 82static int sclp_vt220_buffered_chars;
84 83
85/* Flag indicating whether this driver has already been initialized */ 84/* Counter controlling core driver initialization. */
86static int sclp_vt220_initialized = 0; 85static int __initdata sclp_vt220_init_count;
87 86
88/* Flag indicating that sclp_vt220_current_request should really 87/* Flag indicating that sclp_vt220_current_request should really
89 * have been already queued but wasn't because the SCLP was processing 88 * have been already queued but wasn't because the SCLP was processing
@@ -609,10 +608,8 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
609 sclp_vt220_emit_current(); 608 sclp_vt220_emit_current();
610} 609}
611 610
612/* 611/* Release allocated pages. */
613 * Initialize all relevant components and register driver with system. 612static void __init __sclp_vt220_free_pages(void)
614 */
615static void __init __sclp_vt220_cleanup(void)
616{ 613{
617 struct list_head *page, *p; 614 struct list_head *page, *p;
618 615
@@ -623,21 +620,30 @@ static void __init __sclp_vt220_cleanup(void)
623 else 620 else
624 free_bootmem((unsigned long) page, PAGE_SIZE); 621 free_bootmem((unsigned long) page, PAGE_SIZE);
625 } 622 }
626 if (!list_empty(&sclp_vt220_register.list))
627 sclp_unregister(&sclp_vt220_register);
628 sclp_vt220_initialized = 0;
629} 623}
630 624
631static int __init __sclp_vt220_init(void) 625/* Release memory and unregister from sclp core. Controlled by init counting -
626 * only the last invoker will actually perform these actions. */
627static void __init __sclp_vt220_cleanup(void)
628{
629 sclp_vt220_init_count--;
630 if (sclp_vt220_init_count != 0)
631 return;
632 sclp_unregister(&sclp_vt220_register);
633 __sclp_vt220_free_pages();
634}
635
636/* Allocate buffer pages and register with sclp core. Controlled by init
637 * counting - only the first invoker will actually perform these actions. */
638static int __init __sclp_vt220_init(int num_pages)
632{ 639{
633 void *page; 640 void *page;
634 int i; 641 int i;
635 int num_pages;
636 int rc; 642 int rc;
637 643
638 if (sclp_vt220_initialized) 644 sclp_vt220_init_count++;
645 if (sclp_vt220_init_count != 1)
639 return 0; 646 return 0;
640 sclp_vt220_initialized = 1;
641 spin_lock_init(&sclp_vt220_lock); 647 spin_lock_init(&sclp_vt220_lock);
642 INIT_LIST_HEAD(&sclp_vt220_empty); 648 INIT_LIST_HEAD(&sclp_vt220_empty);
643 INIT_LIST_HEAD(&sclp_vt220_outqueue); 649 INIT_LIST_HEAD(&sclp_vt220_outqueue);
@@ -649,24 +655,22 @@ static int __init __sclp_vt220_init(void)
649 sclp_vt220_flush_later = 0; 655 sclp_vt220_flush_later = 0;
650 656
651 /* Allocate pages for output buffering */ 657 /* Allocate pages for output buffering */
652 num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
653 for (i = 0; i < num_pages; i++) { 658 for (i = 0; i < num_pages; i++) {
654 if (slab_is_available()) 659 if (slab_is_available())
655 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 660 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
656 else 661 else
657 page = alloc_bootmem_low_pages(PAGE_SIZE); 662 page = alloc_bootmem_low_pages(PAGE_SIZE);
658 if (!page) { 663 if (!page) {
659 __sclp_vt220_cleanup(); 664 rc = -ENOMEM;
660 return -ENOMEM; 665 goto out;
661 } 666 }
662 list_add_tail((struct list_head *) page, &sclp_vt220_empty); 667 list_add_tail((struct list_head *) page, &sclp_vt220_empty);
663 } 668 }
664 rc = sclp_register(&sclp_vt220_register); 669 rc = sclp_register(&sclp_vt220_register);
670out:
665 if (rc) { 671 if (rc) {
666 printk(KERN_ERR SCLP_VT220_PRINT_HEADER 672 __sclp_vt220_free_pages();
667 "could not register vt220 - " 673 sclp_vt220_init_count--;
668 "sclp_register returned %d\n", rc);
669 __sclp_vt220_cleanup();
670 } 674 }
671 return rc; 675 return rc;
672} 676}
@@ -689,15 +693,13 @@ static int __init sclp_vt220_tty_init(void)
689{ 693{
690 struct tty_driver *driver; 694 struct tty_driver *driver;
691 int rc; 695 int rc;
692 int cleanup;
693 696
694 /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve 697 /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
695 * symmetry between VM and LPAR systems regarding ttyS1. */ 698 * symmetry between VM and LPAR systems regarding ttyS1. */
696 driver = alloc_tty_driver(1); 699 driver = alloc_tty_driver(1);
697 if (!driver) 700 if (!driver)
698 return -ENOMEM; 701 return -ENOMEM;
699 cleanup = !sclp_vt220_initialized; 702 rc = __sclp_vt220_init(MAX_KMEM_PAGES);
700 rc = __sclp_vt220_init();
701 if (rc) 703 if (rc)
702 goto out_driver; 704 goto out_driver;
703 705
@@ -713,18 +715,13 @@ static int __init sclp_vt220_tty_init(void)
713 tty_set_operations(driver, &sclp_vt220_ops); 715 tty_set_operations(driver, &sclp_vt220_ops);
714 716
715 rc = tty_register_driver(driver); 717 rc = tty_register_driver(driver);
716 if (rc) { 718 if (rc)
717 printk(KERN_ERR SCLP_VT220_PRINT_HEADER
718 "could not register tty - "
719 "tty_register_driver returned %d\n", rc);
720 goto out_init; 719 goto out_init;
721 }
722 sclp_vt220_driver = driver; 720 sclp_vt220_driver = driver;
723 return 0; 721 return 0;
724 722
725out_init: 723out_init:
726 if (cleanup) 724 __sclp_vt220_cleanup();
727 __sclp_vt220_cleanup();
728out_driver: 725out_driver:
729 put_tty_driver(driver); 726 put_tty_driver(driver);
730 return rc; 727 return rc;
@@ -773,10 +770,9 @@ sclp_vt220_con_init(void)
773{ 770{
774 int rc; 771 int rc;
775 772
776 INIT_LIST_HEAD(&sclp_vt220_register.list);
777 if (!CONSOLE_IS_SCLP) 773 if (!CONSOLE_IS_SCLP)
778 return 0; 774 return 0;
779 rc = __sclp_vt220_init(); 775 rc = __sclp_vt220_init(MAX_CONSOLE_PAGES);
780 if (rc) 776 if (rc)
781 return rc; 777 return rc;
782 /* Attach linux console */ 778 /* Attach linux console */
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 874adf365e46..22ca34361ed7 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -196,7 +196,7 @@ tape_34xx_erp_retry(struct tape_request *request)
196static int 196static int
197tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb) 197tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb)
198{ 198{
199 if (irb->scsw.dstat == 0x85 /* READY */) { 199 if (irb->scsw.cmd.dstat == 0x85) { /* READY */
200 /* A medium was inserted in the drive. */ 200 /* A medium was inserted in the drive. */
201 DBF_EVENT(6, "xuud med\n"); 201 DBF_EVENT(6, "xuud med\n");
202 tape_34xx_delete_sbid_from(device, 0); 202 tape_34xx_delete_sbid_from(device, 0);
@@ -844,22 +844,22 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request,
844 if (request == NULL) 844 if (request == NULL)
845 return tape_34xx_unsolicited_irq(device, irb); 845 return tape_34xx_unsolicited_irq(device, irb);
846 846
847 if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) && 847 if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
848 (irb->scsw.dstat & DEV_STAT_DEV_END) && 848 (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
849 (request->op == TO_WRI)) { 849 (request->op == TO_WRI)) {
850 /* Write at end of volume */ 850 /* Write at end of volume */
851 PRINT_INFO("End of volume\n"); /* XXX */ 851 PRINT_INFO("End of volume\n"); /* XXX */
852 return tape_34xx_erp_failed(request, -ENOSPC); 852 return tape_34xx_erp_failed(request, -ENOSPC);
853 } 853 }
854 854
855 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) 855 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
856 return tape_34xx_unit_check(device, request, irb); 856 return tape_34xx_unit_check(device, request, irb);
857 857
858 if (irb->scsw.dstat & DEV_STAT_DEV_END) { 858 if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
859 /* 859 /*
860 * A unit exception occurs on skipping over a tapemark block. 860 * A unit exception occurs on skipping over a tapemark block.
861 */ 861 */
862 if (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) { 862 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
863 if (request->op == TO_BSB || request->op == TO_FSB) 863 if (request->op == TO_BSB || request->op == TO_FSB)
864 request->rescnt++; 864 request->rescnt++;
865 else 865 else
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 42ce7915fc5d..839987618ffd 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -837,13 +837,13 @@ tape_3590_erp_retry(struct tape_device *device, struct tape_request *request,
837static int 837static int
838tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb) 838tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb)
839{ 839{
840 if (irb->scsw.dstat == DEV_STAT_CHN_END) 840 if (irb->scsw.cmd.dstat == DEV_STAT_CHN_END)
841 /* Probably result of halt ssch */ 841 /* Probably result of halt ssch */
842 return TAPE_IO_PENDING; 842 return TAPE_IO_PENDING;
843 else if (irb->scsw.dstat == 0x85) 843 else if (irb->scsw.cmd.dstat == 0x85)
844 /* Device Ready */ 844 /* Device Ready */
845 DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id); 845 DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id);
846 else if (irb->scsw.dstat & DEV_STAT_ATTENTION) { 846 else if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
847 tape_3590_schedule_work(device, TO_READ_ATTMSG); 847 tape_3590_schedule_work(device, TO_READ_ATTMSG);
848 } else { 848 } else {
849 DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); 849 DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
@@ -1515,18 +1515,19 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
1515 if (request == NULL) 1515 if (request == NULL)
1516 return tape_3590_unsolicited_irq(device, irb); 1516 return tape_3590_unsolicited_irq(device, irb);
1517 1517
1518 if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) && 1518 if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
1519 (irb->scsw.dstat & DEV_STAT_DEV_END) && (request->op == TO_WRI)) { 1519 (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
1520 (request->op == TO_WRI)) {
1520 /* Write at end of volume */ 1521 /* Write at end of volume */
1521 DBF_EVENT(2, "End of volume\n"); 1522 DBF_EVENT(2, "End of volume\n");
1522 return tape_3590_erp_failed(device, request, irb, -ENOSPC); 1523 return tape_3590_erp_failed(device, request, irb, -ENOSPC);
1523 } 1524 }
1524 1525
1525 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) 1526 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
1526 return tape_3590_unit_check(device, request, irb); 1527 return tape_3590_unit_check(device, request, irb);
1527 1528
1528 if (irb->scsw.dstat & DEV_STAT_DEV_END) { 1529 if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
1529 if (irb->scsw.dstat == DEV_STAT_UNIT_EXCEP) { 1530 if (irb->scsw.cmd.dstat == DEV_STAT_UNIT_EXCEP) {
1530 if (request->op == TO_FSB || request->op == TO_BSB) 1531 if (request->op == TO_FSB || request->op == TO_BSB)
1531 request->rescnt++; 1532 request->rescnt++;
1532 else 1533 else
@@ -1536,12 +1537,12 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
1536 return tape_3590_done(device, request); 1537 return tape_3590_done(device, request);
1537 } 1538 }
1538 1539
1539 if (irb->scsw.dstat & DEV_STAT_CHN_END) { 1540 if (irb->scsw.cmd.dstat & DEV_STAT_CHN_END) {
1540 DBF_EVENT(2, "cannel end\n"); 1541 DBF_EVENT(2, "cannel end\n");
1541 return TAPE_IO_PENDING; 1542 return TAPE_IO_PENDING;
1542 } 1543 }
1543 1544
1544 if (irb->scsw.dstat & DEV_STAT_ATTENTION) { 1545 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
1545 DBF_EVENT(2, "Unit Attention when busy..\n"); 1546 DBF_EVENT(2, "Unit Attention when busy..\n");
1546 return TAPE_IO_PENDING; 1547 return TAPE_IO_PENDING;
1547 } 1548 }
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index ebe84067bae9..687720b552d1 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -14,6 +14,7 @@
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/proc_fs.h> 15#include <linux/proc_fs.h>
16#include <linux/mtio.h> 16#include <linux/mtio.h>
17#include <linux/smp_lock.h>
17 18
18#include <asm/uaccess.h> 19#include <asm/uaccess.h>
19 20
@@ -289,21 +290,26 @@ tapechar_open (struct inode *inode, struct file *filp)
289 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) 290 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
290 return -ENODEV; 291 return -ENODEV;
291 292
293 lock_kernel();
292 minor = iminor(filp->f_path.dentry->d_inode); 294 minor = iminor(filp->f_path.dentry->d_inode);
293 device = tape_get_device(minor / TAPE_MINORS_PER_DEV); 295 device = tape_get_device(minor / TAPE_MINORS_PER_DEV);
294 if (IS_ERR(device)) { 296 if (IS_ERR(device)) {
295 DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); 297 DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n");
296 return PTR_ERR(device); 298 rc = PTR_ERR(device);
299 goto out;
297 } 300 }
298 301
299 302
300 rc = tape_open(device); 303 rc = tape_open(device);
301 if (rc == 0) { 304 if (rc == 0) {
302 filp->private_data = device; 305 filp->private_data = device;
303 return nonseekable_open(inode, filp); 306 rc = nonseekable_open(inode, filp);
304 } 307 }
305 tape_put_device(device); 308 else
309 tape_put_device(device);
306 310
311out:
312 unlock_kernel();
307 return rc; 313 return rc;
308} 314}
309 315
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index c20e3c548343..181a5441af16 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -839,7 +839,7 @@ tape_dump_sense(struct tape_device* device, struct tape_request *request,
839 839
840 PRINT_INFO("-------------------------------------------------\n"); 840 PRINT_INFO("-------------------------------------------------\n");
841 PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n", 841 PRINT_INFO("DSTAT : %02x CSTAT: %02x CPA: %04x\n",
842 irb->scsw.dstat, irb->scsw.cstat, irb->scsw.cpa); 842 irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa);
843 PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id); 843 PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id);
844 if (request != NULL) 844 if (request != NULL)
845 PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]); 845 PRINT_INFO("OP : %s\n", tape_op_verbose[request->op]);
@@ -867,7 +867,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request,
867 else 867 else
868 op = "---"; 868 op = "---";
869 DBF_EVENT(3, "DSTAT : %02x CSTAT: %02x\n", 869 DBF_EVENT(3, "DSTAT : %02x CSTAT: %02x\n",
870 irb->scsw.dstat,irb->scsw.cstat); 870 irb->scsw.cmd.dstat, irb->scsw.cmd.cstat);
871 DBF_EVENT(3, "DEVICE: %08x OP\t: %s\n", device->cdev_id, op); 871 DBF_EVENT(3, "DEVICE: %08x OP\t: %s\n", device->cdev_id, op);
872 sptr = (unsigned int *) irb->ecw; 872 sptr = (unsigned int *) irb->ecw;
873 DBF_EVENT(3, "%08x %08x\n", sptr[0], sptr[1]); 873 DBF_EVENT(3, "%08x %08x\n", sptr[0], sptr[1]);
@@ -1083,10 +1083,11 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1083 * error might still apply. So we just schedule the request to be 1083 * error might still apply. So we just schedule the request to be
1084 * started later. 1084 * started later.
1085 */ 1085 */
1086 if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC) && 1086 if (irb->scsw.cmd.cc != 0 &&
1087 (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
1087 (request->status == TAPE_REQUEST_IN_IO)) { 1088 (request->status == TAPE_REQUEST_IN_IO)) {
1088 DBF_EVENT(3,"(%08x): deferred cc=%i, fctl=%i. restarting\n", 1089 DBF_EVENT(3,"(%08x): deferred cc=%i, fctl=%i. restarting\n",
1089 device->cdev_id, irb->scsw.cc, irb->scsw.fctl); 1090 device->cdev_id, irb->scsw.cmd.cc, irb->scsw.cmd.fctl);
1090 request->status = TAPE_REQUEST_QUEUED; 1091 request->status = TAPE_REQUEST_QUEUED;
1091 schedule_delayed_work(&device->tape_dnr, HZ); 1092 schedule_delayed_work(&device->tape_dnr, HZ);
1092 return; 1093 return;
@@ -1094,8 +1095,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1094 1095
1095 /* May be an unsolicited irq */ 1096 /* May be an unsolicited irq */
1096 if(request != NULL) 1097 if(request != NULL)
1097 request->rescnt = irb->scsw.count; 1098 request->rescnt = irb->scsw.cmd.count;
1098 else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) && 1099 else if ((irb->scsw.cmd.dstat == 0x85 || irb->scsw.cmd.dstat == 0x80) &&
1099 !list_empty(&device->req_queue)) { 1100 !list_empty(&device->req_queue)) {
1100 /* Not Ready to Ready after long busy ? */ 1101 /* Not Ready to Ready after long busy ? */
1101 struct tape_request *req; 1102 struct tape_request *req;
@@ -1111,7 +1112,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
1111 return; 1112 return;
1112 } 1113 }
1113 } 1114 }
1114 if (irb->scsw.dstat != 0x0c) { 1115 if (irb->scsw.cmd.dstat != 0x0c) {
1115 /* Set the 'ONLINE' flag depending on sense byte 1 */ 1116 /* Set the 'ONLINE' flag depending on sense byte 1 */
1116 if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) 1117 if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
1117 device->tape_generic_status |= GMT_ONLINE(~0); 1118 device->tape_generic_status |= GMT_ONLINE(~0);
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 5043150019ac..a7fe6302c982 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -663,7 +663,7 @@ static int
663tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb) 663tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
664{ 664{
665 /* Handle ATTN. Schedule tasklet to read aid. */ 665 /* Handle ATTN. Schedule tasklet to read aid. */
666 if (irb->scsw.dstat & DEV_STAT_ATTENTION) { 666 if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
667 if (!tp->throttle) 667 if (!tp->throttle)
668 tty3270_issue_read(tp, 0); 668 tty3270_issue_read(tp, 0);
669 else 669 else
@@ -671,11 +671,11 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
671 } 671 }
672 672
673 if (rq) { 673 if (rq) {
674 if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) 674 if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
675 rq->rc = -EIO; 675 rq->rc = -EIO;
676 else 676 else
677 /* Normal end. Copy residual count. */ 677 /* Normal end. Copy residual count. */
678 rq->rescnt = irb->scsw.count; 678 rq->rescnt = irb->scsw.cmd.count;
679 } 679 }
680 return RAW3270_IO_DONE; 680 return RAW3270_IO_DONE;
681} 681}
@@ -1792,15 +1792,12 @@ static int __init tty3270_init(void)
1792 tty_set_operations(driver, &tty3270_ops); 1792 tty_set_operations(driver, &tty3270_ops);
1793 ret = tty_register_driver(driver); 1793 ret = tty_register_driver(driver);
1794 if (ret) { 1794 if (ret) {
1795 printk(KERN_ERR "tty3270 registration failed with %d\n", ret);
1796 put_tty_driver(driver); 1795 put_tty_driver(driver);
1797 return ret; 1796 return ret;
1798 } 1797 }
1799 tty3270_driver = driver; 1798 tty3270_driver = driver;
1800 ret = raw3270_register_notifier(tty3270_notifier); 1799 ret = raw3270_register_notifier(tty3270_notifier);
1801 if (ret) { 1800 if (ret) {
1802 printk(KERN_ERR "tty3270 notifier registration failed "
1803 "with %d\n", ret);
1804 put_tty_driver(driver); 1801 put_tty_driver(driver);
1805 return ret; 1802 return ret;
1806 1803
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 2f419b0ea628..09e7d9bf438b 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -16,6 +16,7 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/miscdevice.h> 17#include <linux/miscdevice.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/smp_lock.h>
19#include <asm/cpcmd.h> 20#include <asm/cpcmd.h>
20#include <asm/debug.h> 21#include <asm/debug.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
@@ -39,11 +40,14 @@ static int vmcp_open(struct inode *inode, struct file *file)
39 session = kmalloc(sizeof(*session), GFP_KERNEL); 40 session = kmalloc(sizeof(*session), GFP_KERNEL);
40 if (!session) 41 if (!session)
41 return -ENOMEM; 42 return -ENOMEM;
43
44 lock_kernel();
42 session->bufsize = PAGE_SIZE; 45 session->bufsize = PAGE_SIZE;
43 session->response = NULL; 46 session->response = NULL;
44 session->resp_size = 0; 47 session->resp_size = 0;
45 mutex_init(&session->mutex); 48 mutex_init(&session->mutex);
46 file->private_data = session; 49 file->private_data = session;
50 unlock_kernel();
47 return nonseekable_open(inode, file); 51 return nonseekable_open(inode, file);
48} 52}
49 53
@@ -61,30 +65,24 @@ static int vmcp_release(struct inode *inode, struct file *file)
61static ssize_t 65static ssize_t
62vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos) 66vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
63{ 67{
64 size_t tocopy; 68 ssize_t ret;
69 size_t size;
65 struct vmcp_session *session; 70 struct vmcp_session *session;
66 71
67 session = (struct vmcp_session *)file->private_data; 72 session = file->private_data;
68 if (mutex_lock_interruptible(&session->mutex)) 73 if (mutex_lock_interruptible(&session->mutex))
69 return -ERESTARTSYS; 74 return -ERESTARTSYS;
70 if (!session->response) { 75 if (!session->response) {
71 mutex_unlock(&session->mutex); 76 mutex_unlock(&session->mutex);
72 return 0; 77 return 0;
73 } 78 }
74 if (*ppos > session->resp_size) { 79 size = min_t(size_t, session->resp_size, session->bufsize);
75 mutex_unlock(&session->mutex); 80 ret = simple_read_from_buffer(buff, count, ppos,
76 return 0; 81 session->response, size);
77 }
78 tocopy = min(session->resp_size - (size_t) (*ppos), count);
79 tocopy = min(tocopy, session->bufsize - (size_t) (*ppos));
80 82
81 if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
82 mutex_unlock(&session->mutex);
83 return -EFAULT;
84 }
85 mutex_unlock(&session->mutex); 83 mutex_unlock(&session->mutex);
86 *ppos += tocopy; 84
87 return tocopy; 85 return ret;
88} 86}
89 87
90static ssize_t 88static ssize_t
@@ -198,27 +196,23 @@ static int __init vmcp_init(void)
198 PRINT_WARN("z/VM CP interface is only available under z/VM\n"); 196 PRINT_WARN("z/VM CP interface is only available under z/VM\n");
199 return -ENODEV; 197 return -ENODEV;
200 } 198 }
199
201 vmcp_debug = debug_register("vmcp", 1, 1, 240); 200 vmcp_debug = debug_register("vmcp", 1, 1, 240);
202 if (!vmcp_debug) { 201 if (!vmcp_debug)
203 PRINT_ERR("z/VM CP interface not loaded. Could not register "
204 "debug feature\n");
205 return -ENOMEM; 202 return -ENOMEM;
206 } 203
207 ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view); 204 ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view);
208 if (ret) { 205 if (ret) {
209 PRINT_ERR("z/VM CP interface not loaded. Could not register "
210 "debug feature view. Error code: %d\n", ret);
211 debug_unregister(vmcp_debug); 206 debug_unregister(vmcp_debug);
212 return ret; 207 return ret;
213 } 208 }
209
214 ret = misc_register(&vmcp_dev); 210 ret = misc_register(&vmcp_dev);
215 if (ret) { 211 if (ret) {
216 PRINT_ERR("z/VM CP interface not loaded. Could not register "
217 "misc device. Error code: %d\n", ret);
218 debug_unregister(vmcp_debug); 212 debug_unregister(vmcp_debug);
219 return ret; 213 return ret;
220 } 214 }
221 PRINT_INFO("z/VM CP interface loaded\n"); 215
222 return 0; 216 return 0;
223} 217}
224 218
@@ -226,7 +220,6 @@ static void __exit vmcp_exit(void)
226{ 220{
227 misc_deregister(&vmcp_dev); 221 misc_deregister(&vmcp_dev);
228 debug_unregister(vmcp_debug); 222 debug_unregister(vmcp_debug);
229 PRINT_INFO("z/VM CP interface unloaded.\n");
230} 223}
231 224
232module_init(vmcp_init); 225module_init(vmcp_init);
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 2c2428cc05d8..c31faefa2b3b 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -25,6 +25,7 @@
25#include <linux/kmod.h> 25#include <linux/kmod.h>
26#include <linux/cdev.h> 26#include <linux/cdev.h>
27#include <linux/device.h> 27#include <linux/device.h>
28#include <linux/smp_lock.h>
28#include <linux/string.h> 29#include <linux/string.h>
29 30
30 31
@@ -216,9 +217,7 @@ static int vmlogrdr_get_recording_class_AB(void)
216 char *tail; 217 char *tail;
217 int len,i; 218 int len,i;
218 219
219 printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
220 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); 220 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
221 printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
222 len = strnlen(cp_response,sizeof(cp_response)); 221 len = strnlen(cp_response,sizeof(cp_response));
223 // now the parsing 222 // now the parsing
224 tail=strnchr(cp_response,len,'='); 223 tail=strnchr(cp_response,len,'=');
@@ -268,11 +267,7 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
268 logptr->recording_name, 267 logptr->recording_name,
269 qid_string); 268 qid_string);
270 269
271 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
272 cp_command);
273 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); 270 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
274 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
275 cp_response);
276 } 271 }
277 272
278 memset(cp_command, 0x00, sizeof(cp_command)); 273 memset(cp_command, 0x00, sizeof(cp_command));
@@ -282,10 +277,7 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
282 onoff, 277 onoff,
283 qid_string); 278 qid_string);
284 279
285 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
286 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); 280 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
287 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
288 cp_response);
289 /* The recording command will usually answer with 'Command complete' 281 /* The recording command will usually answer with 'Command complete'
290 * on success, but when the specific service was never connected 282 * on success, but when the specific service was never connected
291 * before then there might be an additional informational message 283 * before then there might be an additional informational message
@@ -319,9 +311,11 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
319 return -ENOSYS; 311 return -ENOSYS;
320 312
321 /* Besure this device hasn't already been opened */ 313 /* Besure this device hasn't already been opened */
314 lock_kernel();
322 spin_lock_bh(&logptr->priv_lock); 315 spin_lock_bh(&logptr->priv_lock);
323 if (logptr->dev_in_use) { 316 if (logptr->dev_in_use) {
324 spin_unlock_bh(&logptr->priv_lock); 317 spin_unlock_bh(&logptr->priv_lock);
318 unlock_kernel();
325 return -EBUSY; 319 return -EBUSY;
326 } 320 }
327 logptr->dev_in_use = 1; 321 logptr->dev_in_use = 1;
@@ -365,7 +359,9 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
365 || (logptr->iucv_path_severed)); 359 || (logptr->iucv_path_severed));
366 if (logptr->iucv_path_severed) 360 if (logptr->iucv_path_severed)
367 goto out_record; 361 goto out_record;
368 return nonseekable_open(inode, filp); 362 ret = nonseekable_open(inode, filp);
363 unlock_kernel();
364 return ret;
369 365
370out_record: 366out_record:
371 if (logptr->autorecording) 367 if (logptr->autorecording)
@@ -375,6 +371,7 @@ out_path:
375 logptr->path = NULL; 371 logptr->path = NULL;
376out_dev: 372out_dev:
377 logptr->dev_in_use = 0; 373 logptr->dev_in_use = 0;
374 unlock_kernel();
378 return -EIO; 375 return -EIO;
379} 376}
380 377
@@ -567,10 +564,7 @@ static ssize_t vmlogrdr_purge_store(struct device * dev,
567 "RECORDING %s PURGE ", 564 "RECORDING %s PURGE ",
568 priv->recording_name); 565 priv->recording_name);
569 566
570 printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
571 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); 567 cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
572 printk (KERN_DEBUG "vmlogrdr: recording response: %s",
573 cp_response);
574 568
575 return count; 569 return count;
576} 570}
@@ -682,28 +676,20 @@ static int vmlogrdr_register_driver(void)
682 676
683 /* Register with iucv driver */ 677 /* Register with iucv driver */
684 ret = iucv_register(&vmlogrdr_iucv_handler, 1); 678 ret = iucv_register(&vmlogrdr_iucv_handler, 1);
685 if (ret) { 679 if (ret)
686 printk (KERN_ERR "vmlogrdr: failed to register with "
687 "iucv driver\n");
688 goto out; 680 goto out;
689 }
690 681
691 ret = driver_register(&vmlogrdr_driver); 682 ret = driver_register(&vmlogrdr_driver);
692 if (ret) { 683 if (ret)
693 printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
694 goto out_iucv; 684 goto out_iucv;
695 }
696 685
697 ret = driver_create_file(&vmlogrdr_driver, 686 ret = driver_create_file(&vmlogrdr_driver,
698 &driver_attr_recording_status); 687 &driver_attr_recording_status);
699 if (ret) { 688 if (ret)
700 printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
701 goto out_driver; 689 goto out_driver;
702 }
703 690
704 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr"); 691 vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
705 if (IS_ERR(vmlogrdr_class)) { 692 if (IS_ERR(vmlogrdr_class)) {
706 printk(KERN_ERR "vmlogrdr: failed to create class.\n");
707 ret = PTR_ERR(vmlogrdr_class); 693 ret = PTR_ERR(vmlogrdr_class);
708 vmlogrdr_class = NULL; 694 vmlogrdr_class = NULL;
709 goto out_attr; 695 goto out_attr;
@@ -871,12 +857,10 @@ static int __init vmlogrdr_init(void)
871 rc = vmlogrdr_register_cdev(dev); 857 rc = vmlogrdr_register_cdev(dev);
872 if (rc) 858 if (rc)
873 goto cleanup; 859 goto cleanup;
874 printk (KERN_INFO "vmlogrdr: driver loaded\n");
875 return 0; 860 return 0;
876 861
877cleanup: 862cleanup:
878 vmlogrdr_cleanup(); 863 vmlogrdr_cleanup();
879 printk (KERN_ERR "vmlogrdr: driver not loaded.\n");
880 return rc; 864 return rc;
881} 865}
882 866
@@ -884,7 +868,6 @@ cleanup:
884static void __exit vmlogrdr_exit(void) 868static void __exit vmlogrdr_exit(void)
885{ 869{
886 vmlogrdr_cleanup(); 870 vmlogrdr_cleanup();
887 printk (KERN_INFO "vmlogrdr: driver unloaded\n");
888 return; 871 return;
889} 872}
890 873
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 83ae9a852f00..b0ac44b27127 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -9,6 +9,7 @@
9 */ 9 */
10 10
11#include <linux/cdev.h> 11#include <linux/cdev.h>
12#include <linux/smp_lock.h>
12 13
13#include <asm/uaccess.h> 14#include <asm/uaccess.h>
14#include <asm/cio.h> 15#include <asm/cio.h>
@@ -277,7 +278,8 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
277 struct urdev *urd; 278 struct urdev *urd;
278 279
279 TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n", 280 TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
280 intparm, irb->scsw.cstat, irb->scsw.dstat, irb->scsw.count); 281 intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
282 irb->scsw.cmd.count);
281 283
282 if (!intparm) { 284 if (!intparm) {
283 TRACE("ur_int_handler: unsolicited interrupt\n"); 285 TRACE("ur_int_handler: unsolicited interrupt\n");
@@ -288,7 +290,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
288 /* On special conditions irb is an error pointer */ 290 /* On special conditions irb is an error pointer */
289 if (IS_ERR(irb)) 291 if (IS_ERR(irb))
290 urd->io_request_rc = PTR_ERR(irb); 292 urd->io_request_rc = PTR_ERR(irb);
291 else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) 293 else if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
292 urd->io_request_rc = 0; 294 urd->io_request_rc = 0;
293 else 295 else
294 urd->io_request_rc = -EIO; 296 urd->io_request_rc = -EIO;
@@ -343,7 +345,7 @@ static int get_urd_class(struct urdev *urd)
343 cc = diag210(&ur_diag210); 345 cc = diag210(&ur_diag210);
344 switch (cc) { 346 switch (cc) {
345 case 0: 347 case 0:
346 return -ENOTSUPP; 348 return -EOPNOTSUPP;
347 case 2: 349 case 2:
348 return ur_diag210.vrdcvcla; /* virtual device class */ 350 return ur_diag210.vrdcvcla; /* virtual device class */
349 case 3: 351 case 3:
@@ -619,7 +621,7 @@ static int verify_device(struct urdev *urd)
619 case DEV_CLASS_UR_I: 621 case DEV_CLASS_UR_I:
620 return verify_uri_device(urd); 622 return verify_uri_device(urd);
621 default: 623 default:
622 return -ENOTSUPP; 624 return -EOPNOTSUPP;
623 } 625 }
624} 626}
625 627
@@ -652,7 +654,7 @@ static int get_file_reclen(struct urdev *urd)
652 case DEV_CLASS_UR_I: 654 case DEV_CLASS_UR_I:
653 return get_uri_file_reclen(urd); 655 return get_uri_file_reclen(urd);
654 default: 656 default:
655 return -ENOTSUPP; 657 return -EOPNOTSUPP;
656 } 658 }
657} 659}
658 660
@@ -668,7 +670,7 @@ static int ur_open(struct inode *inode, struct file *file)
668 670
669 if (accmode == O_RDWR) 671 if (accmode == O_RDWR)
670 return -EACCES; 672 return -EACCES;
671 673 lock_kernel();
672 /* 674 /*
673 * We treat the minor number as the devno of the ur device 675 * We treat the minor number as the devno of the ur device
674 * to find in the driver tree. 676 * to find in the driver tree.
@@ -676,8 +678,10 @@ static int ur_open(struct inode *inode, struct file *file)
676 devno = MINOR(file->f_dentry->d_inode->i_rdev); 678 devno = MINOR(file->f_dentry->d_inode->i_rdev);
677 679
678 urd = urdev_get_from_devno(devno); 680 urd = urdev_get_from_devno(devno);
679 if (!urd) 681 if (!urd) {
680 return -ENXIO; 682 rc = -ENXIO;
683 goto out;
684 }
681 685
682 spin_lock(&urd->open_lock); 686 spin_lock(&urd->open_lock);
683 while (urd->open_flag) { 687 while (urd->open_flag) {
@@ -720,6 +724,7 @@ static int ur_open(struct inode *inode, struct file *file)
720 goto fail_urfile_free; 724 goto fail_urfile_free;
721 urf->file_reclen = rc; 725 urf->file_reclen = rc;
722 file->private_data = urf; 726 file->private_data = urf;
727 unlock_kernel();
723 return 0; 728 return 0;
724 729
725fail_urfile_free: 730fail_urfile_free:
@@ -730,6 +735,8 @@ fail_unlock:
730 spin_unlock(&urd->open_lock); 735 spin_unlock(&urd->open_lock);
731fail_put: 736fail_put:
732 urdev_put(urd); 737 urdev_put(urd);
738out:
739 unlock_kernel();
733 return rc; 740 return rc;
734} 741}
735 742
@@ -820,7 +827,7 @@ static int ur_probe(struct ccw_device *cdev)
820 goto fail_remove_attr; 827 goto fail_remove_attr;
821 } 828 }
822 if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { 829 if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
823 rc = -ENOTSUPP; 830 rc = -EOPNOTSUPP;
824 goto fail_remove_attr; 831 goto fail_remove_attr;
825 } 832 }
826 spin_lock_irq(get_ccwdev_lock(cdev)); 833 spin_lock_irq(get_ccwdev_lock(cdev));
@@ -885,7 +892,7 @@ static int ur_set_online(struct ccw_device *cdev)
885 } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) { 892 } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) {
886 sprintf(node_id, "vmprt-%s", cdev->dev.bus_id); 893 sprintf(node_id, "vmprt-%s", cdev->dev.bus_id);
887 } else { 894 } else {
888 rc = -ENOTSUPP; 895 rc = -EOPNOTSUPP;
889 goto fail_free_cdev; 896 goto fail_free_cdev;
890 } 897 }
891 898
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 19f8389291b6..21a2a829bf4e 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/moduleparam.h> 14#include <linux/moduleparam.h>
15#include <linux/watchdog.h> 15#include <linux/watchdog.h>
16#include <linux/smp_lock.h>
16 17
17#include <asm/ebcdic.h> 18#include <asm/ebcdic.h>
18#include <asm/io.h> 19#include <asm/io.h>
@@ -92,23 +93,15 @@ static int vmwdt_keepalive(void)
92 93
93 func = vmwdt_conceal ? (wdt_init | wdt_conceal) : wdt_init; 94 func = vmwdt_conceal ? (wdt_init | wdt_conceal) : wdt_init;
94 ret = __diag288(func, vmwdt_interval, ebc_cmd, len); 95 ret = __diag288(func, vmwdt_interval, ebc_cmd, len);
96 WARN_ON(ret != 0);
95 kfree(ebc_cmd); 97 kfree(ebc_cmd);
96
97 if (ret) {
98 printk(KERN_WARNING "%s: problem setting interval %d, "
99 "cmd %s\n", __func__, vmwdt_interval,
100 vmwdt_cmd);
101 }
102 return ret; 98 return ret;
103} 99}
104 100
105static int vmwdt_disable(void) 101static int vmwdt_disable(void)
106{ 102{
107 int ret = __diag288(wdt_cancel, 0, "", 0); 103 int ret = __diag288(wdt_cancel, 0, "", 0);
108 if (ret) { 104 WARN_ON(ret != 0);
109 printk(KERN_WARNING "%s: problem disabling watchdog\n",
110 __func__);
111 }
112 return ret; 105 return ret;
113} 106}
114 107
@@ -121,21 +114,23 @@ static int __init vmwdt_probe(void)
121 static char __initdata ebc_begin[] = { 114 static char __initdata ebc_begin[] = {
122 194, 197, 199, 201, 213 115 194, 197, 199, 201, 213
123 }; 116 };
124 if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0) { 117 if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0)
125 printk(KERN_INFO "z/VM watchdog not available\n");
126 return -EINVAL; 118 return -EINVAL;
127 }
128 return vmwdt_disable(); 119 return vmwdt_disable();
129} 120}
130 121
131static int vmwdt_open(struct inode *i, struct file *f) 122static int vmwdt_open(struct inode *i, struct file *f)
132{ 123{
133 int ret; 124 int ret;
134 if (test_and_set_bit(0, &vmwdt_is_open)) 125 lock_kernel();
126 if (test_and_set_bit(0, &vmwdt_is_open)) {
127 unlock_kernel();
135 return -EBUSY; 128 return -EBUSY;
129 }
136 ret = vmwdt_keepalive(); 130 ret = vmwdt_keepalive();
137 if (ret) 131 if (ret)
138 clear_bit(0, &vmwdt_is_open); 132 clear_bit(0, &vmwdt_is_open);
133 unlock_kernel();
139 return ret ? ret : nonseekable_open(i, f); 134 return ret ? ret : nonseekable_open(i, f);
140} 135}
141 136
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index bbbd14e9d48f..7fd84be11931 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -29,6 +29,7 @@
29 29
30#define TO_USER 0 30#define TO_USER 0
31#define TO_KERNEL 1 31#define TO_KERNEL 1
32#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
32 33
33enum arch_id { 34enum arch_id {
34 ARCH_S390 = 0, 35 ARCH_S390 = 0,
@@ -51,6 +52,7 @@ static struct debug_info *zcore_dbf;
51static int hsa_available; 52static int hsa_available;
52static struct dentry *zcore_dir; 53static struct dentry *zcore_dir;
53static struct dentry *zcore_file; 54static struct dentry *zcore_file;
55static struct dentry *zcore_memmap_file;
54 56
55/* 57/*
56 * Copy memory from HSA to kernel or user memory (not reentrant): 58 * Copy memory from HSA to kernel or user memory (not reentrant):
@@ -223,12 +225,10 @@ static int __init init_cpu_info(enum arch_id arch)
223 /* get info for boot cpu from lowcore, stored in the HSA */ 225 /* get info for boot cpu from lowcore, stored in the HSA */
224 226
225 sa = kmalloc(sizeof(*sa), GFP_KERNEL); 227 sa = kmalloc(sizeof(*sa), GFP_KERNEL);
226 if (!sa) { 228 if (!sa)
227 ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
228 return -ENOMEM; 229 return -ENOMEM;
229 }
230 if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) { 230 if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
231 ERROR_MSG("could not copy from HSA\n"); 231 TRACE("could not copy from HSA\n");
232 kfree(sa); 232 kfree(sa);
233 return -EIO; 233 return -EIO;
234 } 234 }
@@ -478,6 +478,54 @@ static const struct file_operations zcore_fops = {
478 .release = zcore_release, 478 .release = zcore_release,
479}; 479};
480 480
481static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
482 size_t count, loff_t *ppos)
483{
484 return simple_read_from_buffer(buf, count, ppos, filp->private_data,
485 MEMORY_CHUNKS * CHUNK_INFO_SIZE);
486}
487
488static int zcore_memmap_open(struct inode *inode, struct file *filp)
489{
490 int i;
491 char *buf;
492 struct mem_chunk *chunk_array;
493
494 chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
495 GFP_KERNEL);
496 if (!chunk_array)
497 return -ENOMEM;
498 detect_memory_layout(chunk_array);
499 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
500 if (!buf) {
501 kfree(chunk_array);
502 return -ENOMEM;
503 }
504 for (i = 0; i < MEMORY_CHUNKS; i++) {
505 sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
506 (unsigned long long) chunk_array[i].addr,
507 (unsigned long long) chunk_array[i].size);
508 if (chunk_array[i].size == 0)
509 break;
510 }
511 kfree(chunk_array);
512 filp->private_data = buf;
513 return 0;
514}
515
516static int zcore_memmap_release(struct inode *inode, struct file *filp)
517{
518 kfree(filp->private_data);
519 return 0;
520}
521
522static const struct file_operations zcore_memmap_fops = {
523 .owner = THIS_MODULE,
524 .read = zcore_memmap_read,
525 .open = zcore_memmap_open,
526 .release = zcore_memmap_release,
527};
528
481 529
482static void __init set_s390_lc_mask(union save_area *map) 530static void __init set_s390_lc_mask(union save_area *map)
483{ 531{
@@ -511,6 +559,8 @@ static void __init set_s390x_lc_mask(union save_area *map)
511 */ 559 */
512static int __init sys_info_init(enum arch_id arch) 560static int __init sys_info_init(enum arch_id arch)
513{ 561{
562 int rc;
563
514 switch (arch) { 564 switch (arch) {
515 case ARCH_S390X: 565 case ARCH_S390X:
516 MSG("DETECTED 'S390X (64 bit) OS'\n"); 566 MSG("DETECTED 'S390X (64 bit) OS'\n");
@@ -529,10 +579,9 @@ static int __init sys_info_init(enum arch_id arch)
529 return -EINVAL; 579 return -EINVAL;
530 } 580 }
531 sys_info.arch = arch; 581 sys_info.arch = arch;
532 if (init_cpu_info(arch)) { 582 rc = init_cpu_info(arch);
533 ERROR_MSG("get cpu info failed\n"); 583 if (rc)
534 return -ENOMEM; 584 return rc;
535 }
536 sys_info.mem_size = real_memory_size; 585 sys_info.mem_size = real_memory_size;
537 586
538 return 0; 587 return 0;
@@ -544,29 +593,55 @@ static int __init check_sdias(void)
544 593
545 rc = sclp_sdias_blk_count(); 594 rc = sclp_sdias_blk_count();
546 if (rc < 0) { 595 if (rc < 0) {
547 ERROR_MSG("Could not determine HSA size\n"); 596 TRACE("Could not determine HSA size\n");
548 return rc; 597 return rc;
549 } 598 }
550 act_hsa_size = (rc - 1) * PAGE_SIZE; 599 act_hsa_size = (rc - 1) * PAGE_SIZE;
551 if (act_hsa_size < ZFCPDUMP_HSA_SIZE) { 600 if (act_hsa_size < ZFCPDUMP_HSA_SIZE) {
552 ERROR_MSG("HSA size too small: %i\n", act_hsa_size); 601 TRACE("HSA size too small: %i\n", act_hsa_size);
553 return -EINVAL; 602 return -EINVAL;
554 } 603 }
555 return 0; 604 return 0;
556} 605}
557 606
558static void __init zcore_header_init(int arch, struct zcore_header *hdr) 607static int __init get_mem_size(unsigned long *mem)
559{ 608{
609 int i;
610 struct mem_chunk *chunk_array;
611
612 chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
613 GFP_KERNEL);
614 if (!chunk_array)
615 return -ENOMEM;
616 detect_memory_layout(chunk_array);
617 for (i = 0; i < MEMORY_CHUNKS; i++) {
618 if (chunk_array[i].size == 0)
619 break;
620 *mem += chunk_array[i].size;
621 }
622 kfree(chunk_array);
623 return 0;
624}
625
626static int __init zcore_header_init(int arch, struct zcore_header *hdr)
627{
628 int rc;
629 unsigned long memory = 0;
630
560 if (arch == ARCH_S390X) 631 if (arch == ARCH_S390X)
561 hdr->arch_id = DUMP_ARCH_S390X; 632 hdr->arch_id = DUMP_ARCH_S390X;
562 else 633 else
563 hdr->arch_id = DUMP_ARCH_S390; 634 hdr->arch_id = DUMP_ARCH_S390;
564 hdr->mem_size = sys_info.mem_size; 635 rc = get_mem_size(&memory);
565 hdr->rmem_size = sys_info.mem_size; 636 if (rc)
637 return rc;
638 hdr->mem_size = memory;
639 hdr->rmem_size = memory;
566 hdr->mem_end = sys_info.mem_size; 640 hdr->mem_end = sys_info.mem_size;
567 hdr->num_pages = sys_info.mem_size / PAGE_SIZE; 641 hdr->num_pages = memory / PAGE_SIZE;
568 hdr->tod = get_clock(); 642 hdr->tod = get_clock();
569 get_cpu_id(&hdr->cpu_id); 643 get_cpu_id(&hdr->cpu_id);
644 return 0;
570} 645}
571 646
572static int __init zcore_init(void) 647static int __init zcore_init(void)
@@ -590,16 +665,12 @@ static int __init zcore_init(void)
590 goto fail; 665 goto fail;
591 666
592 rc = check_sdias(); 667 rc = check_sdias();
593 if (rc) { 668 if (rc)
594 ERROR_MSG("Dump initialization failed\n");
595 goto fail; 669 goto fail;
596 }
597 670
598 rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1); 671 rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1);
599 if (rc) { 672 if (rc)
600 ERROR_MSG("sdial memcpy for arch id failed\n");
601 goto fail; 673 goto fail;
602 }
603 674
604#ifndef __s390x__ 675#ifndef __s390x__
605 if (arch == ARCH_S390X) { 676 if (arch == ARCH_S390X) {
@@ -610,12 +681,12 @@ static int __init zcore_init(void)
610#endif 681#endif
611 682
612 rc = sys_info_init(arch); 683 rc = sys_info_init(arch);
613 if (rc) { 684 if (rc)
614 ERROR_MSG("arch init failed\n");
615 goto fail; 685 goto fail;
616 }
617 686
618 zcore_header_init(arch, &zcore_header); 687 rc = zcore_header_init(arch, &zcore_header);
688 if (rc)
689 goto fail;
619 690
620 zcore_dir = debugfs_create_dir("zcore" , NULL); 691 zcore_dir = debugfs_create_dir("zcore" , NULL);
621 if (!zcore_dir) { 692 if (!zcore_dir) {
@@ -625,13 +696,22 @@ static int __init zcore_init(void)
625 zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL, 696 zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,
626 &zcore_fops); 697 &zcore_fops);
627 if (!zcore_file) { 698 if (!zcore_file) {
628 debugfs_remove(zcore_dir);
629 rc = -ENOMEM; 699 rc = -ENOMEM;
630 goto fail; 700 goto fail_dir;
701 }
702 zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir,
703 NULL, &zcore_memmap_fops);
704 if (!zcore_memmap_file) {
705 rc = -ENOMEM;
706 goto fail_file;
631 } 707 }
632 hsa_available = 1; 708 hsa_available = 1;
633 return 0; 709 return 0;
634 710
711fail_file:
712 debugfs_remove(zcore_file);
713fail_dir:
714 debugfs_remove(zcore_dir);
635fail: 715fail:
636 diag308(DIAG308_REL_HSA, NULL); 716 diag308(DIAG308_REL_HSA, NULL);
637 return rc; 717 return rc;