diff options
Diffstat (limited to 'drivers/input/joystick/turbografx.c')
-rw-r--r-- | drivers/input/joystick/turbografx.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dd88b9cb49fa..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 | /* |
@@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private) | |||
99 | for (i = 0; i < 7; i++) | 100 | for (i = 0; i < 7; i++) |
100 | if (tgfx->sticks & (1 << i)) { | 101 | if (tgfx->sticks & (1 << i)) { |
101 | 102 | ||
102 | dev = tgfx->dev + i; | 103 | dev = tgfx->dev + i; |
103 | 104 | ||
104 | parport_write_data(tgfx->pd->port, ~(1 << i)); | 105 | parport_write_data(tgfx->pd->port, ~(1 << i)); |
105 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; | 106 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; |
@@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private) | |||
122 | 123 | ||
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; |
126 | if (!tgfx->used++) { | 127 | int err; |
128 | |||
129 | err = down_interruptible(&tgfx->sem); | ||
130 | if (err) | ||
131 | return err; | ||
132 | |||
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 | } |
131 | return 0; | 138 | |
139 | up(&tgfx->sem); | ||
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; |
137 | if (!--tgfx->used) { | 146 | |
138 | del_timer(&tgfx->timer); | 147 | down(&tgfx->sem); |
148 | if (!--tgfx->used) { | ||
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 | ||