aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/pcmcia_resource.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-17 12:31:34 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:22 -0500
commit94a819f80297e1f635a7cde4ed5317612e512ba7 (patch)
tree9bbb1eab3a0f0c722fe40295fb512d99cc0190d9 /drivers/pcmcia/pcmcia_resource.c
parent3d068261854b00c930df4516cd617900935e7706 (diff)
pcmcia: assert locking to struct pcmcia_device
Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/pcmcia_resource.c')
-rw-r--r--drivers/pcmcia/pcmcia_resource.c122
1 files changed, 77 insertions, 45 deletions
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)
381static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) 387static 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; 413out:
414 mutex_unlock(&s->ops_mutex);
415
416 return ret;
404} /* pcmcia_release_io */ 417} /* pcmcia_release_io */
405 418
406 419
407static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) 420static 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
459out:
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
696out:
697 mutex_unlock(&s->ops_mutex);
698
699 return ret;
670} /* pcmcia_request_io */ 700} /* pcmcia_request_io */
671EXPORT_SYMBOL(pcmcia_request_io); 701EXPORT_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;
838out:
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 */
810EXPORT_SYMBOL(pcmcia_request_irq); 842EXPORT_SYMBOL(pcmcia_request_irq);
811 843