diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-05-29 03:29:52 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-05-29 03:29:52 -0400 |
commit | 8b1a198bf14d59b67e47dc7b133ec5ea443fb40d (patch) | |
tree | 11d80109ddc2f61de6a75a37941346100a67a0d1 /drivers/input/joystick/amijoy.c | |
parent | af246041277674854383cf91b8f0b01217b521e8 (diff) |
Input: fix open/close races in joystick drivers - add a semaphore
to the ones that register more than one input device.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/joystick/amijoy.c')
-rw-r--r-- | drivers/input/joystick/amijoy.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index cf36ca9b92f3..033456bb9fe0 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is | |||
51 | 51 | ||
52 | __obsolete_setup("amijoy="); | 52 | __obsolete_setup("amijoy="); |
53 | 53 | ||
54 | static int amijoy_used[2] = { 0, 0 }; | 54 | static int amijoy_used; |
55 | static DECLARE_MUTEX(amijoy_sem); | ||
55 | static struct input_dev amijoy_dev[2]; | 56 | static struct input_dev amijoy_dev[2]; |
56 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; | 57 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; |
57 | 58 | ||
@@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
84 | 85 | ||
85 | static int amijoy_open(struct input_dev *dev) | 86 | static int amijoy_open(struct input_dev *dev) |
86 | { | 87 | { |
87 | int *used = dev->private; | 88 | int err; |
88 | 89 | ||
89 | if ((*used)++) | 90 | err = down_interruptible(&amijoy_sem); |
90 | return 0; | 91 | if (err) |
92 | return err; | ||
91 | 93 | ||
92 | if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { | 94 | if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { |
93 | (*used)--; | ||
94 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 95 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
95 | return -EBUSY; | 96 | err = -EBUSY; |
97 | goto out; | ||
96 | } | 98 | } |
97 | 99 | ||
98 | return 0; | 100 | amijoy_used++; |
101 | out: | ||
102 | up(&amijoy_sem); | ||
103 | return err; | ||
99 | } | 104 | } |
100 | 105 | ||
101 | static void amijoy_close(struct input_dev *dev) | 106 | static void amijoy_close(struct input_dev *dev) |
102 | { | 107 | { |
103 | int *used = dev->private; | 108 | down(&amijoysem); |
104 | 109 | if (!--amijoy_used) | |
105 | if (!--(*used)) | ||
106 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); | 110 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); |
111 | up(&amijoy_sem); | ||
107 | } | 112 | } |
108 | 113 | ||
109 | static int __init amijoy_init(void) | 114 | static int __init amijoy_init(void) |
@@ -138,8 +143,6 @@ static int __init amijoy_init(void) | |||
138 | amijoy_dev[i].id.product = 0x0003; | 143 | amijoy_dev[i].id.product = 0x0003; |
139 | amijoy_dev[i].id.version = 0x0100; | 144 | amijoy_dev[i].id.version = 0x0100; |
140 | 145 | ||
141 | amijoy_dev[i].private = amijoy_used + i; | ||
142 | |||
143 | input_register_device(amijoy_dev + i); | 146 | input_register_device(amijoy_dev + i); |
144 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); | 147 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); |
145 | } | 148 | } |