Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ab24855 authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

pcmcia: add locking to pcmcia_{read,write}_cis_mem

parent 44961a03
Loading
Loading
Loading
Loading
+21 −6
Original line number Original line Diff line number Diff line
@@ -83,6 +83,8 @@ void release_cis_mem(struct pcmcia_socket *s)
 * Map the card memory at "card_offset" into virtual space.
 * Map the card memory at "card_offset" into virtual space.
 * If flags & MAP_ATTRIB, map the attribute space, otherwise
 * If flags & MAP_ATTRIB, map the attribute space, otherwise
 * map the memory space.
 * map the memory space.
 *
 * Must be called with ops_mutex held.
 */
 */
static void __iomem *
static void __iomem *
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
@@ -90,13 +92,11 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
	pccard_mem_map *mem = &s->cis_mem;
	pccard_mem_map *mem = &s->cis_mem;
	int ret;
	int ret;


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


@@ -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);
		s->cis_virt = ioremap(mem->static_start, s->map_size);
	}
	}


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


@@ -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);
    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 */
@@ -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));
	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");
	    memset(ptr, 0xff, len);
	    memset(ptr, 0xff, len);
	    mutex_unlock(&s->ops_mutex);
	    return -1;
	    return -1;
	}
	}


@@ -170,6 +171,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
    } else {
    } else {
	u_int inc = 1, card_offset, flags;
	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);
	flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
	if (attr) {
	if (attr) {
	    flags |= MAP_ATTRIB;
	    flags |= MAP_ATTRIB;
@@ -181,7 +185,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
	while (len) {
	while (len) {
	    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");
		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;
@@ -195,6 +201,7 @@ 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));
@@ -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);
    dev_dbg(&s->dev, "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 */
@@ -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));
	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 */
		return; /* FIXME: Error */
	}


	writeb(flags, sys+CISREG_ICTRL0);
	writeb(flags, sys+CISREG_ICTRL0);
	writeb(addr & 0xff, sys+CISREG_IADDR0);
	writeb(addr & 0xff, sys+CISREG_IADDR0);
@@ -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);
	card_offset = addr & ~(s->map_size-1);
	while (len) {
	while (len) {
	    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");
		mutex_unlock(&s->ops_mutex);
		return; /* FIXME: error */
		return; /* FIXME: error */
	    }


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




+5 −0
Original line number Original line Diff line number Diff line
@@ -273,6 +273,11 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
{
{
	int ret = -EINVAL;
	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_mem.res = res;
	s->cis_virt = ioremap(res->start, s->map_size);
	s->cis_virt = ioremap(res->start, s->map_size);
	if (s->cis_virt) {
	if (s->cis_virt) {