pcmcia: use ops_mutex for rsrc_{mgr,nonstatic} locking
Dominik Brodowski [Sun, 17 Jan 2010 18:31:45 +0000 (19:31 +0100)]
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

Documentation/pcmcia/locking.txt
drivers/pcmcia/cs.c
drivers/pcmcia/ds.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c

index d625105..68f622b 100644 (file)
@@ -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):
index 13277ee..7ba45b0 100644 (file)
@@ -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);
index 253d9ac..76a2163 100644 (file)
@@ -607,19 +607,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) {
index db2e3db..96fd236 100644 (file)
@@ -187,7 +187,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:
@@ -206,10 +205,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);
index b815866..aca2cfd 100644 (file)
@@ -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;
 }
index 1de46cf..c13424f 100644 (file)
@@ -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;
 }