[PATCH 13/16] pcmcia: use ops_mutex for rsrc_{mgr,nonstatic} locking

Dominik Brodowski linux at dominikbrodowski.net
Mon Jan 18 03:36:33 EST 2010


Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 Documentation/pcmcia/locking.txt |    5 +++--
 drivers/pcmcia/cs.c              |    7 ++++++-
 drivers/pcmcia/ds.c              |    6 +++++-
 drivers/pcmcia/pcmcia_ioctl.c    |    4 +---
 drivers/pcmcia/rsrc_mgr.c        |    2 --
 drivers/pcmcia/rsrc_nonstatic.c  |   35 ++++++++---------------------------
 6 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt
index d625105..68f622b 100644
--- a/Documentation/pcmcia/locking.txt
+++ b/Documentation/pcmcia/locking.txt
@@ -36,7 +36,8 @@ be called with "ops_mutex" held:
 	socket_reset()
 	socket_setup()
 
-	struct pccard_operations *ops
+	struct pccard_operations	*ops
+	struct pccard_resource_ops	*resource_ops;
 
 Note that send_event() and struct pcmcia_callback *callback must not be
 called with "ops_mutex" held.
@@ -54,7 +55,7 @@ protected by pcmcia_socket_list_rwsem;
 
 2. Per-Socket Data:
 -------------------
-The resource_ops are on their own to provide proper locking.
+The resource_ops and their data are protected by ops_mutex.
 
 The "main" struct pcmcia_socket is protected as follows (read-only fields
 or single-use fields not mentioned):
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 13277ee..7ba45b0 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -224,7 +224,9 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 	spin_lock_init(&socket->thread_lock);
 
 	if (socket->resource_ops->init) {
+		mutex_lock(&socket->ops_mutex);
 		ret = socket->resource_ops->init(socket);
+		mutex_unlock(&socket->ops_mutex);
 		if (ret)
 			goto err;
 	}
@@ -282,8 +284,11 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
 	up_write(&pcmcia_socket_list_rwsem);
 
 	/* wait for sysfs to drop all references */
-	if (socket->resource_ops->exit)
+	if (socket->resource_ops->exit) {
+		mutex_lock(&socket->ops_mutex);
 		socket->resource_ops->exit(socket);
+		mutex_unlock(&socket->ops_mutex);
+	}
 	wait_for_completion(&socket->socket_released);
 } /* pcmcia_unregister_socket */
 EXPORT_SYMBOL(pcmcia_unregister_socket);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index d61f3f1..977958f 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -615,19 +615,23 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
 {
 	cistpl_longlink_mfc_t mfc;
 	unsigned int no_funcs, i, no_chains;
-	int ret = 0;
+	int ret = -EAGAIN;
 
+	mutex_lock(&s->ops_mutex);
 	if (!(s->resource_setup_done)) {
 		dev_dbg(&s->dev,
 			   "no resources available, delaying card_add\n");
+		mutex_unlock(&s->ops_mutex);
 		return -EAGAIN; /* try again, but later... */
 	}
 
 	if (pcmcia_validate_mem(s)) {
 		dev_dbg(&s->dev, "validating mem resources failed, "
 		       "delaying card_add\n");
+		mutex_unlock(&s->ops_mutex);
 		return -EAGAIN; /* try again, but later... */
 	}
+	mutex_unlock(&s->ops_mutex);
 
 	ret = pccard_validate_cis(s, &no_chains);
 	if (ret || !no_chains) {
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index b6a01ff..61e49fe 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -188,7 +188,6 @@ static int pcmcia_adjust_resource_info(adjust_t *adj)
 				continue;
 			} else if (!(s->resource_setup_old))
 				s->resource_setup_old = 1;
-			mutex_unlock(&s->ops_mutex);
 
 			switch (adj->Resource) {
 			case RES_MEMORY_RANGE:
@@ -207,10 +206,9 @@ static int pcmcia_adjust_resource_info(adjust_t *adj)
 				 * last call to adjust_resource_info, we
 				 * always need to assume this is the latest
 				 * one... */
-				mutex_lock(&s->ops_mutex);
 				s->resource_setup_done = 1;
-				mutex_unlock(&s->ops_mutex);
 			}
+			mutex_unlock(&s->ops_mutex);
 		}
 	}
 	up_read(&pcmcia_socket_list_rwsem);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index b815866..aca2cfd 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -26,9 +26,7 @@ static int static_init(struct pcmcia_socket *s)
 	/* the good thing about SS_CAP_STATIC_MAP sockets is
 	 * that they don't need a resource database */
 
-	mutex_lock(&s->ops_mutex);
 	s->resource_setup_done = 1;
-	mutex_unlock(&s->ops_mutex);
 
 	return 0;
 }
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 1de46cf..c13424f 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -59,7 +59,6 @@ struct socket_data {
 	unsigned int			rsrc_mem_probe;
 };
 
-static DEFINE_MUTEX(rsrc_mutex);
 #define MEM_PROBE_LOW	(1 << 0)
 #define MEM_PROBE_HIGH	(1 << 1)
 
@@ -274,7 +273,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
 {
 	int ret = -EINVAL;
 
-	mutex_lock(&s->ops_mutex);
 	s->cis_mem.res = res;
 	s->cis_virt = ioremap(res->start, s->map_size);
 	if (s->cis_virt) {
@@ -288,7 +286,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
 		s->cis_virt = NULL;
 	}
 	s->cis_mem.res = NULL;
-	mutex_unlock(&s->ops_mutex);
 	if ((ret) || (*count == 0))
 		return -EINVAL;
 	return 0;
@@ -304,8 +301,6 @@ static int checksum(struct pcmcia_socket *s, struct resource *res,
 	int i, a = 0, b = -1, d;
 	void __iomem *virt;
 
-	mutex_lock(&s->ops_mutex);
-
 	virt = ioremap(res->start, s->map_size);
 	if (virt) {
 		map.map = 0;
@@ -328,8 +323,6 @@ static int checksum(struct pcmcia_socket *s, struct resource *res,
 		iounmap(virt);
 	}
 
-	mutex_unlock(&s->ops_mutex);
-
 	if (b == -1)
 		return -EINVAL;
 
@@ -570,8 +563,6 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 	if (!probe_mem)
 		return 0;
 
-	mutex_lock(&rsrc_mutex);
-
 	if (s->features & SS_CAP_PAGE_REGS)
 		probe_mask = MEM_PROBE_HIGH;
 
@@ -583,8 +574,6 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 		}
 	}
 
-	mutex_unlock(&rsrc_mutex);
-
 	return ret;
 }
 
@@ -661,7 +650,6 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
 	struct socket_data *s_data = s->resource_data;
 	int ret = -ENOMEM;
 
-	mutex_lock(&rsrc_mutex);
 	for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
 		unsigned long start = m->base;
 		unsigned long end = m->base + m->num - 1;
@@ -672,7 +660,6 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
 		ret = adjust_resource(res, r_start, r_end - r_start + 1);
 		break;
 	}
-	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -706,7 +693,6 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 	data.offset = base & data.mask;
 	data.map = &s_data->io_db;
 
-	mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
 	if (s->cb_dev) {
 		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -715,7 +701,6 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
 #endif
 		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
 					1, pcmcia_align, &data);
-	mutex_unlock(&rsrc_mutex);
 
 	if (ret != 0) {
 		kfree(res);
@@ -748,7 +733,6 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
 			min = 0x100000UL + base;
 		}
 
-		mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
 		if (s->cb_dev) {
 			ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -758,7 +742,6 @@ static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
 #endif
 			ret = allocate_resource(&iomem_resource, res, num, min,
 						max, 1, pcmcia_align, &data);
-		mutex_unlock(&rsrc_mutex);
 		if (ret == 0 || low)
 			break;
 		low = 1;
@@ -781,7 +764,6 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
 	if (end < start)
 		return -EINVAL;
 
-	mutex_lock(&rsrc_mutex);
 	switch (action) {
 	case ADD_MANAGED_RESOURCE:
 		ret = add_interval(&data->mem_db, start, size);
@@ -794,7 +776,6 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
 	default:
 		ret = -EINVAL;
 	}
-	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -812,7 +793,6 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
 	if (end > IO_SPACE_LIMIT)
 		return -EINVAL;
 
-	mutex_lock(&rsrc_mutex);
 	switch (action) {
 	case ADD_MANAGED_RESOURCE:
 		if (add_interval(&data->io_db, start, size) != 0) {
@@ -831,7 +811,6 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
 		ret = -EINVAL;
 		break;
 	}
-	mutex_unlock(&rsrc_mutex);
 
 	return ret;
 }
@@ -929,7 +908,6 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
 	struct socket_data *data = s->resource_data;
 	struct resource_map *p, *q;
 
-	mutex_lock(&rsrc_mutex);
 	for (p = data->mem_db.next; p != &data->mem_db; p = q) {
 		q = p->next;
 		kfree(p);
@@ -938,7 +916,6 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
 		q = p->next;
 		kfree(p);
 	}
-	mutex_unlock(&rsrc_mutex);
 }
 
 
@@ -965,7 +942,7 @@ static ssize_t show_io_db(struct device *dev,
 	struct resource_map *p;
 	ssize_t ret = 0;
 
-	mutex_lock(&rsrc_mutex);
+	mutex_lock(&s->ops_mutex);
 	data = s->resource_data;
 
 	for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -977,7 +954,7 @@ static ssize_t show_io_db(struct device *dev,
 				((unsigned long) p->base + p->num - 1));
 	}
 
-	mutex_unlock(&rsrc_mutex);
+	mutex_unlock(&s->ops_mutex);
 	return ret;
 }
 
@@ -1005,9 +982,11 @@ static ssize_t store_io_db(struct device *dev,
 	if (end_addr < start_addr)
 		return -EINVAL;
 
+	mutex_lock(&s->ops_mutex);
 	ret = adjust_io(s, add, start_addr, end_addr);
 	if (!ret)
 		s->resource_setup_new = 1;
+	mutex_unlock(&s->ops_mutex);
 
 	return ret ? ret : count;
 }
@@ -1021,7 +1000,7 @@ static ssize_t show_mem_db(struct device *dev,
 	struct resource_map *p;
 	ssize_t ret = 0;
 
-	mutex_lock(&rsrc_mutex);
+	mutex_lock(&s->ops_mutex);
 	data = s->resource_data;
 
 	for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -1033,7 +1012,7 @@ static ssize_t show_mem_db(struct device *dev,
 				((unsigned long) p->base + p->num - 1));
 	}
 
-	mutex_unlock(&rsrc_mutex);
+	mutex_unlock(&s->ops_mutex);
 	return ret;
 }
 
@@ -1061,9 +1040,11 @@ static ssize_t store_mem_db(struct device *dev,
 	if (end_addr < start_addr)
 		return -EINVAL;
 
+	mutex_lock(&s->ops_mutex);
 	ret = adjust_memory(s, add, start_addr, end_addr);
 	if (!ret)
 		s->resource_setup_new = 1;
+	mutex_unlock(&s->ops_mutex);
 
 	return ret ? ret : count;
 }
-- 
1.6.3.3




More information about the linux-pcmcia mailing list