diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-15 18:26:33 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-02-17 11:48:16 -0500 |
commit | 9e86749cff70fca505c7c1a9dc760d193f27a059 (patch) | |
tree | 3017dc3c22c12c7ef53fd81de6d4869f212cef02 /drivers/pcmcia | |
parent | 8533ee31cdc08fc1f2533e5f21f8e4abf6a57dfc (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.c | 18 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 15 |
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 | ||
415 | static int socket_setup(struct pcmcia_socket *skt, int initial_delay) | 418 | static 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 | ||
546 | static int socket_early_resume(struct pcmcia_socket *skt) | 553 | static 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 | ||
556 | static int socket_late_resume(struct pcmcia_socket *skt) | 565 | static 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 */ |
796 | EXPORT_SYMBOL(pcmcia_request_irq); | 807 | EXPORT_SYMBOL(pcmcia_request_irq); |