diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-16 00:26:33 +0100 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-02-17 17:48:16 +0100 |
commit | 9e86749cff70fca505c7c1a9dc760d193f27a059 (patch) | |
tree | 3017dc3c22c12c7ef53fd81de6d4869f212cef02 | |
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>
-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 91aa1f28406..cc0ba8aef59 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -383,6 +383,8 @@ static void socket_shutdown(struct pcmcia_socket *s) dev_dbg(&s->dev, "shutdown\n"); send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); + + mutex_lock(&s->ops_mutex); s->state &= SOCKET_INUSE | SOCKET_PRESENT; msleep(shutdown_delay * 10); s->state &= SOCKET_INUSE; @@ -410,6 +412,7 @@ static void socket_shutdown(struct pcmcia_socket *s) } s->state &= ~SOCKET_INUSE; + mutex_unlock(&s->ops_mutex); } static int socket_setup(struct pcmcia_socket *skt, int initial_delay) @@ -498,6 +501,7 @@ static int socket_insert(struct pcmcia_socket *skt) dev_dbg(&skt->dev, "insert\n"); + mutex_lock(&skt->ops_mutex); WARN_ON(skt->state & SOCKET_INUSE); skt->state |= SOCKET_INUSE; @@ -517,9 +521,11 @@ static int socket_insert(struct pcmcia_socket *skt) } #endif dev_dbg(&skt->dev, "insert done\n"); + mutex_unlock(&skt->ops_mutex); send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); } else { + mutex_unlock(&skt->ops_mutex); socket_shutdown(skt); } @@ -531,6 +537,7 @@ static int socket_suspend(struct pcmcia_socket *skt) if (skt->state & SOCKET_SUSPEND) return -EBUSY; + mutex_lock(&skt->ops_mutex); skt->suspended_state = skt->state; send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); @@ -539,23 +546,27 @@ static int socket_suspend(struct pcmcia_socket *skt) if (skt->ops->suspend) skt->ops->suspend(skt); skt->state |= SOCKET_SUSPEND; - + mutex_unlock(&skt->ops_mutex); return 0; } static int socket_early_resume(struct pcmcia_socket *skt) { + mutex_lock(&skt->ops_mutex); skt->socket = dead_socket; skt->ops->init(skt); skt->ops->set_socket(skt, &skt->socket); if (skt->state & SOCKET_PRESENT) skt->resume_status = socket_setup(skt, resume_delay); + mutex_unlock(&skt->ops_mutex); return 0; } static int socket_late_resume(struct pcmcia_socket *skt) { + mutex_lock(&skt->ops_mutex); skt->state &= ~SOCKET_SUSPEND; + mutex_unlock(&skt->ops_mutex); if (!(skt->state & SOCKET_PRESENT)) return socket_insert(skt); @@ -795,7 +806,10 @@ int pcmcia_reset_card(struct pcmcia_socket *skt) send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); if (skt->callback) skt->callback->suspend(skt); - if (socket_reset(skt) == 0) { + mutex_lock(&skt->ops_mutex); + ret = socket_reset(skt); + mutex_unlock(&skt->ops_mutex); + if (ret == 0) { send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); if (skt->callback) skt->callback->resume(skt); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 4e0aaec5cf9..f365ecb9c5c 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, } if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { + mutex_lock(&s->ops_mutex); if (mod->Attributes & CONF_ENABLE_IRQ) { c->Attributes |= CONF_ENABLE_IRQ; s->socket.io_irq = s->irq.AssignedIRQ; @@ -274,6 +275,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, s->socket.io_irq = 0; } s->ops->set_socket(s, &s->socket); + mutex_unlock(&s->ops_mutex); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) { @@ -288,12 +290,15 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); return -EINVAL; } + mutex_lock(&s->ops_mutex); s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { + mutex_unlock(&s->ops_mutex); dev_printk(KERN_WARNING, &s->dev, "Unable to set VPP\n"); return -EIO; } + mutex_unlock(&s->ops_mutex); } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { 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) config_t *c = p_dev->function_config; int i; + mutex_lock(&s->ops_mutex); if (p_dev->_locked) { p_dev->_locked = 0; if (--(s->lock_count) == 0) { @@ -347,7 +353,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) } if (c->state & CONFIG_LOCKED) { c->state &= ~CONFIG_LOCKED; - mutex_lock(&s->ops_mutex); if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) @@ -358,8 +363,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) io.map = i; s->ops->set_io_map(s, &io); } - mutex_unlock(&s->ops_mutex); } + mutex_unlock(&s->ops_mutex); return 0; } /* pcmcia_release_configuration */ @@ -493,9 +498,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, return -EACCES; } + mutex_lock(&s->ops_mutex); /* Do power control. We don't allow changes in Vcc. */ s->socket.Vpp = req->Vpp; if (s->ops->set_socket(s, &s->socket)) { + mutex_unlock(&s->ops_mutex); dev_printk(KERN_WARNING, &s->dev, "Unable to set socket state\n"); return -EINVAL; @@ -518,6 +525,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, s->socket.io_irq = 0; s->ops->set_socket(s, &s->socket); s->lock_count++; + mutex_unlock(&s->ops_mutex); /* Set up CIS configuration registers */ base = c->ConfigBase = req->ConfigBase; @@ -698,6 +706,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) return -EBUSY; } + mutex_lock(&s->ops_mutex); /* Decide what type of interrupt we are registering */ type = 0; 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) pcmcia_used_irq[irq]++; #endif + mutex_unlock(&s->ops_mutex); + return 0; } /* pcmcia_request_irq */ EXPORT_SYMBOL(pcmcia_request_irq); |