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

Commit 059f667d authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

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



This avoids multiple lock takings in several codepaths.

Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent a60f22c4
Loading
Loading
Loading
Loading
+9 −12
Original line number Diff line number Diff line
@@ -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
 *
 * must be called with ops_mutex held
 */
int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
		 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);

	mutex_lock(&s->ops_mutex);
	if (attr & IS_INDIRECT) {
		/* Indirect accesses use a bunch of special registers at fixed
		   locations in common memory */
@@ -153,7 +154,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
		if (!sys) {
			dev_dbg(&s->dev, "could not map memory\n");
			memset(ptr, 0xff, len);
			mutex_unlock(&s->ops_mutex);
			return -1;
		}

@@ -184,7 +184,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
			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;
@@ -198,7 +197,6 @@ 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));
@@ -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
 *
 * 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,
		   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,
		"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 */
@@ -234,7 +232,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
				((cis_width) ? MAP_16BIT : 0));
		if (!sys) {
			dev_dbg(&s->dev, "could not map memory\n");
			mutex_unlock(&s->ops_mutex);
			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);
			if (!sys) {
				dev_dbg(&s->dev, "could not map memory\n");
				mutex_unlock(&s->ops_mutex);
				return; /* FIXME: error */
			}

@@ -275,7 +271,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
			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;
		}
	}
	mutex_unlock(&s->ops_mutex);

	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->attr = attr;
			memcpy(cis->cache, ptr, len);
			mutex_lock(&s->ops_mutex);
			list_add(&cis->node, &s->cis_cache);
			mutex_unlock(&s->ops_mutex);
		}
	}
	mutex_unlock(&s->ops_mutex);

	return ret;
}

@@ -386,6 +380,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
			   "no memory for verifying CIS\n");
		return -ENOMEM;
	}
	mutex_lock(&s->ops_mutex);
	list_for_each_entry(cis, &s->cis_cache, node) {
		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);
		if (ret || memcmp(buf, cis->cache, len) != 0) {
			kfree(buf);
			mutex_unlock(&s->ops_mutex);
			return -1;
		}
	}
	kfree(buf);
	mutex_unlock(&s->ops_mutex);
	return 0;
}

+4 −0
Original line number Diff line number Diff line
@@ -301,7 +301,9 @@ static int pccard_get_status(struct pcmcia_socket *s,
	    (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
		u_char reg;
		if (c->CardValues & PRESENT_PIN_REPLACE) {
			mutex_lock(&s->ops_mutex);
			pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
			mutex_unlock(&s->ops_mutex);
			status->CardState |=
				(reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
			status->CardState |=
@@ -315,7 +317,9 @@ static int pccard_get_status(struct pcmcia_socket *s,
			status->CardState |= CS_EVENT_READY_CHANGE;
		}
		if (c->CardValues & PRESENT_EXT_STATUS) {
			mutex_lock(&s->ops_mutex);
			pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
			mutex_unlock(&s->ops_mutex);
			status->CardState |=
				(reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
		}
+6 −7
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
	config_t *c;
	int addr;
	u_char val;
	int ret = 0;

	if (!p_dev || !p_dev->function_config)
		return -EINVAL;
@@ -139,11 +140,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
	}

	addr = (c->ConfigBase + reg->Offset) >> 1;
	mutex_unlock(&s->ops_mutex);

	switch (reg->Action) {
	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;
		break;
	case CS_WRITE:
@@ -152,10 +152,11 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
		break;
	default:
		dev_dbg(&s->dev, "Invalid conf register request\n");
		return -EINVAL;
		ret = -EINVAL;
		break;
	}
	return 0;
	mutex_unlock(&s->ops_mutex);
	return ret;
} /* 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->ops->set_socket(s, &s->socket);
	s->lock_count++;
	mutex_unlock(&s->ops_mutex);

	/* Set up CIS configuration registers */
	base = c->ConfigBase = req->ConfigBase;
@@ -485,7 +485,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,

	/* Configure I/O windows */
	if (c->state & CONFIG_IO_REQ) {
		mutex_lock(&s->ops_mutex);
		iomap.speed = io_speed;
		for (i = 0; i < MAX_IO_WIN; i++)
			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->io[i].Config++;
			}
		mutex_unlock(&s->ops_mutex);
	}

	c->state |= CONFIG_LOCKED;
	p_dev->_locked = 1;
	mutex_unlock(&s->ops_mutex);
	return 0;
} /* pcmcia_request_configuration */
EXPORT_SYMBOL(pcmcia_request_configuration);