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>
This commit is contained in:
Родитель
8533ee31cd
Коммит
9e86749cff
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче