diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-17 12:31:34 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-02-17 11:48:22 -0500 |
commit | 94a819f80297e1f635a7cde4ed5317612e512ba7 (patch) | |
tree | 9bbb1eab3a0f0c722fe40295fb512d99cc0190d9 | |
parent | 3d068261854b00c930df4516cd617900935e7706 (diff) |
pcmcia: assert locking to struct pcmcia_device
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r-- | Documentation/pcmcia/locking.txt | 25 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 38 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 122 |
3 files changed, 129 insertions, 56 deletions
diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt index 5f25de4cdb42..d6251056128f 100644 --- a/Documentation/pcmcia/locking.txt +++ b/Documentation/pcmcia/locking.txt | |||
@@ -90,3 +90,28 @@ or single-use fields not mentioned): | |||
90 | struct list_head devices_list; | 90 | struct list_head devices_list; |
91 | u8 device_count; | 91 | u8 device_count; |
92 | struct pcmcia_state; | 92 | struct pcmcia_state; |
93 | |||
94 | |||
95 | 3. Per PCMCIA-device Data: | ||
96 | -------------------------- | ||
97 | |||
98 | The "main" struct pcmcia_devie is protected as follows (read-only fields | ||
99 | or single-use fields not mentioned): | ||
100 | |||
101 | |||
102 | - by pcmcia_socket->ops_mutex: | ||
103 | struct list_head socket_device_list; | ||
104 | struct config_t *function_config; | ||
105 | u16 _irq:1; | ||
106 | u16 _io:1; | ||
107 | u16 _win:4; | ||
108 | u16 _locked:1; | ||
109 | u16 allow_func_id_match:1; | ||
110 | u16 suspended:1; | ||
111 | u16 _removed:1; | ||
112 | |||
113 | - by the PCMCIA driver: | ||
114 | io_req_t io; | ||
115 | irq_req_t irq; | ||
116 | config_req_t conf; | ||
117 | window_handle_t win; | ||
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4c40db8889d9..83b51ddd3da3 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -835,6 +835,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
835 | } | 835 | } |
836 | 836 | ||
837 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { | 837 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { |
838 | int ret; | ||
839 | |||
838 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) | 840 | if ((!dev->has_func_id) || (dev->func_id != did->func_id)) |
839 | return 0; | 841 | return 0; |
840 | 842 | ||
@@ -849,10 +851,15 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
849 | * after it has re-checked that there is no possible module | 851 | * after it has re-checked that there is no possible module |
850 | * with a prod_id/manf_id/card_id match. | 852 | * with a prod_id/manf_id/card_id match. |
851 | */ | 853 | */ |
852 | dev_dbg(&dev->dev, | 854 | mutex_lock(&dev->socket->ops_mutex); |
853 | "skipping FUNC_ID match until userspace interaction\n"); | 855 | ret = dev->allow_func_id_match; |
854 | if (!dev->allow_func_id_match) | 856 | mutex_unlock(&dev->socket->ops_mutex); |
857 | |||
858 | if (!ret) { | ||
859 | dev_dbg(&dev->dev, | ||
860 | "skipping FUNC_ID match until userspace ACK\n"); | ||
855 | return 0; | 861 | return 0; |
862 | } | ||
856 | } | 863 | } |
857 | 864 | ||
858 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { | 865 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { |
@@ -1079,9 +1086,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
1079 | if (!count) | 1086 | if (!count) |
1080 | return -EINVAL; | 1087 | return -EINVAL; |
1081 | 1088 | ||
1082 | mutex_lock(&p_dev->socket->skt_mutex); | 1089 | mutex_lock(&p_dev->socket->ops_mutex); |
1083 | p_dev->allow_func_id_match = 1; | 1090 | p_dev->allow_func_id_match = 1; |
1084 | mutex_unlock(&p_dev->socket->skt_mutex); | 1091 | mutex_unlock(&p_dev->socket->ops_mutex); |
1085 | 1092 | ||
1086 | ret = bus_rescan_devices(&pcmcia_bus_type); | 1093 | ret = bus_rescan_devices(&pcmcia_bus_type); |
1087 | if (ret) | 1094 | if (ret) |
@@ -1114,8 +1121,13 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
1114 | struct pcmcia_driver *p_drv = NULL; | 1121 | struct pcmcia_driver *p_drv = NULL; |
1115 | int ret = 0; | 1122 | int ret = 0; |
1116 | 1123 | ||
1117 | if (p_dev->suspended) | 1124 | mutex_lock(&p_dev->socket->ops_mutex); |
1125 | if (p_dev->suspended) { | ||
1126 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1118 | return 0; | 1127 | return 0; |
1128 | } | ||
1129 | p_dev->suspended = 1; | ||
1130 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1119 | 1131 | ||
1120 | dev_dbg(dev, "suspending\n"); | 1132 | dev_dbg(dev, "suspending\n"); |
1121 | 1133 | ||
@@ -1132,6 +1144,9 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
1132 | "pcmcia: device %s (driver %s) did " | 1144 | "pcmcia: device %s (driver %s) did " |
1133 | "not want to go to sleep (%d)\n", | 1145 | "not want to go to sleep (%d)\n", |
1134 | p_dev->devname, p_drv->drv.name, ret); | 1146 | p_dev->devname, p_drv->drv.name, ret); |
1147 | mutex_lock(&p_dev->socket->ops_mutex); | ||
1148 | p_dev->suspended = 0; | ||
1149 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1135 | goto out; | 1150 | goto out; |
1136 | } | 1151 | } |
1137 | } | 1152 | } |
@@ -1142,8 +1157,6 @@ static int pcmcia_dev_suspend(struct device *dev, pm_message_t state) | |||
1142 | } | 1157 | } |
1143 | 1158 | ||
1144 | out: | 1159 | out: |
1145 | if (!ret) | ||
1146 | p_dev->suspended = 1; | ||
1147 | return ret; | 1160 | return ret; |
1148 | } | 1161 | } |
1149 | 1162 | ||
@@ -1154,8 +1167,13 @@ static int pcmcia_dev_resume(struct device *dev) | |||
1154 | struct pcmcia_driver *p_drv = NULL; | 1167 | struct pcmcia_driver *p_drv = NULL; |
1155 | int ret = 0; | 1168 | int ret = 0; |
1156 | 1169 | ||
1157 | if (!p_dev->suspended) | 1170 | mutex_lock(&p_dev->socket->ops_mutex); |
1171 | if (!p_dev->suspended) { | ||
1172 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1158 | return 0; | 1173 | return 0; |
1174 | } | ||
1175 | p_dev->suspended = 0; | ||
1176 | mutex_unlock(&p_dev->socket->ops_mutex); | ||
1159 | 1177 | ||
1160 | dev_dbg(dev, "resuming\n"); | 1178 | dev_dbg(dev, "resuming\n"); |
1161 | 1179 | ||
@@ -1176,8 +1194,6 @@ static int pcmcia_dev_resume(struct device *dev) | |||
1176 | ret = p_drv->resume(p_dev); | 1194 | ret = p_drv->resume(p_dev); |
1177 | 1195 | ||
1178 | out: | 1196 | out: |
1179 | if (!ret) | ||
1180 | p_dev->suspended = 0; | ||
1181 | return ret; | 1197 | return ret; |
1182 | } | 1198 | } |
1183 | 1199 | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f0de7b8b123b..b2df04199a21 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -191,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | 192 | ||
193 | s = p_dev->socket; | 193 | s = p_dev->socket; |
194 | |||
195 | mutex_lock(&s->ops_mutex); | ||
194 | c = p_dev->function_config; | 196 | c = p_dev->function_config; |
195 | 197 | ||
196 | if (!(c->state & CONFIG_LOCKED)) { | 198 | if (!(c->state & CONFIG_LOCKED)) { |
197 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 199 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); |
200 | mutex_unlock(&s->ops_mutex); | ||
198 | return -EACCES; | 201 | return -EACCES; |
199 | } | 202 | } |
200 | 203 | ||
201 | addr = (c->ConfigBase + reg->Offset) >> 1; | 204 | addr = (c->ConfigBase + reg->Offset) >> 1; |
205 | mutex_unlock(&s->ops_mutex); | ||
202 | 206 | ||
203 | switch (reg->Action) { | 207 | switch (reg->Action) { |
204 | case CS_READ: | 208 | case CS_READ: |
@@ -254,19 +258,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
254 | config_t *c; | 258 | config_t *c; |
255 | 259 | ||
256 | s = p_dev->socket; | 260 | s = p_dev->socket; |
261 | |||
262 | mutex_lock(&s->ops_mutex); | ||
257 | c = p_dev->function_config; | 263 | c = p_dev->function_config; |
258 | 264 | ||
259 | if (!(s->state & SOCKET_PRESENT)) { | 265 | if (!(s->state & SOCKET_PRESENT)) { |
260 | dev_dbg(&s->dev, "No card present\n"); | 266 | dev_dbg(&s->dev, "No card present\n"); |
267 | mutex_unlock(&s->ops_mutex); | ||
261 | return -ENODEV; | 268 | return -ENODEV; |
262 | } | 269 | } |
263 | if (!(c->state & CONFIG_LOCKED)) { | 270 | if (!(c->state & CONFIG_LOCKED)) { |
264 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); | 271 | dev_dbg(&s->dev, "Configuration isnt't locked\n"); |
272 | mutex_unlock(&s->ops_mutex); | ||
265 | return -EACCES; | 273 | return -EACCES; |
266 | } | 274 | } |
267 | 275 | ||
268 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { | 276 | if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { |
269 | mutex_lock(&s->ops_mutex); | ||
270 | if (mod->Attributes & CONF_ENABLE_IRQ) { | 277 | if (mod->Attributes & CONF_ENABLE_IRQ) { |
271 | c->Attributes |= CONF_ENABLE_IRQ; | 278 | c->Attributes |= CONF_ENABLE_IRQ; |
272 | s->socket.io_irq = s->irq.AssignedIRQ; | 279 | s->socket.io_irq = s->irq.AssignedIRQ; |
@@ -275,7 +282,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
275 | s->socket.io_irq = 0; | 282 | s->socket.io_irq = 0; |
276 | } | 283 | } |
277 | s->ops->set_socket(s, &s->socket); | 284 | s->ops->set_socket(s, &s->socket); |
278 | mutex_unlock(&s->ops_mutex); | ||
279 | } | 285 | } |
280 | 286 | ||
281 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { | 287 | if (mod->Attributes & CONF_VCC_CHANGE_VALID) { |
@@ -288,9 +294,9 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
288 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 294 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
289 | if (mod->Vpp1 != mod->Vpp2) { | 295 | if (mod->Vpp1 != mod->Vpp2) { |
290 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); | 296 | dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); |
297 | mutex_unlock(&s->ops_mutex); | ||
291 | return -EINVAL; | 298 | return -EINVAL; |
292 | } | 299 | } |
293 | mutex_lock(&s->ops_mutex); | ||
294 | s->socket.Vpp = mod->Vpp1; | 300 | s->socket.Vpp = mod->Vpp1; |
295 | if (s->ops->set_socket(s, &s->socket)) { | 301 | if (s->ops->set_socket(s, &s->socket)) { |
296 | mutex_unlock(&s->ops_mutex); | 302 | mutex_unlock(&s->ops_mutex); |
@@ -298,10 +304,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
298 | "Unable to set VPP\n"); | 304 | "Unable to set VPP\n"); |
299 | return -EIO; | 305 | return -EIO; |
300 | } | 306 | } |
301 | mutex_unlock(&s->ops_mutex); | ||
302 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 307 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
303 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 308 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
304 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); | 309 | dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); |
310 | mutex_unlock(&s->ops_mutex); | ||
305 | return -EINVAL; | 311 | return -EINVAL; |
306 | } | 312 | } |
307 | 313 | ||
@@ -311,7 +317,6 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
311 | int i; | 317 | int i; |
312 | 318 | ||
313 | io_on.speed = io_speed; | 319 | io_on.speed = io_speed; |
314 | mutex_lock(&s->ops_mutex); | ||
315 | for (i = 0; i < MAX_IO_WIN; i++) { | 320 | for (i = 0; i < MAX_IO_WIN; i++) { |
316 | if (!s->io[i].res) | 321 | if (!s->io[i].res) |
317 | continue; | 322 | continue; |
@@ -326,8 +331,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
326 | mdelay(40); | 331 | mdelay(40); |
327 | s->ops->set_io_map(s, &io_on); | 332 | s->ops->set_io_map(s, &io_on); |
328 | } | 333 | } |
329 | mutex_unlock(&s->ops_mutex); | ||
330 | } | 334 | } |
335 | mutex_unlock(&s->ops_mutex); | ||
331 | 336 | ||
332 | return 0; | 337 | return 0; |
333 | } /* modify_configuration */ | 338 | } /* modify_configuration */ |
@@ -338,10 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
338 | { | 343 | { |
339 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 344 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
340 | struct pcmcia_socket *s = p_dev->socket; | 345 | struct pcmcia_socket *s = p_dev->socket; |
341 | config_t *c = p_dev->function_config; | 346 | config_t *c; |
342 | int i; | 347 | int i; |
343 | 348 | ||
344 | mutex_lock(&s->ops_mutex); | 349 | mutex_lock(&s->ops_mutex); |
350 | c = p_dev->function_config; | ||
345 | if (p_dev->_locked) { | 351 | if (p_dev->_locked) { |
346 | p_dev->_locked = 0; | 352 | p_dev->_locked = 0; |
347 | if (--(s->lock_count) == 0) { | 353 | if (--(s->lock_count) == 0) { |
@@ -381,10 +387,14 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
381 | static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | 387 | static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) |
382 | { | 388 | { |
383 | struct pcmcia_socket *s = p_dev->socket; | 389 | struct pcmcia_socket *s = p_dev->socket; |
384 | config_t *c = p_dev->function_config; | 390 | int ret = -EINVAL; |
391 | config_t *c; | ||
392 | |||
393 | mutex_lock(&s->ops_mutex); | ||
394 | c = p_dev->function_config; | ||
385 | 395 | ||
386 | if (!p_dev->_io) | 396 | if (!p_dev->_io) |
387 | return -EINVAL; | 397 | goto out; |
388 | 398 | ||
389 | p_dev->_io = 0; | 399 | p_dev->_io = 0; |
390 | 400 | ||
@@ -392,7 +402,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
392 | (c->io.NumPorts1 != req->NumPorts1) || | 402 | (c->io.NumPorts1 != req->NumPorts1) || |
393 | (c->io.BasePort2 != req->BasePort2) || | 403 | (c->io.BasePort2 != req->BasePort2) || |
394 | (c->io.NumPorts2 != req->NumPorts2)) | 404 | (c->io.NumPorts2 != req->NumPorts2)) |
395 | return -EINVAL; | 405 | goto out; |
396 | 406 | ||
397 | c->state &= ~CONFIG_IO_REQ; | 407 | c->state &= ~CONFIG_IO_REQ; |
398 | 408 | ||
@@ -400,30 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
400 | if (req->NumPorts2) | 410 | if (req->NumPorts2) |
401 | release_io_space(s, req->BasePort2, req->NumPorts2); | 411 | release_io_space(s, req->BasePort2, req->NumPorts2); |
402 | 412 | ||
403 | return 0; | 413 | out: |
414 | mutex_unlock(&s->ops_mutex); | ||
415 | |||
416 | return ret; | ||
404 | } /* pcmcia_release_io */ | 417 | } /* pcmcia_release_io */ |
405 | 418 | ||
406 | 419 | ||
407 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 420 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) |
408 | { | 421 | { |
409 | struct pcmcia_socket *s = p_dev->socket; | 422 | struct pcmcia_socket *s = p_dev->socket; |
410 | config_t *c = p_dev->function_config; | 423 | config_t *c; |
424 | int ret = -EINVAL; | ||
425 | |||
426 | mutex_lock(&s->ops_mutex); | ||
427 | |||
428 | c = p_dev->function_config; | ||
411 | 429 | ||
412 | if (!p_dev->_irq) | 430 | if (!p_dev->_irq) |
413 | return -EINVAL; | 431 | goto out; |
432 | |||
414 | p_dev->_irq = 0; | 433 | p_dev->_irq = 0; |
415 | 434 | ||
416 | if (c->state & CONFIG_LOCKED) | 435 | if (c->state & CONFIG_LOCKED) |
417 | return -EACCES; | 436 | goto out; |
437 | |||
418 | if (c->irq.Attributes != req->Attributes) { | 438 | if (c->irq.Attributes != req->Attributes) { |
419 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); | 439 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); |
420 | return -EINVAL; | 440 | goto out; |
421 | } | 441 | } |
422 | mutex_lock(&s->ops_mutex); | ||
423 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | 442 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { |
424 | mutex_unlock(&s->ops_mutex); | ||
425 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); | 443 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); |
426 | return -EINVAL; | 444 | goto out; |
427 | } | 445 | } |
428 | if (--s->irq.Config == 0) { | 446 | if (--s->irq.Config == 0) { |
429 | c->state &= ~CONFIG_IRQ_REQ; | 447 | c->state &= ~CONFIG_IRQ_REQ; |
@@ -436,9 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
436 | #ifdef CONFIG_PCMCIA_PROBE | 454 | #ifdef CONFIG_PCMCIA_PROBE |
437 | pcmcia_used_irq[req->AssignedIRQ]--; | 455 | pcmcia_used_irq[req->AssignedIRQ]--; |
438 | #endif | 456 | #endif |
457 | ret = 0; | ||
458 | |||
459 | out: | ||
439 | mutex_unlock(&s->ops_mutex); | 460 | mutex_unlock(&s->ops_mutex); |
440 | 461 | ||
441 | return 0; | 462 | return ret; |
442 | } /* pcmcia_release_irq */ | 463 | } /* pcmcia_release_irq */ |
443 | 464 | ||
444 | 465 | ||
@@ -495,13 +516,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
495 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); | 516 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); |
496 | return -EINVAL; | 517 | return -EINVAL; |
497 | } | 518 | } |
519 | |||
520 | mutex_lock(&s->ops_mutex); | ||
498 | c = p_dev->function_config; | 521 | c = p_dev->function_config; |
499 | if (c->state & CONFIG_LOCKED) { | 522 | if (c->state & CONFIG_LOCKED) { |
523 | mutex_unlock(&s->ops_mutex); | ||
500 | dev_dbg(&s->dev, "Configuration is locked\n"); | 524 | dev_dbg(&s->dev, "Configuration is locked\n"); |
501 | return -EACCES; | 525 | return -EACCES; |
502 | } | 526 | } |
503 | 527 | ||
504 | mutex_lock(&s->ops_mutex); | ||
505 | /* Do power control. We don't allow changes in Vcc. */ | 528 | /* Do power control. We don't allow changes in Vcc. */ |
506 | s->socket.Vpp = req->Vpp; | 529 | s->socket.Vpp = req->Vpp; |
507 | if (s->ops->set_socket(s, &s->socket)) { | 530 | if (s->ops->set_socket(s, &s->socket)) { |
@@ -615,58 +638,65 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
615 | { | 638 | { |
616 | struct pcmcia_socket *s = p_dev->socket; | 639 | struct pcmcia_socket *s = p_dev->socket; |
617 | config_t *c; | 640 | config_t *c; |
641 | int ret = -EINVAL; | ||
642 | |||
643 | mutex_lock(&s->ops_mutex); | ||
618 | 644 | ||
619 | if (!(s->state & SOCKET_PRESENT)) { | 645 | if (!(s->state & SOCKET_PRESENT)) { |
620 | dev_dbg(&s->dev, "No card present\n"); | 646 | dev_dbg(&s->dev, "No card present\n"); |
621 | return -ENODEV; | 647 | goto out; |
622 | } | 648 | } |
623 | 649 | ||
624 | if (!req) | 650 | if (!req) |
625 | return -EINVAL; | 651 | goto out; |
652 | |||
626 | c = p_dev->function_config; | 653 | c = p_dev->function_config; |
627 | if (c->state & CONFIG_LOCKED) { | 654 | if (c->state & CONFIG_LOCKED) { |
628 | dev_dbg(&s->dev, "Configuration is locked\n"); | 655 | dev_dbg(&s->dev, "Configuration is locked\n"); |
629 | return -EACCES; | 656 | goto out; |
630 | } | 657 | } |
631 | if (c->state & CONFIG_IO_REQ) { | 658 | if (c->state & CONFIG_IO_REQ) { |
632 | dev_dbg(&s->dev, "IO already configured\n"); | 659 | dev_dbg(&s->dev, "IO already configured\n"); |
633 | return -EBUSY; | 660 | goto out; |
634 | } | 661 | } |
635 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { | 662 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { |
636 | dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); | 663 | dev_dbg(&s->dev, "bad attribute setting for IO region 1\n"); |
637 | return -EINVAL; | 664 | goto out; |
638 | } | 665 | } |
639 | if ((req->NumPorts2 > 0) && | 666 | if ((req->NumPorts2 > 0) && |
640 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { | 667 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { |
641 | dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); | 668 | dev_dbg(&s->dev, "bad attribute setting for IO region 2\n"); |
642 | return -EINVAL; | 669 | goto out; |
643 | } | 670 | } |
644 | 671 | ||
645 | mutex_lock(&s->ops_mutex); | ||
646 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); | 672 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); |
647 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | 673 | ret = alloc_io_space(s, req->Attributes1, &req->BasePort1, |
648 | req->NumPorts1, req->IOAddrLines)) { | 674 | req->NumPorts1, req->IOAddrLines); |
675 | if (ret) { | ||
649 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); | 676 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); |
650 | mutex_unlock(&s->ops_mutex); | 677 | goto out; |
651 | return -EBUSY; | ||
652 | } | 678 | } |
653 | 679 | ||
654 | if (req->NumPorts2) { | 680 | if (req->NumPorts2) { |
655 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); | 681 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); |
656 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | 682 | ret = alloc_io_space(s, req->Attributes2, &req->BasePort2, |
657 | req->NumPorts2, req->IOAddrLines)) { | 683 | req->NumPorts2, req->IOAddrLines); |
684 | if (ret) { | ||
658 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); | 685 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); |
659 | release_io_space(s, req->BasePort1, req->NumPorts1); | 686 | release_io_space(s, req->BasePort1, req->NumPorts1); |
660 | mutex_unlock(&s->ops_mutex); | 687 | goto out; |
661 | return -EBUSY; | ||
662 | } | 688 | } |
663 | } | 689 | } |
664 | mutex_unlock(&s->ops_mutex); | ||
665 | 690 | ||
666 | c->io = *req; | 691 | c->io = *req; |
667 | c->state |= CONFIG_IO_REQ; | 692 | c->state |= CONFIG_IO_REQ; |
668 | p_dev->_io = 1; | 693 | p_dev->_io = 1; |
669 | return 0; | 694 | dev_dbg(&s->dev, "allocating resources succeeded: %d\n", ret); |
695 | |||
696 | out: | ||
697 | mutex_unlock(&s->ops_mutex); | ||
698 | |||
699 | return ret; | ||
670 | } /* pcmcia_request_io */ | 700 | } /* pcmcia_request_io */ |
671 | EXPORT_SYMBOL(pcmcia_request_io); | 701 | EXPORT_SYMBOL(pcmcia_request_io); |
672 | 702 | ||
@@ -695,21 +725,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
695 | int ret = -EINVAL, irq = 0; | 725 | int ret = -EINVAL, irq = 0; |
696 | int type; | 726 | int type; |
697 | 727 | ||
728 | mutex_lock(&s->ops_mutex); | ||
729 | |||
698 | if (!(s->state & SOCKET_PRESENT)) { | 730 | if (!(s->state & SOCKET_PRESENT)) { |
699 | dev_dbg(&s->dev, "No card present\n"); | 731 | dev_dbg(&s->dev, "No card present\n"); |
700 | return -ENODEV; | 732 | goto out; |
701 | } | 733 | } |
702 | c = p_dev->function_config; | 734 | c = p_dev->function_config; |
703 | if (c->state & CONFIG_LOCKED) { | 735 | if (c->state & CONFIG_LOCKED) { |
704 | dev_dbg(&s->dev, "Configuration is locked\n"); | 736 | dev_dbg(&s->dev, "Configuration is locked\n"); |
705 | return -EACCES; | 737 | goto out; |
706 | } | 738 | } |
707 | if (c->state & CONFIG_IRQ_REQ) { | 739 | if (c->state & CONFIG_IRQ_REQ) { |
708 | dev_dbg(&s->dev, "IRQ already configured\n"); | 740 | dev_dbg(&s->dev, "IRQ already configured\n"); |
709 | return -EBUSY; | 741 | goto out; |
710 | } | 742 | } |
711 | 743 | ||
712 | mutex_lock(&s->ops_mutex); | ||
713 | /* Decide what type of interrupt we are registering */ | 744 | /* Decide what type of interrupt we are registering */ |
714 | type = 0; | 745 | type = 0; |
715 | if (s->functions > 1) /* All of this ought to be handled higher up */ | 746 | if (s->functions > 1) /* All of this ought to be handled higher up */ |
@@ -768,7 +799,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
768 | if (ret && !s->irq.AssignedIRQ) { | 799 | if (ret && !s->irq.AssignedIRQ) { |
769 | if (!s->pci_irq) { | 800 | if (!s->pci_irq) { |
770 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | 801 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); |
771 | return ret; | 802 | goto out; |
772 | } | 803 | } |
773 | type = IRQF_SHARED; | 804 | type = IRQF_SHARED; |
774 | irq = s->pci_irq; | 805 | irq = s->pci_irq; |
@@ -780,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
780 | if (ret) { | 811 | if (ret) { |
781 | dev_printk(KERN_INFO, &s->dev, | 812 | dev_printk(KERN_INFO, &s->dev, |
782 | "request_irq() failed\n"); | 813 | "request_irq() failed\n"); |
783 | return ret; | 814 | goto out; |
784 | } | 815 | } |
785 | } | 816 | } |
786 | 817 | ||
@@ -803,9 +834,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
803 | pcmcia_used_irq[irq]++; | 834 | pcmcia_used_irq[irq]++; |
804 | #endif | 835 | #endif |
805 | 836 | ||
837 | ret = 0; | ||
838 | out: | ||
806 | mutex_unlock(&s->ops_mutex); | 839 | mutex_unlock(&s->ops_mutex); |
807 | 840 | return ret; | |
808 | return 0; | ||
809 | } /* pcmcia_request_irq */ | 841 | } /* pcmcia_request_irq */ |
810 | EXPORT_SYMBOL(pcmcia_request_irq); | 842 | EXPORT_SYMBOL(pcmcia_request_irq); |
811 | 843 | ||