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 | |
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')
-rw-r--r-- | drivers/input/joystick/amijoy.c | 29 | ||||
-rw-r--r-- | drivers/input/joystick/db9.c | 17 | ||||
-rw-r--r-- | drivers/input/joystick/gamecon.c | 19 | ||||
-rw-r--r-- | drivers/input/joystick/turbografx.c | 19 |
4 files changed, 61 insertions, 23 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 | } |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index cfdd3acf06a1..fbd3eed07f90 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); | |||
87 | #define DB9_NORMAL 0x0a | 87 | #define DB9_NORMAL 0x0a |
88 | #define DB9_NOSELECT 0x08 | 88 | #define DB9_NOSELECT 0x08 |
89 | 89 | ||
90 | #define DB9_MAX_DEVICES 2 | 90 | #define DB9_MAX_DEVICES 2 |
91 | 91 | ||
92 | #define DB9_GENESIS6_DELAY 14 | 92 | #define DB9_GENESIS6_DELAY 14 |
93 | #define DB9_REFRESH_TIME HZ/100 | 93 | #define DB9_REFRESH_TIME HZ/100 |
@@ -98,6 +98,7 @@ struct db9 { | |||
98 | struct pardevice *pd; | 98 | struct pardevice *pd; |
99 | int mode; | 99 | int mode; |
100 | int used; | 100 | int used; |
101 | struct semaphore sem; | ||
101 | char phys[2][32]; | 102 | char phys[2][32]; |
102 | }; | 103 | }; |
103 | 104 | ||
@@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev) | |||
503 | { | 504 | { |
504 | struct db9 *db9 = dev->private; | 505 | struct db9 *db9 = dev->private; |
505 | struct parport *port = db9->pd->port; | 506 | struct parport *port = db9->pd->port; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&db9->sem); | ||
510 | if (err) | ||
511 | return err; | ||
506 | 512 | ||
507 | if (!db9->used++) { | 513 | if (!db9->used++) { |
508 | parport_claim(db9->pd); | 514 | parport_claim(db9->pd); |
@@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev) | |||
514 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); | 520 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); |
515 | } | 521 | } |
516 | 522 | ||
523 | up(&db9->sem); | ||
517 | return 0; | 524 | return 0; |
518 | } | 525 | } |
519 | 526 | ||
@@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev) | |||
522 | struct db9 *db9 = dev->private; | 529 | struct db9 *db9 = dev->private; |
523 | struct parport *port = db9->pd->port; | 530 | struct parport *port = db9->pd->port; |
524 | 531 | ||
532 | down(&db9->sem); | ||
525 | if (!--db9->used) { | 533 | if (!--db9->used) { |
526 | del_timer(&db9->timer); | 534 | del_timer_sync(&db9->timer); |
527 | parport_write_control(port, 0x00); | 535 | parport_write_control(port, 0x00); |
528 | parport_data_forward(port); | 536 | parport_data_forward(port); |
529 | parport_release(db9->pd); | 537 | parport_release(db9->pd); |
530 | } | 538 | } |
539 | up(&db9->sem); | ||
531 | } | 540 | } |
532 | 541 | ||
533 | static struct db9 __init *db9_probe(int *config, int nargs) | 542 | static struct db9 __init *db9_probe(int *config, int nargs) |
@@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) | |||
563 | } | 572 | } |
564 | } | 573 | } |
565 | 574 | ||
566 | if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { | 575 | if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { |
567 | parport_put_port(pp); | 576 | parport_put_port(pp); |
568 | return NULL; | 577 | return NULL; |
569 | } | 578 | } |
570 | memset(db9, 0, sizeof(struct db9)); | ||
571 | 579 | ||
580 | init_MUTEX(&db9->sem); | ||
572 | db9->mode = config[1]; | 581 | db9->mode = config[1]; |
573 | init_timer(&db9->timer); | 582 | init_timer(&db9->timer); |
574 | db9->timer.data = (long) db9; | 583 | db9->timer.data = (long) db9; |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 462fc38f026e..95bbdd302aad 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -81,6 +81,7 @@ struct gc { | |||
81 | struct timer_list timer; | 81 | struct timer_list timer; |
82 | unsigned char pads[GC_MAX + 1]; | 82 | unsigned char pads[GC_MAX + 1]; |
83 | int used; | 83 | int used; |
84 | struct semaphore sem; | ||
84 | char phys[5][32]; | 85 | char phys[5][32]; |
85 | }; | 86 | }; |
86 | 87 | ||
@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private) | |||
503 | static int gc_open(struct input_dev *dev) | 504 | static int gc_open(struct input_dev *dev) |
504 | { | 505 | { |
505 | struct gc *gc = dev->private; | 506 | struct gc *gc = dev->private; |
507 | int err; | ||
508 | |||
509 | err = down_interruptible(&gc->sem); | ||
510 | if (err) | ||
511 | return err; | ||
512 | |||
506 | if (!gc->used++) { | 513 | if (!gc->used++) { |
507 | parport_claim(gc->pd); | 514 | parport_claim(gc->pd); |
508 | parport_write_control(gc->pd->port, 0x04); | 515 | parport_write_control(gc->pd->port, 0x04); |
509 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 516 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
510 | } | 517 | } |
518 | |||
519 | up(&gc->sem); | ||
511 | return 0; | 520 | return 0; |
512 | } | 521 | } |
513 | 522 | ||
514 | static void gc_close(struct input_dev *dev) | 523 | static void gc_close(struct input_dev *dev) |
515 | { | 524 | { |
516 | struct gc *gc = dev->private; | 525 | struct gc *gc = dev->private; |
526 | |||
527 | down(&gc->sem); | ||
517 | if (!--gc->used) { | 528 | if (!--gc->used) { |
518 | del_timer(&gc->timer); | 529 | del_timer_sync(&gc->timer); |
519 | parport_write_control(gc->pd->port, 0x00); | 530 | parport_write_control(gc->pd->port, 0x00); |
520 | parport_release(gc->pd); | 531 | parport_release(gc->pd); |
521 | } | 532 | } |
533 | up(&gc->sem); | ||
522 | } | 534 | } |
523 | 535 | ||
524 | static struct gc __init *gc_probe(int *config, int nargs) | 536 | static struct gc __init *gc_probe(int *config, int nargs) |
@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs) | |||
542 | return NULL; | 554 | return NULL; |
543 | } | 555 | } |
544 | 556 | ||
545 | if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { | 557 | if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { |
546 | parport_put_port(pp); | 558 | parport_put_port(pp); |
547 | return NULL; | 559 | return NULL; |
548 | } | 560 | } |
549 | memset(gc, 0, sizeof(struct gc)); | 561 | |
562 | init_MUTEX(&gc->sem); | ||
550 | 563 | ||
551 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 564 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
552 | 565 | ||
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 316c4bebfed2..28100d461cb7 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -84,6 +84,7 @@ static struct tgfx { | |||
84 | char phys[7][32]; | 84 | char phys[7][32]; |
85 | int sticks; | 85 | int sticks; |
86 | int used; | 86 | int used; |
87 | struct semaphore sem; | ||
87 | } *tgfx_base[3]; | 88 | } *tgfx_base[3]; |
88 | 89 | ||
89 | /* | 90 | /* |
@@ -123,22 +124,33 @@ static void tgfx_timer(unsigned long private) | |||
123 | static int tgfx_open(struct input_dev *dev) | 124 | static int tgfx_open(struct input_dev *dev) |
124 | { | 125 | { |
125 | struct tgfx *tgfx = dev->private; | 126 | struct tgfx *tgfx = dev->private; |
127 | int err; | ||
128 | |||
129 | err = down_interruptible(&tgfx->sem); | ||
130 | if (err) | ||
131 | return err; | ||
132 | |||
126 | if (!tgfx->used++) { | 133 | if (!tgfx->used++) { |
127 | parport_claim(tgfx->pd); | 134 | parport_claim(tgfx->pd); |
128 | parport_write_control(tgfx->pd->port, 0x04); | 135 | parport_write_control(tgfx->pd->port, 0x04); |
129 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); | 136 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); |
130 | } | 137 | } |
138 | |||
139 | up(&tgfx->sem); | ||
131 | return 0; | 140 | return 0; |
132 | } | 141 | } |
133 | 142 | ||
134 | static void tgfx_close(struct input_dev *dev) | 143 | static void tgfx_close(struct input_dev *dev) |
135 | { | 144 | { |
136 | struct tgfx *tgfx = dev->private; | 145 | struct tgfx *tgfx = dev->private; |
146 | |||
147 | down(&tgfx->sem); | ||
137 | if (!--tgfx->used) { | 148 | if (!--tgfx->used) { |
138 | del_timer(&tgfx->timer); | 149 | del_timer_sync(&tgfx->timer); |
139 | parport_write_control(tgfx->pd->port, 0x00); | 150 | parport_write_control(tgfx->pd->port, 0x00); |
140 | parport_release(tgfx->pd); | 151 | parport_release(tgfx->pd); |
141 | } | 152 | } |
153 | up(&tgfx->sem); | ||
142 | } | 154 | } |
143 | 155 | ||
144 | /* | 156 | /* |
@@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) | |||
166 | return NULL; | 178 | return NULL; |
167 | } | 179 | } |
168 | 180 | ||
169 | if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { | 181 | if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { |
170 | parport_put_port(pp); | 182 | parport_put_port(pp); |
171 | return NULL; | 183 | return NULL; |
172 | } | 184 | } |
173 | memset(tgfx, 0, sizeof(struct tgfx)); | 185 | |
186 | init_MUTEX(&tgfx->sem); | ||
174 | 187 | ||
175 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 188 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
176 | 189 | ||