summaryrefslogtreecommitdiffstats
path: root/drivers/char/lp.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-18 02:39:39 -0700
committerDavid S. Miller <davem@davemloft.net>2008-07-18 02:39:39 -0700
commit49997d75152b3d23c53b0fa730599f2f74c92c65 (patch)
tree46e93126170d02cfec9505172e545732c1b69656 /drivers/char/lp.c
parenta0c80b80e0fb48129e4e9d6a9ede914f9ff1850d (diff)
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
downloadkernel-crypto-49997d75152b3d23c53b0fa730599f2f74c92c65.tar.gz
kernel-crypto-49997d75152b3d23c53b0fa730599f2f74c92c65.tar.xz
kernel-crypto-49997d75152b3d23c53b0fa730599f2f74c92c65.zip
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: Documentation/powerpc/booting-without-of.txt drivers/atm/Makefile drivers/net/fs_enet/fs_enet-main.c drivers/pci/pci-acpi.c net/8021q/vlan.c net/iucv/iucv.c
Diffstat (limited to 'drivers/char/lp.c')
-rw-r--r--drivers/char/lp.c38
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)