pcmcia: call pcmcia_{read,write}_cis_mem with ops_mutex held
Dominik Brodowski [Tue, 30 Mar 2010 16:07:50 +0000 (18:07 +0200)]
This avoids multiple lock takings in several codepaths.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

drivers/pcmcia/cistpl.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c

index e0b09e7..60d428b 100644 (file)
@@ -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;
 }
 
index a42a6c7..ef0c5f1 100644 (file)
@@ -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;
                }
index c6419c1..29f91fa 100644 (file)
@@ -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);