pcmcia: call pcmcia_{read,write}_cis_mem with ops_mutex held

This avoids multiple lock takings in several codepaths.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
Dominik Brodowski 2010-03-30 18:07:50 +02:00
parent a60f22c4af
commit 059f667d9f
3 changed files with 19 additions and 19 deletions

View file

@ -129,6 +129,8 @@ static void __iomem *set_cis_map(struct pcmcia_socket *s,
/** /**
* pcmcia_read_cis_mem() - low-level function to read CIS memory * pcmcia_read_cis_mem() - low-level function to read CIS memory
*
* must be called with ops_mutex held
*/ */
int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr) u_int len, void *ptr)
@ -138,7 +140,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
mutex_lock(&s->ops_mutex);
if (attr & IS_INDIRECT) { if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed /* Indirect accesses use a bunch of special registers at fixed
locations in common memory */ locations in common memory */
@ -153,7 +154,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
if (!sys) { if (!sys) {
dev_dbg(&s->dev, "could not map memory\n"); dev_dbg(&s->dev, "could not map memory\n");
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
mutex_unlock(&s->ops_mutex);
return -1; return -1;
} }
@ -184,7 +184,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
if (!sys) { if (!sys) {
dev_dbg(&s->dev, "could not map memory\n"); dev_dbg(&s->dev, "could not map memory\n");
memset(ptr, 0xff, len); memset(ptr, 0xff, len);
mutex_unlock(&s->ops_mutex);
return -1; return -1;
} }
end = sys + s->map_size; end = sys + s->map_size;
@ -198,7 +197,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
addr = 0; addr = 0;
} }
} }
mutex_unlock(&s->ops_mutex);
dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
*(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+0), *(u_char *)(ptr+1),
*(u_char *)(ptr+2), *(u_char *)(ptr+3)); *(u_char *)(ptr+2), *(u_char *)(ptr+3));
@ -209,7 +207,8 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
/** /**
* pcmcia_write_cis_mem() - low-level function to write CIS memory * pcmcia_write_cis_mem() - low-level function to write CIS memory
* *
* Probably only useful for writing one-byte registers. * Probably only useful for writing one-byte registers. Must be called
* with ops_mutex held.
*/ */
void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
u_int len, void *ptr) u_int len, void *ptr)
@ -220,7 +219,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
dev_dbg(&s->dev, dev_dbg(&s->dev,
"pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
mutex_lock(&s->ops_mutex);
if (attr & IS_INDIRECT) { if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed /* Indirect accesses use a bunch of special registers at fixed
locations in common memory */ locations in common memory */
@ -234,7 +232,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
((cis_width) ? MAP_16BIT : 0)); ((cis_width) ? MAP_16BIT : 0));
if (!sys) { if (!sys) {
dev_dbg(&s->dev, "could not map memory\n"); dev_dbg(&s->dev, "could not map memory\n");
mutex_unlock(&s->ops_mutex);
return; /* FIXME: Error */ return; /* FIXME: Error */
} }
@ -260,7 +257,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
sys = set_cis_map(s, card_offset, flags); sys = set_cis_map(s, card_offset, flags);
if (!sys) { if (!sys) {
dev_dbg(&s->dev, "could not map memory\n"); dev_dbg(&s->dev, "could not map memory\n");
mutex_unlock(&s->ops_mutex);
return; /* FIXME: error */ return; /* FIXME: error */
} }
@ -275,7 +271,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
addr = 0; addr = 0;
} }
} }
mutex_unlock(&s->ops_mutex);
} }
@ -314,7 +309,6 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
return 0; return 0;
} }
} }
mutex_unlock(&s->ops_mutex);
ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
@ -326,11 +320,11 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
cis->len = len; cis->len = len;
cis->attr = attr; cis->attr = attr;
memcpy(cis->cache, ptr, len); memcpy(cis->cache, ptr, len);
mutex_lock(&s->ops_mutex);
list_add(&cis->node, &s->cis_cache); list_add(&cis->node, &s->cis_cache);
mutex_unlock(&s->ops_mutex);
} }
} }
mutex_unlock(&s->ops_mutex);
return ret; return ret;
} }
@ -386,6 +380,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
"no memory for verifying CIS\n"); "no memory for verifying CIS\n");
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&s->ops_mutex);
list_for_each_entry(cis, &s->cis_cache, node) { list_for_each_entry(cis, &s->cis_cache, node) {
int len = cis->len; int len = cis->len;
@ -395,10 +390,12 @@ int verify_cis_cache(struct pcmcia_socket *s)
ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
if (ret || memcmp(buf, cis->cache, len) != 0) { if (ret || memcmp(buf, cis->cache, len) != 0) {
kfree(buf); kfree(buf);
mutex_unlock(&s->ops_mutex);
return -1; return -1;
} }
} }
kfree(buf); kfree(buf);
mutex_unlock(&s->ops_mutex);
return 0; return 0;
} }

View file

@ -301,7 +301,9 @@ static int pccard_get_status(struct pcmcia_socket *s,
(c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
u_char reg; u_char reg;
if (c->CardValues & PRESENT_PIN_REPLACE) { if (c->CardValues & PRESENT_PIN_REPLACE) {
mutex_lock(&s->ops_mutex);
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg); pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
mutex_unlock(&s->ops_mutex);
status->CardState |= status->CardState |=
(reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
status->CardState |= status->CardState |=
@ -315,7 +317,9 @@ static int pccard_get_status(struct pcmcia_socket *s,
status->CardState |= CS_EVENT_READY_CHANGE; status->CardState |= CS_EVENT_READY_CHANGE;
} }
if (c->CardValues & PRESENT_EXT_STATUS) { if (c->CardValues & PRESENT_EXT_STATUS) {
mutex_lock(&s->ops_mutex);
pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg); pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
mutex_unlock(&s->ops_mutex);
status->CardState |= status->CardState |=
(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
} }

View file

@ -123,6 +123,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
config_t *c; config_t *c;
int addr; int addr;
u_char val; u_char val;
int ret = 0;
if (!p_dev || !p_dev->function_config) if (!p_dev || !p_dev->function_config)
return -EINVAL; return -EINVAL;
@ -139,11 +140,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
} }
addr = (c->ConfigBase + reg->Offset) >> 1; addr = (c->ConfigBase + reg->Offset) >> 1;
mutex_unlock(&s->ops_mutex);
switch (reg->Action) { switch (reg->Action) {
case CS_READ: case CS_READ:
pcmcia_read_cis_mem(s, 1, addr, 1, &val); ret = pcmcia_read_cis_mem(s, 1, addr, 1, &val);
reg->Value = val; reg->Value = val;
break; break;
case CS_WRITE: case CS_WRITE:
@ -152,10 +152,11 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
break; break;
default: default:
dev_dbg(&s->dev, "Invalid conf register request\n"); dev_dbg(&s->dev, "Invalid conf register request\n");
return -EINVAL; ret = -EINVAL;
break; break;
} }
return 0; mutex_unlock(&s->ops_mutex);
return ret;
} /* pcmcia_access_configuration_register */ } /* pcmcia_access_configuration_register */
EXPORT_SYMBOL(pcmcia_access_configuration_register); EXPORT_SYMBOL(pcmcia_access_configuration_register);
@ -436,7 +437,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
s->socket.io_irq = 0; s->socket.io_irq = 0;
s->ops->set_socket(s, &s->socket); s->ops->set_socket(s, &s->socket);
s->lock_count++; s->lock_count++;
mutex_unlock(&s->ops_mutex);
/* Set up CIS configuration registers */ /* Set up CIS configuration registers */
base = c->ConfigBase = req->ConfigBase; base = c->ConfigBase = req->ConfigBase;
@ -485,7 +485,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
/* Configure I/O windows */ /* Configure I/O windows */
if (c->state & CONFIG_IO_REQ) { if (c->state & CONFIG_IO_REQ) {
mutex_lock(&s->ops_mutex);
iomap.speed = io_speed; iomap.speed = io_speed;
for (i = 0; i < MAX_IO_WIN; i++) for (i = 0; i < MAX_IO_WIN; i++)
if (s->io[i].res) { if (s->io[i].res) {
@ -504,11 +503,11 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
s->ops->set_io_map(s, &iomap); s->ops->set_io_map(s, &iomap);
s->io[i].Config++; s->io[i].Config++;
} }
mutex_unlock(&s->ops_mutex);
} }
c->state |= CONFIG_LOCKED; c->state |= CONFIG_LOCKED;
p_dev->_locked = 1; p_dev->_locked = 1;
mutex_unlock(&s->ops_mutex);
return 0; return 0;
} /* pcmcia_request_configuration */ } /* pcmcia_request_configuration */
EXPORT_SYMBOL(pcmcia_request_configuration); EXPORT_SYMBOL(pcmcia_request_configuration);