diff options
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 169 |
1 files changed, 134 insertions, 35 deletions
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index d5db95644b64..b2df04199a21 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -43,6 +43,39 @@ module_param(io_speed, int, 0444); | |||
43 | static u8 pcmcia_used_irq[NR_IRQS]; | 43 | static u8 pcmcia_used_irq[NR_IRQS]; |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | static int pcmcia_adjust_io_region(struct resource *res, unsigned long start, | ||
47 | unsigned long end, struct pcmcia_socket *s) | ||
48 | { | ||
49 | if (s->resource_ops->adjust_io_region) | ||
50 | return s->resource_ops->adjust_io_region(res, start, end, s); | ||
51 | return -ENOMEM; | ||
52 | } | ||
53 | |||
54 | static struct resource *pcmcia_find_io_region(unsigned long base, int num, | ||
55 | unsigned long align, | ||
56 | struct pcmcia_socket *s) | ||
57 | { | ||
58 | if (s->resource_ops->find_io) | ||
59 | return s->resource_ops->find_io(base, num, align, s); | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | int pcmcia_validate_mem(struct pcmcia_socket *s) | ||
64 | { | ||
65 | if (s->resource_ops->validate_mem) | ||
66 | return s->resource_ops->validate_mem(s); | ||
67 | /* if there is no callback, we can assume that everything is OK */ | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, | ||
72 | int low, struct pcmcia_socket *s) | ||
73 | { | ||
74 | if (s->resource_ops->find_mem) | ||
75 | return s->resource_ops->find_mem(base, num, align, low, s); | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
46 | 79 | ||
47 | /** alloc_io_space | 80 | /** alloc_io_space |
48 | * | 81 | * |
@@ -158,14 +191,18 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | |||
158 | return -EINVAL; | 191 | return -EINVAL; |
159 | 192 | ||
160 | s = p_dev->socket; | 193 | s = p_dev->socket; |
194 | |||
195 | mutex_lock(&s->ops_mutex); | ||
161 | c = p_dev->function_config; | 196 | c = p_dev->function_config; |
162 | 197 | ||
163 | if (!(c->state & CONFIG_LOCKED)) { | 198 | if (!(c->state & CONFIG_LOCKED)) { |
164 | 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); | ||
165 | return -EACCES; | 201 | return -EACCES; |
166 | } | 202 | } |
167 | 203 | ||
168 | addr = (c->ConfigBase + reg->Offset) >> 1; | 204 | addr = (c->ConfigBase + reg->Offset) >> 1; |
205 | mutex_unlock(&s->ops_mutex); | ||
169 | 206 | ||
170 | switch (reg->Action) { | 207 | switch (reg->Action) { |
171 | case CS_READ: | 208 | case CS_READ: |
@@ -190,6 +227,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
190 | memreq_t *req) | 227 | memreq_t *req) |
191 | { | 228 | { |
192 | struct pcmcia_socket *s = p_dev->socket; | 229 | struct pcmcia_socket *s = p_dev->socket; |
230 | int ret; | ||
193 | 231 | ||
194 | wh--; | 232 | wh--; |
195 | if (wh >= MAX_WIN) | 233 | if (wh >= MAX_WIN) |
@@ -198,12 +236,13 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, | |||
198 | dev_dbg(&s->dev, "failure: requested page is zero\n"); | 236 | dev_dbg(&s->dev, "failure: requested page is zero\n"); |
199 | return -EINVAL; | 237 | return -EINVAL; |
200 | } | 238 | } |
239 | mutex_lock(&s->ops_mutex); | ||
201 | s->win[wh].card_start = req->CardOffset; | 240 | s->win[wh].card_start = req->CardOffset; |
202 | if (s->ops->set_mem_map(s, &s->win[wh]) != 0) { | 241 | ret = s->ops->set_mem_map(s, &s->win[wh]); |
203 | dev_dbg(&s->dev, "failed to set_mem_map\n"); | 242 | if (ret) |
204 | return -EIO; | 243 | dev_warn(&s->dev, "failed to set_mem_map\n"); |
205 | } | 244 | mutex_unlock(&s->ops_mutex); |
206 | return 0; | 245 | return ret; |
207 | } /* pcmcia_map_mem_page */ | 246 | } /* pcmcia_map_mem_page */ |
208 | EXPORT_SYMBOL(pcmcia_map_mem_page); | 247 | EXPORT_SYMBOL(pcmcia_map_mem_page); |
209 | 248 | ||
@@ -219,14 +258,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
219 | config_t *c; | 258 | config_t *c; |
220 | 259 | ||
221 | s = p_dev->socket; | 260 | s = p_dev->socket; |
261 | |||
262 | mutex_lock(&s->ops_mutex); | ||
222 | c = p_dev->function_config; | 263 | c = p_dev->function_config; |
223 | 264 | ||
224 | if (!(s->state & SOCKET_PRESENT)) { | 265 | if (!(s->state & SOCKET_PRESENT)) { |
225 | dev_dbg(&s->dev, "No card present\n"); | 266 | dev_dbg(&s->dev, "No card present\n"); |
267 | mutex_unlock(&s->ops_mutex); | ||
226 | return -ENODEV; | 268 | return -ENODEV; |
227 | } | 269 | } |
228 | if (!(c->state & CONFIG_LOCKED)) { | 270 | if (!(c->state & CONFIG_LOCKED)) { |
229 | 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); | ||
230 | return -EACCES; | 273 | return -EACCES; |
231 | } | 274 | } |
232 | 275 | ||
@@ -251,10 +294,12 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
251 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 294 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
252 | if (mod->Vpp1 != mod->Vpp2) { | 295 | if (mod->Vpp1 != mod->Vpp2) { |
253 | 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); | ||
254 | return -EINVAL; | 298 | return -EINVAL; |
255 | } | 299 | } |
256 | s->socket.Vpp = mod->Vpp1; | 300 | s->socket.Vpp = mod->Vpp1; |
257 | if (s->ops->set_socket(s, &s->socket)) { | 301 | if (s->ops->set_socket(s, &s->socket)) { |
302 | mutex_unlock(&s->ops_mutex); | ||
258 | dev_printk(KERN_WARNING, &s->dev, | 303 | dev_printk(KERN_WARNING, &s->dev, |
259 | "Unable to set VPP\n"); | 304 | "Unable to set VPP\n"); |
260 | return -EIO; | 305 | return -EIO; |
@@ -262,6 +307,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
262 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || | 307 | } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || |
263 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 308 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
264 | 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); | ||
265 | return -EINVAL; | 311 | return -EINVAL; |
266 | } | 312 | } |
267 | 313 | ||
@@ -286,6 +332,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
286 | s->ops->set_io_map(s, &io_on); | 332 | s->ops->set_io_map(s, &io_on); |
287 | } | 333 | } |
288 | } | 334 | } |
335 | mutex_unlock(&s->ops_mutex); | ||
289 | 336 | ||
290 | return 0; | 337 | return 0; |
291 | } /* modify_configuration */ | 338 | } /* modify_configuration */ |
@@ -296,9 +343,11 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
296 | { | 343 | { |
297 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 344 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
298 | struct pcmcia_socket *s = p_dev->socket; | 345 | struct pcmcia_socket *s = p_dev->socket; |
299 | config_t *c = p_dev->function_config; | 346 | config_t *c; |
300 | int i; | 347 | int i; |
301 | 348 | ||
349 | mutex_lock(&s->ops_mutex); | ||
350 | c = p_dev->function_config; | ||
302 | if (p_dev->_locked) { | 351 | if (p_dev->_locked) { |
303 | p_dev->_locked = 0; | 352 | p_dev->_locked = 0; |
304 | if (--(s->lock_count) == 0) { | 353 | if (--(s->lock_count) == 0) { |
@@ -321,6 +370,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
321 | s->ops->set_io_map(s, &io); | 370 | s->ops->set_io_map(s, &io); |
322 | } | 371 | } |
323 | } | 372 | } |
373 | mutex_unlock(&s->ops_mutex); | ||
324 | 374 | ||
325 | return 0; | 375 | return 0; |
326 | } /* pcmcia_release_configuration */ | 376 | } /* pcmcia_release_configuration */ |
@@ -337,10 +387,14 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
337 | 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) |
338 | { | 388 | { |
339 | struct pcmcia_socket *s = p_dev->socket; | 389 | struct pcmcia_socket *s = p_dev->socket; |
340 | 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; | ||
341 | 395 | ||
342 | if (!p_dev->_io) | 396 | if (!p_dev->_io) |
343 | return -EINVAL; | 397 | goto out; |
344 | 398 | ||
345 | p_dev->_io = 0; | 399 | p_dev->_io = 0; |
346 | 400 | ||
@@ -348,7 +402,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
348 | (c->io.NumPorts1 != req->NumPorts1) || | 402 | (c->io.NumPorts1 != req->NumPorts1) || |
349 | (c->io.BasePort2 != req->BasePort2) || | 403 | (c->io.BasePort2 != req->BasePort2) || |
350 | (c->io.NumPorts2 != req->NumPorts2)) | 404 | (c->io.NumPorts2 != req->NumPorts2)) |
351 | return -EINVAL; | 405 | goto out; |
352 | 406 | ||
353 | c->state &= ~CONFIG_IO_REQ; | 407 | c->state &= ~CONFIG_IO_REQ; |
354 | 408 | ||
@@ -356,28 +410,38 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
356 | if (req->NumPorts2) | 410 | if (req->NumPorts2) |
357 | release_io_space(s, req->BasePort2, req->NumPorts2); | 411 | release_io_space(s, req->BasePort2, req->NumPorts2); |
358 | 412 | ||
359 | return 0; | 413 | out: |
414 | mutex_unlock(&s->ops_mutex); | ||
415 | |||
416 | return ret; | ||
360 | } /* pcmcia_release_io */ | 417 | } /* pcmcia_release_io */ |
361 | 418 | ||
362 | 419 | ||
363 | 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) |
364 | { | 421 | { |
365 | struct pcmcia_socket *s = p_dev->socket; | 422 | struct pcmcia_socket *s = p_dev->socket; |
366 | 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; | ||
367 | 429 | ||
368 | if (!p_dev->_irq) | 430 | if (!p_dev->_irq) |
369 | return -EINVAL; | 431 | goto out; |
432 | |||
370 | p_dev->_irq = 0; | 433 | p_dev->_irq = 0; |
371 | 434 | ||
372 | if (c->state & CONFIG_LOCKED) | 435 | if (c->state & CONFIG_LOCKED) |
373 | return -EACCES; | 436 | goto out; |
437 | |||
374 | if (c->irq.Attributes != req->Attributes) { | 438 | if (c->irq.Attributes != req->Attributes) { |
375 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); | 439 | dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n"); |
376 | return -EINVAL; | 440 | goto out; |
377 | } | 441 | } |
378 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { | 442 | if (s->irq.AssignedIRQ != req->AssignedIRQ) { |
379 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); | 443 | dev_dbg(&s->dev, "IRQ must match assigned one\n"); |
380 | return -EINVAL; | 444 | goto out; |
381 | } | 445 | } |
382 | if (--s->irq.Config == 0) { | 446 | if (--s->irq.Config == 0) { |
383 | c->state &= ~CONFIG_IRQ_REQ; | 447 | c->state &= ~CONFIG_IRQ_REQ; |
@@ -390,8 +454,12 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
390 | #ifdef CONFIG_PCMCIA_PROBE | 454 | #ifdef CONFIG_PCMCIA_PROBE |
391 | pcmcia_used_irq[req->AssignedIRQ]--; | 455 | pcmcia_used_irq[req->AssignedIRQ]--; |
392 | #endif | 456 | #endif |
457 | ret = 0; | ||
393 | 458 | ||
394 | return 0; | 459 | out: |
460 | mutex_unlock(&s->ops_mutex); | ||
461 | |||
462 | return ret; | ||
395 | } /* pcmcia_release_irq */ | 463 | } /* pcmcia_release_irq */ |
396 | 464 | ||
397 | 465 | ||
@@ -404,10 +472,12 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) | |||
404 | if (wh >= MAX_WIN) | 472 | if (wh >= MAX_WIN) |
405 | return -EINVAL; | 473 | return -EINVAL; |
406 | 474 | ||
475 | mutex_lock(&s->ops_mutex); | ||
407 | win = &s->win[wh]; | 476 | win = &s->win[wh]; |
408 | 477 | ||
409 | if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { | 478 | if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { |
410 | dev_dbg(&s->dev, "not releasing unknown window\n"); | 479 | dev_dbg(&s->dev, "not releasing unknown window\n"); |
480 | mutex_unlock(&s->ops_mutex); | ||
411 | return -EINVAL; | 481 | return -EINVAL; |
412 | } | 482 | } |
413 | 483 | ||
@@ -423,6 +493,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh) | |||
423 | win->res = NULL; | 493 | win->res = NULL; |
424 | } | 494 | } |
425 | p_dev->_win &= ~CLIENT_WIN_REQ(wh); | 495 | p_dev->_win &= ~CLIENT_WIN_REQ(wh); |
496 | mutex_unlock(&s->ops_mutex); | ||
426 | 497 | ||
427 | return 0; | 498 | return 0; |
428 | } /* pcmcia_release_window */ | 499 | } /* pcmcia_release_window */ |
@@ -445,8 +516,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
445 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); | 516 | dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); |
446 | return -EINVAL; | 517 | return -EINVAL; |
447 | } | 518 | } |
519 | |||
520 | mutex_lock(&s->ops_mutex); | ||
448 | c = p_dev->function_config; | 521 | c = p_dev->function_config; |
449 | if (c->state & CONFIG_LOCKED) { | 522 | if (c->state & CONFIG_LOCKED) { |
523 | mutex_unlock(&s->ops_mutex); | ||
450 | dev_dbg(&s->dev, "Configuration is locked\n"); | 524 | dev_dbg(&s->dev, "Configuration is locked\n"); |
451 | return -EACCES; | 525 | return -EACCES; |
452 | } | 526 | } |
@@ -454,6 +528,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
454 | /* Do power control. We don't allow changes in Vcc. */ | 528 | /* Do power control. We don't allow changes in Vcc. */ |
455 | s->socket.Vpp = req->Vpp; | 529 | s->socket.Vpp = req->Vpp; |
456 | if (s->ops->set_socket(s, &s->socket)) { | 530 | if (s->ops->set_socket(s, &s->socket)) { |
531 | mutex_unlock(&s->ops_mutex); | ||
457 | dev_printk(KERN_WARNING, &s->dev, | 532 | dev_printk(KERN_WARNING, &s->dev, |
458 | "Unable to set socket state\n"); | 533 | "Unable to set socket state\n"); |
459 | return -EINVAL; | 534 | return -EINVAL; |
@@ -476,6 +551,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
476 | s->socket.io_irq = 0; | 551 | s->socket.io_irq = 0; |
477 | s->ops->set_socket(s, &s->socket); | 552 | s->ops->set_socket(s, &s->socket); |
478 | s->lock_count++; | 553 | s->lock_count++; |
554 | mutex_unlock(&s->ops_mutex); | ||
479 | 555 | ||
480 | /* Set up CIS configuration registers */ | 556 | /* Set up CIS configuration registers */ |
481 | base = c->ConfigBase = req->ConfigBase; | 557 | base = c->ConfigBase = req->ConfigBase; |
@@ -524,6 +600,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
524 | 600 | ||
525 | /* Configure I/O windows */ | 601 | /* Configure I/O windows */ |
526 | if (c->state & CONFIG_IO_REQ) { | 602 | if (c->state & CONFIG_IO_REQ) { |
603 | mutex_lock(&s->ops_mutex); | ||
527 | iomap.speed = io_speed; | 604 | iomap.speed = io_speed; |
528 | for (i = 0; i < MAX_IO_WIN; i++) | 605 | for (i = 0; i < MAX_IO_WIN; i++) |
529 | if (s->io[i].res) { | 606 | if (s->io[i].res) { |
@@ -542,6 +619,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
542 | s->ops->set_io_map(s, &iomap); | 619 | s->ops->set_io_map(s, &iomap); |
543 | s->io[i].Config++; | 620 | s->io[i].Config++; |
544 | } | 621 | } |
622 | mutex_unlock(&s->ops_mutex); | ||
545 | } | 623 | } |
546 | 624 | ||
547 | c->state |= CONFIG_LOCKED; | 625 | c->state |= CONFIG_LOCKED; |
@@ -560,54 +638,65 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
560 | { | 638 | { |
561 | struct pcmcia_socket *s = p_dev->socket; | 639 | struct pcmcia_socket *s = p_dev->socket; |
562 | config_t *c; | 640 | config_t *c; |
641 | int ret = -EINVAL; | ||
642 | |||
643 | mutex_lock(&s->ops_mutex); | ||
563 | 644 | ||
564 | if (!(s->state & SOCKET_PRESENT)) { | 645 | if (!(s->state & SOCKET_PRESENT)) { |
565 | dev_dbg(&s->dev, "No card present\n"); | 646 | dev_dbg(&s->dev, "No card present\n"); |
566 | return -ENODEV; | 647 | goto out; |
567 | } | 648 | } |
568 | 649 | ||
569 | if (!req) | 650 | if (!req) |
570 | return -EINVAL; | 651 | goto out; |
652 | |||
571 | c = p_dev->function_config; | 653 | c = p_dev->function_config; |
572 | if (c->state & CONFIG_LOCKED) { | 654 | if (c->state & CONFIG_LOCKED) { |
573 | dev_dbg(&s->dev, "Configuration is locked\n"); | 655 | dev_dbg(&s->dev, "Configuration is locked\n"); |
574 | return -EACCES; | 656 | goto out; |
575 | } | 657 | } |
576 | if (c->state & CONFIG_IO_REQ) { | 658 | if (c->state & CONFIG_IO_REQ) { |
577 | dev_dbg(&s->dev, "IO already configured\n"); | 659 | dev_dbg(&s->dev, "IO already configured\n"); |
578 | return -EBUSY; | 660 | goto out; |
579 | } | 661 | } |
580 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { | 662 | if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { |
581 | 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"); |
582 | return -EINVAL; | 664 | goto out; |
583 | } | 665 | } |
584 | if ((req->NumPorts2 > 0) && | 666 | if ((req->NumPorts2 > 0) && |
585 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { | 667 | (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { |
586 | 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"); |
587 | return -EINVAL; | 669 | goto out; |
588 | } | 670 | } |
589 | 671 | ||
590 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); | 672 | dev_dbg(&s->dev, "trying to allocate resource 1\n"); |
591 | if (alloc_io_space(s, req->Attributes1, &req->BasePort1, | 673 | ret = alloc_io_space(s, req->Attributes1, &req->BasePort1, |
592 | req->NumPorts1, req->IOAddrLines)) { | 674 | req->NumPorts1, req->IOAddrLines); |
675 | if (ret) { | ||
593 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); | 676 | dev_dbg(&s->dev, "allocation of resource 1 failed\n"); |
594 | return -EBUSY; | 677 | goto out; |
595 | } | 678 | } |
596 | 679 | ||
597 | if (req->NumPorts2) { | 680 | if (req->NumPorts2) { |
598 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); | 681 | dev_dbg(&s->dev, "trying to allocate resource 2\n"); |
599 | if (alloc_io_space(s, req->Attributes2, &req->BasePort2, | 682 | ret = alloc_io_space(s, req->Attributes2, &req->BasePort2, |
600 | req->NumPorts2, req->IOAddrLines)) { | 683 | req->NumPorts2, req->IOAddrLines); |
684 | if (ret) { | ||
601 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); | 685 | dev_dbg(&s->dev, "allocation of resource 2 failed\n"); |
602 | release_io_space(s, req->BasePort1, req->NumPorts1); | 686 | release_io_space(s, req->BasePort1, req->NumPorts1); |
603 | return -EBUSY; | 687 | goto out; |
604 | } | 688 | } |
605 | } | 689 | } |
606 | 690 | ||
607 | c->io = *req; | 691 | c->io = *req; |
608 | c->state |= CONFIG_IO_REQ; | 692 | c->state |= CONFIG_IO_REQ; |
609 | p_dev->_io = 1; | 693 | p_dev->_io = 1; |
610 | 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; | ||
611 | } /* pcmcia_request_io */ | 700 | } /* pcmcia_request_io */ |
612 | EXPORT_SYMBOL(pcmcia_request_io); | 701 | EXPORT_SYMBOL(pcmcia_request_io); |
613 | 702 | ||
@@ -636,18 +725,20 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
636 | int ret = -EINVAL, irq = 0; | 725 | int ret = -EINVAL, irq = 0; |
637 | int type; | 726 | int type; |
638 | 727 | ||
728 | mutex_lock(&s->ops_mutex); | ||
729 | |||
639 | if (!(s->state & SOCKET_PRESENT)) { | 730 | if (!(s->state & SOCKET_PRESENT)) { |
640 | dev_dbg(&s->dev, "No card present\n"); | 731 | dev_dbg(&s->dev, "No card present\n"); |
641 | return -ENODEV; | 732 | goto out; |
642 | } | 733 | } |
643 | c = p_dev->function_config; | 734 | c = p_dev->function_config; |
644 | if (c->state & CONFIG_LOCKED) { | 735 | if (c->state & CONFIG_LOCKED) { |
645 | dev_dbg(&s->dev, "Configuration is locked\n"); | 736 | dev_dbg(&s->dev, "Configuration is locked\n"); |
646 | return -EACCES; | 737 | goto out; |
647 | } | 738 | } |
648 | if (c->state & CONFIG_IRQ_REQ) { | 739 | if (c->state & CONFIG_IRQ_REQ) { |
649 | dev_dbg(&s->dev, "IRQ already configured\n"); | 740 | dev_dbg(&s->dev, "IRQ already configured\n"); |
650 | return -EBUSY; | 741 | goto out; |
651 | } | 742 | } |
652 | 743 | ||
653 | /* Decide what type of interrupt we are registering */ | 744 | /* Decide what type of interrupt we are registering */ |
@@ -708,7 +799,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
708 | if (ret && !s->irq.AssignedIRQ) { | 799 | if (ret && !s->irq.AssignedIRQ) { |
709 | if (!s->pci_irq) { | 800 | if (!s->pci_irq) { |
710 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); | 801 | dev_printk(KERN_INFO, &s->dev, "no IRQ found\n"); |
711 | return ret; | 802 | goto out; |
712 | } | 803 | } |
713 | type = IRQF_SHARED; | 804 | type = IRQF_SHARED; |
714 | irq = s->pci_irq; | 805 | irq = s->pci_irq; |
@@ -720,7 +811,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
720 | if (ret) { | 811 | if (ret) { |
721 | dev_printk(KERN_INFO, &s->dev, | 812 | dev_printk(KERN_INFO, &s->dev, |
722 | "request_irq() failed\n"); | 813 | "request_irq() failed\n"); |
723 | return ret; | 814 | goto out; |
724 | } | 815 | } |
725 | } | 816 | } |
726 | 817 | ||
@@ -743,7 +834,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
743 | pcmcia_used_irq[irq]++; | 834 | pcmcia_used_irq[irq]++; |
744 | #endif | 835 | #endif |
745 | 836 | ||
746 | return 0; | 837 | ret = 0; |
838 | out: | ||
839 | mutex_unlock(&s->ops_mutex); | ||
840 | return ret; | ||
747 | } /* pcmcia_request_irq */ | 841 | } /* pcmcia_request_irq */ |
748 | EXPORT_SYMBOL(pcmcia_request_irq); | 842 | EXPORT_SYMBOL(pcmcia_request_irq); |
749 | 843 | ||
@@ -796,6 +890,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
796 | return -EINVAL; | 890 | return -EINVAL; |
797 | } | 891 | } |
798 | 892 | ||
893 | mutex_lock(&s->ops_mutex); | ||
799 | win = &s->win[w]; | 894 | win = &s->win[w]; |
800 | 895 | ||
801 | if (!(s->features & SS_CAP_STATIC_MAP)) { | 896 | if (!(s->features & SS_CAP_STATIC_MAP)) { |
@@ -803,6 +898,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
803 | (req->Attributes & WIN_MAP_BELOW_1MB), s); | 898 | (req->Attributes & WIN_MAP_BELOW_1MB), s); |
804 | if (!win->res) { | 899 | if (!win->res) { |
805 | dev_dbg(&s->dev, "allocating mem region failed\n"); | 900 | dev_dbg(&s->dev, "allocating mem region failed\n"); |
901 | mutex_unlock(&s->ops_mutex); | ||
806 | return -EINVAL; | 902 | return -EINVAL; |
807 | } | 903 | } |
808 | } | 904 | } |
@@ -821,8 +917,10 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
821 | if (req->Attributes & WIN_USE_WAIT) | 917 | if (req->Attributes & WIN_USE_WAIT) |
822 | win->flags |= MAP_USE_WAIT; | 918 | win->flags |= MAP_USE_WAIT; |
823 | win->card_start = 0; | 919 | win->card_start = 0; |
920 | |||
824 | if (s->ops->set_mem_map(s, win) != 0) { | 921 | if (s->ops->set_mem_map(s, win) != 0) { |
825 | dev_dbg(&s->dev, "failed to set memory mapping\n"); | 922 | dev_dbg(&s->dev, "failed to set memory mapping\n"); |
923 | mutex_unlock(&s->ops_mutex); | ||
826 | return -EIO; | 924 | return -EIO; |
827 | } | 925 | } |
828 | s->state |= SOCKET_WIN_REQ(w); | 926 | s->state |= SOCKET_WIN_REQ(w); |
@@ -833,6 +931,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha | |||
833 | else | 931 | else |
834 | req->Base = win->res->start; | 932 | req->Base = win->res->start; |
835 | 933 | ||
934 | mutex_unlock(&s->ops_mutex); | ||
836 | *wh = w + 1; | 935 | *wh = w + 1; |
837 | 936 | ||
838 | return 0; | 937 | return 0; |