aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-15 18:26:33 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-02-17 11:48:16 -0500
commit9e86749cff70fca505c7c1a9dc760d193f27a059 (patch)
tree3017dc3c22c12c7ef53fd81de6d4869f212cef02 /drivers/pcmcia
parent8533ee31cdc08fc1f2533e5f21f8e4abf6a57dfc (diff)
pcmcia: lock ops->set_socket
As a side effect, socket_state_t socket; u_int state; u_int suspended_state; are properly protected now. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/cs.c18
-rw-r--r--drivers/pcmcia/pcmcia_resource.c15
2 files changed, 29 insertions, 4 deletions
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 91aa1f284068..cc0ba8aef59e 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -383,6 +383,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
383 dev_dbg(&s->dev, "shutdown\n"); 383 dev_dbg(&s->dev, "shutdown\n");
384 384
385 send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); 385 send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
386
387 mutex_lock(&s->ops_mutex);
386 s->state &= SOCKET_INUSE | SOCKET_PRESENT; 388 s->state &= SOCKET_INUSE | SOCKET_PRESENT;
387 msleep(shutdown_delay * 10); 389 msleep(shutdown_delay * 10);
388 s->state &= SOCKET_INUSE; 390 s->state &= SOCKET_INUSE;
@@ -410,6 +412,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
410 } 412 }
411 413
412 s->state &= ~SOCKET_INUSE; 414 s->state &= ~SOCKET_INUSE;
415 mutex_unlock(&s->ops_mutex);
413} 416}
414 417
415static int socket_setup(struct pcmcia_socket *skt, int initial_delay) 418static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
@@ -498,6 +501,7 @@ static int socket_insert(struct pcmcia_socket *skt)
498 501
499 dev_dbg(&skt->dev, "insert\n"); 502 dev_dbg(&skt->dev, "insert\n");
500 503
504 mutex_lock(&skt->ops_mutex);
501 WARN_ON(skt->state & SOCKET_INUSE); 505 WARN_ON(skt->state & SOCKET_INUSE);
502 skt->state |= SOCKET_INUSE; 506 skt->state |= SOCKET_INUSE;
503 507
@@ -517,9 +521,11 @@ static int socket_insert(struct pcmcia_socket *skt)
517 } 521 }
518#endif 522#endif
519 dev_dbg(&skt->dev, "insert done\n"); 523 dev_dbg(&skt->dev, "insert done\n");
524 mutex_unlock(&skt->ops_mutex);
520 525
521 send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); 526 send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
522 } else { 527 } else {
528 mutex_unlock(&skt->ops_mutex);
523 socket_shutdown(skt); 529 socket_shutdown(skt);
524 } 530 }
525 531
@@ -531,6 +537,7 @@ static int socket_suspend(struct pcmcia_socket *skt)
531 if (skt->state & SOCKET_SUSPEND) 537 if (skt->state & SOCKET_SUSPEND)
532 return -EBUSY; 538 return -EBUSY;
533 539
540 mutex_lock(&skt->ops_mutex);
534 skt->suspended_state = skt->state; 541 skt->suspended_state = skt->state;
535 542
536 send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); 543 send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
@@ -539,23 +546,27 @@ static int socket_suspend(struct pcmcia_socket *skt)
539 if (skt->ops->suspend) 546 if (skt->ops->suspend)
540 skt->ops->suspend(skt); 547 skt->ops->suspend(skt);
541 skt->state |= SOCKET_SUSPEND; 548 skt->state |= SOCKET_SUSPEND;
542 549 mutex_unlock(&skt->ops_mutex);
543 return 0; 550 return 0;
544} 551}
545 552
546static int socket_early_resume(struct pcmcia_socket *skt) 553static int socket_early_resume(struct pcmcia_socket *skt)
547{ 554{
555 mutex_lock(&skt->ops_mutex);
548 skt->socket = dead_socket; 556 skt->socket = dead_socket;
549 skt->ops->init(skt); 557 skt->ops->init(skt);
550 skt->ops->set_socket(skt, &skt->socket); 558 skt->ops->set_socket(skt, &skt->socket);
551 if (skt->state & SOCKET_PRESENT) 559 if (skt->state & SOCKET_PRESENT)
552 skt->resume_status = socket_setup(skt, resume_delay); 560 skt->resume_status = socket_setup(skt, resume_delay);
561 mutex_unlock(&skt->ops_mutex);
553 return 0; 562 return 0;
554} 563}
555 564
556static int socket_late_resume(struct pcmcia_socket *skt) 565static int socket_late_resume(struct pcmcia_socket *skt)
557{ 566{
567 mutex_lock(&skt->ops_mutex);
558 skt->state &= ~SOCKET_SUSPEND; 568 skt->state &= ~SOCKET_SUSPEND;
569 mutex_unlock(&skt->ops_mutex);
559 570
560 if (!(skt->state & SOCKET_PRESENT)) 571 if (!(skt->state & SOCKET_PRESENT))
561 return socket_insert(skt); 572 return socket_insert(skt);
@@ -795,7 +806,10 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
795 send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); 806 send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
796 if (skt->callback) 807 if (skt->callback)
797 skt->callback->suspend(skt); 808 skt->callback->suspend(skt);
798 if (socket_reset(skt) == 0) { 809 mutex_lock(&skt->ops_mutex);
810 ret = socket_reset(skt);
811 mutex_unlock(&skt->ops_mutex);
812 if (ret == 0) {
799 send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); 813 send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
800 if (skt->callback) 814 if (skt->callback)
801 skt->callback->resume(skt); 815 skt->callback->resume(skt);
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 4e0aaec5cf99..f365ecb9c5cd 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -266,6 +266,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
266 } 266 }
267 267
268 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { 268 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
269 mutex_lock(&s->ops_mutex);
269 if (mod->Attributes & CONF_ENABLE_IRQ) { 270 if (mod->Attributes & CONF_ENABLE_IRQ) {
270 c->Attributes |= CONF_ENABLE_IRQ; 271 c->Attributes |= CONF_ENABLE_IRQ;
271 s->socket.io_irq = s->irq.AssignedIRQ; 272 s->socket.io_irq = s->irq.AssignedIRQ;
@@ -274,6 +275,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
274 s->socket.io_irq = 0; 275 s->socket.io_irq = 0;
275 } 276 }
276 s->ops->set_socket(s, &s->socket); 277 s->ops->set_socket(s, &s->socket);
278 mutex_unlock(&s->ops_mutex);
277 } 279 }
278 280
279 if (mod->Attributes & CONF_VCC_CHANGE_VALID) { 281 if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
@@ -288,12 +290,15 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
288 dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); 290 dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
289 return -EINVAL; 291 return -EINVAL;
290 } 292 }
293 mutex_lock(&s->ops_mutex);
291 s->socket.Vpp = mod->Vpp1; 294 s->socket.Vpp = mod->Vpp1;
292 if (s->ops->set_socket(s, &s->socket)) { 295 if (s->ops->set_socket(s, &s->socket)) {
296 mutex_unlock(&s->ops_mutex);
293 dev_printk(KERN_WARNING, &s->dev, 297 dev_printk(KERN_WARNING, &s->dev,
294 "Unable to set VPP\n"); 298 "Unable to set VPP\n");
295 return -EIO; 299 return -EIO;
296 } 300 }
301 mutex_unlock(&s->ops_mutex);
297 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || 302 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
298 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { 303 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
299 dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); 304 dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
@@ -336,6 +341,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
336 config_t *c = p_dev->function_config; 341 config_t *c = p_dev->function_config;
337 int i; 342 int i;
338 343
344 mutex_lock(&s->ops_mutex);
339 if (p_dev->_locked) { 345 if (p_dev->_locked) {
340 p_dev->_locked = 0; 346 p_dev->_locked = 0;
341 if (--(s->lock_count) == 0) { 347 if (--(s->lock_count) == 0) {
@@ -347,7 +353,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
347 } 353 }
348 if (c->state & CONFIG_LOCKED) { 354 if (c->state & CONFIG_LOCKED) {
349 c->state &= ~CONFIG_LOCKED; 355 c->state &= ~CONFIG_LOCKED;
350 mutex_lock(&s->ops_mutex);
351 if (c->state & CONFIG_IO_REQ) 356 if (c->state & CONFIG_IO_REQ)
352 for (i = 0; i < MAX_IO_WIN; i++) { 357 for (i = 0; i < MAX_IO_WIN; i++) {
353 if (!s->io[i].res) 358 if (!s->io[i].res)
@@ -358,8 +363,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
358 io.map = i; 363 io.map = i;
359 s->ops->set_io_map(s, &io); 364 s->ops->set_io_map(s, &io);
360 } 365 }
361 mutex_unlock(&s->ops_mutex);
362 } 366 }
367 mutex_unlock(&s->ops_mutex);
363 368
364 return 0; 369 return 0;
365} /* pcmcia_release_configuration */ 370} /* pcmcia_release_configuration */
@@ -493,9 +498,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
493 return -EACCES; 498 return -EACCES;
494 } 499 }
495 500
501 mutex_lock(&s->ops_mutex);
496 /* Do power control. We don't allow changes in Vcc. */ 502 /* Do power control. We don't allow changes in Vcc. */
497 s->socket.Vpp = req->Vpp; 503 s->socket.Vpp = req->Vpp;
498 if (s->ops->set_socket(s, &s->socket)) { 504 if (s->ops->set_socket(s, &s->socket)) {
505 mutex_unlock(&s->ops_mutex);
499 dev_printk(KERN_WARNING, &s->dev, 506 dev_printk(KERN_WARNING, &s->dev,
500 "Unable to set socket state\n"); 507 "Unable to set socket state\n");
501 return -EINVAL; 508 return -EINVAL;
@@ -518,6 +525,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
518 s->socket.io_irq = 0; 525 s->socket.io_irq = 0;
519 s->ops->set_socket(s, &s->socket); 526 s->ops->set_socket(s, &s->socket);
520 s->lock_count++; 527 s->lock_count++;
528 mutex_unlock(&s->ops_mutex);
521 529
522 /* Set up CIS configuration registers */ 530 /* Set up CIS configuration registers */
523 base = c->ConfigBase = req->ConfigBase; 531 base = c->ConfigBase = req->ConfigBase;
@@ -698,6 +706,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
698 return -EBUSY; 706 return -EBUSY;
699 } 707 }
700 708
709 mutex_lock(&s->ops_mutex);
701 /* Decide what type of interrupt we are registering */ 710 /* Decide what type of interrupt we are registering */
702 type = 0; 711 type = 0;
703 if (s->functions > 1) /* All of this ought to be handled higher up */ 712 if (s->functions > 1) /* All of this ought to be handled higher up */
@@ -791,6 +800,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
791 pcmcia_used_irq[irq]++; 800 pcmcia_used_irq[irq]++;
792#endif 801#endif
793 802
803 mutex_unlock(&s->ops_mutex);
804
794 return 0; 805 return 0;
795} /* pcmcia_request_irq */ 806} /* pcmcia_request_irq */
796EXPORT_SYMBOL(pcmcia_request_irq); 807EXPORT_SYMBOL(pcmcia_request_irq);