Skip to content

Commit

Permalink
pcmcia: add locking to pcmcia_{read,write}_cis_mem
Browse files Browse the repository at this point in the history
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
  • Loading branch information
Dominik Brodowski committed Feb 17, 2010
1 parent 44961a0 commit 7ab2485
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
27 changes: 21 additions & 6 deletions drivers/pcmcia/cistpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,20 @@ void release_cis_mem(struct pcmcia_socket *s)
* Map the card memory at "card_offset" into virtual space.
* If flags & MAP_ATTRIB, map the attribute space, otherwise
* map the memory space.
*
* Must be called with ops_mutex held.
*/
static void __iomem *
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
{
pccard_mem_map *mem = &s->cis_mem;
int ret;

mutex_lock(&s->ops_mutex);
if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
if (mem->res == NULL) {
dev_printk(KERN_NOTICE, &s->dev,
"cs: unable to map card memory!\n");
mutex_unlock(&s->ops_mutex);
return NULL;
}
s->cis_virt = NULL;
Expand All @@ -112,7 +112,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
if (ret) {
iounmap(s->cis_virt);
s->cis_virt = NULL;
mutex_unlock(&s->ops_mutex);
return NULL;
}

Expand All @@ -122,7 +121,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
s->cis_virt = ioremap(mem->static_start, s->map_size);
}

mutex_unlock(&s->ops_mutex);
return s->cis_virt;
}

Expand All @@ -145,6 +143,7 @@ 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);

mutex_lock(&s->ops_mutex);
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
Expand All @@ -156,7 +155,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,

sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
memset(ptr, 0xff, len);
mutex_unlock(&s->ops_mutex);
return -1;
}

Expand All @@ -170,6 +171,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
} else {
u_int inc = 1, card_offset, flags;

if (addr > CISTPL_MAX_CIS_SIZE)
dev_dbg(&s->dev, "attempt to read CIS mem at addr %#x", addr);

flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
if (attr) {
flags |= MAP_ATTRIB;
Expand All @@ -181,7 +185,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
while (len) {
sys = set_cis_map(s, card_offset, flags);
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
memset(ptr, 0xff, len);
mutex_unlock(&s->ops_mutex);
return -1;
}
end = sys + s->map_size;
Expand All @@ -195,6 +201,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
addr = 0;
}
}
mutex_unlock(&s->ops_mutex);
dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
*(u_char *)(ptr+0), *(u_char *)(ptr+1),
*(u_char *)(ptr+2), *(u_char *)(ptr+3));
Expand All @@ -210,6 +217,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,

dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);

mutex_lock(&s->ops_mutex);
if (attr & IS_INDIRECT) {
/* Indirect accesses use a bunch of special registers at fixed
locations in common memory */
Expand All @@ -220,8 +228,11 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
}

sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
if (!sys)
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
mutex_unlock(&s->ops_mutex);
return; /* FIXME: Error */
}

writeb(flags, sys+CISREG_ICTRL0);
writeb(addr & 0xff, sys+CISREG_IADDR0);
Expand All @@ -243,8 +254,11 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
card_offset = addr & ~(s->map_size-1);
while (len) {
sys = set_cis_map(s, card_offset, flags);
if (!sys)
if (!sys) {
dev_dbg(&s->dev, "could not map memory\n");
mutex_unlock(&s->ops_mutex);
return; /* FIXME: error */
}

end = sys + s->map_size;
sys = sys + (addr & (s->map_size-1));
Expand All @@ -257,6 +271,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
addr = 0;
}
}
mutex_unlock(&s->ops_mutex);
}


Expand Down
5 changes: 5 additions & 0 deletions drivers/pcmcia/rsrc_nonstatic.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
{
int ret = -EINVAL;

if (s->fake_cis) {
dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n");
return 0;
}

s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
Expand Down

0 comments on commit 7ab2485

Please sign in to comment.