diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-18 19:31:12 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-18 19:31:12 +0200 |
commit | 3e370b29d35fb01bfb92c2814d6f79bf6a2cb970 (patch) | |
tree | 3b8fb467d60bfe6a34686f4abdc3a60050ba40a4 /drivers/char/lp.c | |
parent | 88d1dce3a74367291f65a757fbdcaf17f042f30c (diff) | |
parent | 5b664cb235e97afbf34db9c4d77f08ebd725335e (diff) |
Merge branch 'linus' into x86/pci-ioapic-boot-irq-quirks
Conflicts:
drivers/pci/quirks.c
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/char/lp.c')
-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 60ac642752b..71abb4c33aa 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -126,6 +126,7 @@ #include <linux/device.h> #include <linux/wait.h> #include <linux/jiffies.h> +#include <linux/smp_lock.h> #include <linux/parport.h> #undef LP_STATS @@ -489,14 +490,21 @@ static ssize_t lp_read(struct file * file, char __user * buf, static int lp_open(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); + int ret = 0; - if (minor >= LP_NO) - return -ENXIO; - if ((LP_F(minor) & LP_EXIST) == 0) - return -ENXIO; - if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) - return -EBUSY; - + lock_kernel(); + if (minor >= LP_NO) { + ret = -ENXIO; + goto out; + } + if ((LP_F(minor) & LP_EXIST) == 0) { + ret = -ENXIO; + goto out; + } + if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) { + ret = -EBUSY; + goto out; + } /* If ABORTOPEN is set and the printer is offline or out of paper, we may still want to open it to perform ioctl()s. Therefore we 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) if (status & LP_POUTPA) { printk(KERN_INFO "lp%d out of paper\n", minor); LP_F(minor) &= ~LP_BUSY; - return -ENOSPC; + ret = -ENOSPC; + goto out; } else if (!(status & LP_PSELECD)) { printk(KERN_INFO "lp%d off-line\n", minor); LP_F(minor) &= ~LP_BUSY; - return -EIO; + ret = -EIO; + goto out; } else if (!(status & LP_PERRORP)) { printk(KERN_ERR "lp%d printer error\n", minor); LP_F(minor) &= ~LP_BUSY; - return -EIO; + ret = -EIO; + goto out; } } lp_table[minor].lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) { LP_F(minor) &= ~LP_BUSY; - return -ENOMEM; + ret = -ENOMEM; + goto out; } /* Determine if the peripheral supports ECP mode */ lp_claim_parport_or_block (&lp_table[minor]); @@ -540,7 +552,9 @@ static int lp_open(struct inode * inode, struct file * file) parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT); lp_release_parport (&lp_table[minor]); lp_table[minor].current_mode = IEEE1284_MODE_COMPAT; - return 0; +out: + unlock_kernel(); + return ret; } static int lp_release(struct inode * inode, struct file * file) |