aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 03:29:52 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2005-05-29 03:29:52 -0400
commit8b1a198bf14d59b67e47dc7b133ec5ea443fb40d (patch)
tree11d80109ddc2f61de6a75a37941346100a67a0d1 /drivers/input/joystick
parentaf246041277674854383cf91b8f0b01217b521e8 (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.c29
-rw-r--r--drivers/input/joystick/db9.c17
-rw-r--r--drivers/input/joystick/gamecon.c19
-rw-r--r--drivers/input/joystick/turbografx.c19
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
54static int amijoy_used[2] = { 0, 0 }; 54static int amijoy_used;
55static DECLARE_MUTEX(amijoy_sem);
55static struct input_dev amijoy_dev[2]; 56static struct input_dev amijoy_dev[2];
56static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; 57static 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
85static int amijoy_open(struct input_dev *dev) 86static 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++;
101out:
102 up(&amijoy_sem);
103 return err;
99} 104}
100 105
101static void amijoy_close(struct input_dev *dev) 106static 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
109static int __init amijoy_init(void) 114static 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
533static struct db9 __init *db9_probe(int *config, int nargs) 542static 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)
503static int gc_open(struct input_dev *dev) 504static 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
514static void gc_close(struct input_dev *dev) 523static 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
524static struct gc __init *gc_probe(int *config, int nargs) 536static 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)
123static int tgfx_open(struct input_dev *dev) 124static 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
134static void tgfx_close(struct input_dev *dev) 143static 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