vserver 1.9.3
[linux-2.6.git] / drivers / pcmcia / rsrc_mgr.c
index 6869e20..620b20f 100644 (file)
@@ -88,6 +88,9 @@ static resource_map_t io_db = {
 };
 
 static DECLARE_MUTEX(rsrc_sem);
+static unsigned int rsrc_mem_probe;
+#define MEM_PROBE_LOW  (1 << 0)
+#define MEM_PROBE_HIGH (1 << 1)
 
 #ifdef CONFIG_PCMCIA_PROBE
 
@@ -301,8 +304,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
 {
        int ret = -1;
 
-       s->cis_mem.sys_start = res->start;
-       s->cis_mem.sys_stop = res->end;
        s->cis_mem.res = res;
        s->cis_virt = ioremap(res->start, s->map_size);
        if (s->cis_virt) {
@@ -312,8 +313,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
                s->cis_virt = NULL;
                destroy_cis_cache(s);
        }
-       s->cis_mem.sys_start = 0;
-       s->cis_mem.sys_stop = 0;
        s->cis_mem.res = NULL;
        if ((ret != 0) || (info->Chains == 0))
                return 0;
@@ -325,15 +324,13 @@ static int checksum(struct pcmcia_socket *s, struct resource *res)
 {
        pccard_mem_map map;
        int i, a = 0, b = -1, d;
-       void *virt;
+       void __iomem *virt;
 
        virt = ioremap(res->start, s->map_size);
        if (virt) {
                map.map = 0;
                map.flags = MAP_ACTIVE;
                map.speed = 0;
-               map.sys_start = res->start;
-               map.sys_stop = res->end;
                map.res = res;
                map.card_start = 0;
                s->ops->set_mem_map(s, &map);
@@ -457,24 +454,21 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
     return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
     resource_map_t *m, mm;
     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    static int hi = 0, lo = 0;
     u_long b, i, ok = 0;
-    int force_low = !(s->features & SS_CAP_PAGE_REGS);
 
-    down(&rsrc_sem);
     /* We do up to four passes through the list */
-    if (!force_low) {
-       if (hi++ || (inv_probe(mem_db.next, s) > 0))
-           goto out;
+    if (probe_mask & MEM_PROBE_HIGH) {
+       if (inv_probe(mem_db.next, s) > 0)
+           return;
        printk(KERN_NOTICE "cs: warning: no high memory space "
               "available!\n");
     }
-    if (lo++)
-       goto out;
+    if ((probe_mask & MEM_PROBE_LOW) == 0)
+       return;
     for (m = mem_db.next; m != &mem_db; m = mm.next) {
        mm = *m;
        /* Only probe < 1 MB */
@@ -494,38 +488,51 @@ static void validate_mem(struct pcmcia_socket *s)
            }
        }
     }
- out:
-    up(&rsrc_sem);
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    resource_map_t *m, mm;
-    static int done = 0;
+       resource_map_t *m, mm;
     
-    if (done++ == 0) {
-       down(&rsrc_sem);
        for (m = mem_db.next; m != &mem_db; m = mm.next) {
-           mm = *m;
-           if (do_mem_probe(mm.base, mm.num, s))
-               break;
+               mm = *m;
+               if (do_mem_probe(mm.base, mm.num, s))
+                       break;
        }
-       up(&rsrc_sem);
-    }
 }
 
 #endif /* CONFIG_PCMCIA_PROBE */
 
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
 void pcmcia_validate_mem(struct pcmcia_socket *s)
 {
-       down(&s->skt_sem);
+       if (probe_mem) {
+               unsigned int probe_mask;
+
+               down(&rsrc_sem);
+
+               probe_mask = MEM_PROBE_LOW;
+               if (s->features & SS_CAP_PAGE_REGS)
+                       probe_mask = MEM_PROBE_HIGH;
+
+               if (probe_mask & ~rsrc_mem_probe) {
+                       rsrc_mem_probe |= probe_mask;
 
-       if (probe_mem && s->state & SOCKET_PRESENT)
-               validate_mem(s);
+                       down(&s->skt_sem);
 
-       up(&s->skt_sem);
+                       if (s->state & SOCKET_PRESENT)
+                               validate_mem(s, probe_mask);
+
+                       up(&s->skt_sem);
+               }
+
+               up(&rsrc_sem);
+       }
 }
 
 EXPORT_SYMBOL(pcmcia_validate_mem);