diff options
Diffstat (limited to 'drivers/s390/char/fs3270.c')
-rw-r--r-- | drivers/s390/char/fs3270.c | 34 |
1 files changed, 20 insertions, 14 deletions
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 | |||
216 | fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb) | 217 | fs3270_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; |
479 | out: | ||
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 | ||