[PATCH] pcmcia: validate_mem shouldn't be void
Dominik Brodowski [Wed, 28 Sep 2005 17:41:56 +0000 (19:41 +0200)]
Add a return value to pcmcia_validate_mem.  Only if we have enough memory
available to map the CIS, we should proceed in trying to determine information
about the device.

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

drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
include/pcmcia/ss.h

index 55867bc..634426b 100644 (file)
@@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socket *s);
 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
 
 /* In rsrc_mgr */
-void pcmcia_validate_mem(struct pcmcia_socket *s);
+int pcmcia_validate_mem(struct pcmcia_socket *s);
 struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
                   struct pcmcia_socket *s);
 int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
index 6fb7639..b120794 100644 (file)
@@ -583,7 +583,9 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
        if (!(s->resource_setup_done))
                return -EAGAIN; /* try again, but later... */
 
-       pcmcia_validate_mem(s);
+       if (pcmcia_validate_mem(s))
+               return -EAGAIN; /* try again, but later... */
+
        ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
        if (ret || !cisinfo.Chains) {
                ds_dbg(0, "invalid CIS or invalid resources\n");
index 0668384..b02598a 100644 (file)
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
 }
 EXPORT_SYMBOL(pcmcia_adjust_resource_info);
 
-void pcmcia_validate_mem(struct pcmcia_socket *s)
+int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
        if (s->resource_ops->validate_mem)
-               s->resource_ops->validate_mem(s);
+               return s->resource_ops->validate_mem(s);
+       /* if there is no callback, we can assume that everything is OK */
+       return 0;
 }
 EXPORT_SYMBOL(pcmcia_validate_mem);
 
index 00960a3..ebfcab5 100644 (file)
@@ -407,56 +407,62 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
 
 static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
 {
-    struct socket_data *s_data = s->resource_data;
-    u_long ok;
-    if (m == &s_data->mem_db)
-       return 0;
-    ok = inv_probe(m->next, s);
-    if (ok) {
-       if (m->base >= 0x100000)
-           sub_interval(&s_data->mem_db, m->base, m->num);
-       return ok;
-    }
-    if (m->base < 0x100000)
-       return 0;
-    return do_mem_probe(m->base, m->num, s);
+       struct socket_data *s_data = s->resource_data;
+       u_long ok;
+       if (m == &s_data->mem_db)
+               return 0;
+       ok = inv_probe(m->next, s);
+       if (ok) {
+               if (m->base >= 0x100000)
+                       sub_interval(&s_data->mem_db, m->base, m->num);
+               return ok;
+       }
+       if (m->base < 0x100000)
+               return 0;
+       return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    struct resource_map *m, mm;
-    static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    u_long b, i, ok = 0;
-    struct socket_data *s_data = s->resource_data;
+       struct resource_map *m, mm;
+       static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+       unsigned long b, i, ok = 0;
+       struct socket_data *s_data = s->resource_data;
 
-    /* We do up to four passes through the list */
-    if (probe_mask & MEM_PROBE_HIGH) {
-       if (inv_probe(s_data->mem_db.next, s) > 0)
-           return;
-       printk(KERN_NOTICE "cs: warning: no high memory space "
-              "available!\n");
-    }
-    if ((probe_mask & MEM_PROBE_LOW) == 0)
-       return;
-    for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
-       mm = *m;
-       /* Only probe < 1 MB */
-       if (mm.base >= 0x100000) continue;
-       if ((mm.base | mm.num) & 0xffff) {
-           ok += do_mem_probe(mm.base, mm.num, s);
-           continue;
+       /* We do up to four passes through the list */
+       if (probe_mask & MEM_PROBE_HIGH) {
+               if (inv_probe(s_data->mem_db.next, s) > 0)
+                       return 0;
+               printk(KERN_NOTICE "cs: warning: no high memory space "
+                      "available!\n");
+               return -ENODEV;
        }
-       /* Special probe for 64K-aligned block */
-       for (i = 0; i < 4; i++) {
-           b = order[i] << 12;
-           if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
-               if (ok >= mem_limit)
-                   sub_interval(&s_data->mem_db, b, 0x10000);
-               else
-                   ok += do_mem_probe(b, 0x10000, s);
-           }
+
+       for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+               mm = *m;
+               /* Only probe < 1 MB */
+               if (mm.base >= 0x100000)
+                       continue;
+               if ((mm.base | mm.num) & 0xffff) {
+                       ok += do_mem_probe(mm.base, mm.num, s);
+                       continue;
+               }
+               /* Special probe for 64K-aligned block */
+               for (i = 0; i < 4; i++) {
+                       b = order[i] << 12;
+                       if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+                               if (ok >= mem_limit)
+                                       sub_interval(&s_data->mem_db, b, 0x10000);
+                               else
+                                       ok += do_mem_probe(b, 0x10000, s);
+                       }
+               }
        }
-    }
+
+       if (ok > 0)
+               return 0;
+
+       return -ENODEV;
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
@@ -478,27 +484,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 /*
  * Locking note: Must be called with skt_sem held!
  */
-static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
 {
        struct socket_data *s_data = s->resource_data;
-       if (probe_mem) {
-               unsigned int probe_mask;
+       unsigned int probe_mask = MEM_PROBE_LOW;
+       int ret = 0;
 
-               down(&rsrc_sem);
+       if (!probe_mem)
+               return 0;
 
-               probe_mask = MEM_PROBE_LOW;
-               if (s->features & SS_CAP_PAGE_REGS)
-                       probe_mask = MEM_PROBE_HIGH;
+       down(&rsrc_sem);
 
-               if (probe_mask & ~s_data->rsrc_mem_probe) {
+       if (s->features & SS_CAP_PAGE_REGS)
+               probe_mask = MEM_PROBE_HIGH;
+
+       if (probe_mask & ~s_data->rsrc_mem_probe) {
+               if (s->state & SOCKET_PRESENT)
+                       ret = validate_mem(s, probe_mask);
+               if (!ret)
                        s_data->rsrc_mem_probe |= probe_mask;
+       }
 
-                       if (s->state & SOCKET_PRESENT)
-                               validate_mem(s, probe_mask);
-               }
+       up(&rsrc_sem);
 
-               up(&rsrc_sem);
-       }
+       return ret;
 }
 
 struct pcmcia_align_data {
index 9f7dab8..2889a69 100644 (file)
@@ -125,7 +125,7 @@ struct pccard_operations {
 };
 
 struct pccard_resource_ops {
-       void    (*validate_mem)         (struct pcmcia_socket *s);
+       int     (*validate_mem)         (struct pcmcia_socket *s);
        int     (*adjust_io_region)     (struct resource *res,
                                         unsigned long r_start,
                                         unsigned long r_end,