diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 20:19:14 +0100 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-07-15 20:19:14 +0100 |
commit | 0c17e4ceedd35c78b1c7413dbd16279a350be6bc (patch) | |
tree | 313b3b9ca04727f3704464e01d8dd97da1dd534b /drivers/char/lp.c | |
parent | 19c1d6a34abf73d0baf8e325d018c920fa78dddc (diff) | |
parent | b9d2252c1e44fa83a4e65fdc9eb93db6297c55af (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-rmk
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) |