diff options
-rw-r--r-- | drivers/char/lp.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 60ac642752be..71abb4c33aa2 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -126,6 +126,7 @@ | |||
126 | #include <linux/device.h> | 126 | #include <linux/device.h> |
127 | #include <linux/wait.h> | 127 | #include <linux/wait.h> |
128 | #include <linux/jiffies.h> | 128 | #include <linux/jiffies.h> |
129 | #include <linux/smp_lock.h> | ||
129 | 130 | ||
130 | #include <linux/parport.h> | 131 | #include <linux/parport.h> |
131 | #undef LP_STATS | 132 | #undef LP_STATS |
@@ -489,14 +490,21 @@ static ssize_t lp_read(struct file * file, char __user * buf, | |||
489 | static int lp_open(struct inode * inode, struct file * file) | 490 | static int lp_open(struct inode * inode, struct file * file) |
490 | { | 491 | { |
491 | unsigned int minor = iminor(inode); | 492 | unsigned int minor = iminor(inode); |
493 | int ret = 0; | ||
492 | 494 | ||
493 | if (minor >= LP_NO) | 495 | lock_kernel(); |
494 | return -ENXIO; | 496 | if (minor >= LP_NO) { |
495 | if ((LP_F(minor) & LP_EXIST) == 0) | 497 | ret = -ENXIO; |
496 | return -ENXIO; | 498 | goto out; |
497 | if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) | 499 | } |
498 | return -EBUSY; | 500 | if ((LP_F(minor) & LP_EXIST) == 0) { |
499 | 501 | ret = -ENXIO; | |
502 | goto out; | ||
503 | } | ||
504 | if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) { | ||
505 | ret = -EBUSY; | ||
506 | goto out; | ||
507 | } | ||
500 | /* If ABORTOPEN is set and the printer is offline or out of paper, | 508 | /* If ABORTOPEN is set and the printer is offline or out of paper, |
501 | we may still want to open it to perform ioctl()s. Therefore we | 509 | we may still want to open it to perform ioctl()s. Therefore we |
502 | have commandeered O_NONBLOCK, even though it is being used in | 510 | have commandeered O_NONBLOCK, even though it is being used in |
@@ -510,21 +518,25 @@ static int lp_open(struct inode * inode, struct file * file) | |||
510 | if (status & LP_POUTPA) { | 518 | if (status & LP_POUTPA) { |
511 | printk(KERN_INFO "lp%d out of paper\n", minor); | 519 | printk(KERN_INFO "lp%d out of paper\n", minor); |
512 | LP_F(minor) &= ~LP_BUSY; | 520 | LP_F(minor) &= ~LP_BUSY; |
513 | return -ENOSPC; | 521 | ret = -ENOSPC; |
522 | goto out; | ||
514 | } else if (!(status & LP_PSELECD)) { | 523 | } else if (!(status & LP_PSELECD)) { |
515 | printk(KERN_INFO "lp%d off-line\n", minor); | 524 | printk(KERN_INFO "lp%d off-line\n", minor); |
516 | LP_F(minor) &= ~LP_BUSY; | 525 | LP_F(minor) &= ~LP_BUSY; |
517 | return -EIO; | 526 | ret = -EIO; |
527 | goto out; | ||
518 | } else if (!(status & LP_PERRORP)) { | 528 | } else if (!(status & LP_PERRORP)) { |
519 | printk(KERN_ERR "lp%d printer error\n", minor); | 529 | printk(KERN_ERR "lp%d printer error\n", minor); |
520 | LP_F(minor) &= ~LP_BUSY; | 530 | LP_F(minor) &= ~LP_BUSY; |
521 | return -EIO; | 531 | ret = -EIO; |
532 | goto out; | ||
522 | } | 533 | } |
523 | } | 534 | } |
524 | lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); | 535 | lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); |
525 | if (!lp_table[minor].lp_buffer) { | 536 | if (!lp_table[minor].lp_buffer) { |
526 | LP_F(minor) &= ~LP_BUSY; | 537 | LP_F(minor) &= ~LP_BUSY; |
527 | return -ENOMEM; | 538 | ret = -ENOMEM; |
539 | goto out; | ||
528 | } | 540 | } |
529 | /* Determine if the peripheral supports ECP mode */ | 541 | /* Determine if the peripheral supports ECP mode */ |
530 | lp_claim_parport_or_block (&lp_table[minor]); | 542 | lp_claim_parport_or_block (&lp_table[minor]); |
@@ -540,7 +552,9 @@ static int lp_open(struct inode * inode, struct file * file) | |||
540 | parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); | 552 | parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); |
541 | lp_release_parport (&lp_table[minor]); | 553 | lp_release_parport (&lp_table[minor]); |
542 | lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; | 554 | lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; |
543 | return 0; | 555 | out: |
556 | unlock_kernel(); | ||
557 | return ret; | ||
544 | } | 558 | } |
545 | 559 | ||
546 | static int lp_release(struct inode * inode, struct file * file) | 560 | static int lp_release(struct inode * inode, struct file * file) |