]> err.no Git - linux-2.6/blobdiff - drivers/pcmcia/rsrc_nonstatic.c
[PATCH] PCI: Run PCI driver initialization on local node
[linux-2.6] / drivers / pcmcia / rsrc_nonstatic.c
index 6b463609a3aa91f6ff862e82905845398ca1e515..c42455d20eb683c6d2c99de733966ad403c5941d 100644 (file)
@@ -372,6 +372,9 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
           base, base+num-1);
     bad = fail = 0;
     step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
+    /* don't allow too large steps */
+    if (step > 0x800000)
+       step = 0x800000;
     /* cis_readable wants to map 2x map_size */
     if (step < 2 * s->map_size)
        step = 2 * s->map_size;
@@ -465,8 +468,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 
        for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
                mm = *m;
-               if (do_mem_probe(mm.base, mm.num, s))
-                       break;
+               do_mem_probe(mm.base, mm.num, s);
        }
 }
 
@@ -768,6 +770,69 @@ static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj
        return CS_UNSUPPORTED_FUNCTION;
 }
 
+#ifdef CONFIG_PCI
+static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
+{
+       struct resource *res;
+       int i, done = 0;
+
+       if (!s->cb_dev || !s->cb_dev->bus)
+               return -ENODEV;
+
+#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
+       /* If this is the root bus, the risk of hitting
+        * some strange system devices which aren't protected
+        * by either ACPI resource tables or properly requested
+        * resources is too big. Therefore, don't do auto-adding
+        * of resources at the moment.
+        */
+       if (s->cb_dev->bus->number == 0)
+               return -EINVAL;
+#endif
+
+       for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) {
+               res = s->cb_dev->bus->resource[i];
+               if (!res)
+                       continue;
+
+               if (res->flags & IORESOURCE_IO) {
+                       if (res == &ioport_resource)
+                               continue;
+                       printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n",
+                              res->start, res->end);
+                       if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
+                               done |= IORESOURCE_IO;
+
+               }
+
+               if (res->flags & IORESOURCE_MEM) {
+                       if (res == &iomem_resource)
+                               continue;
+                       printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n",
+                              res->start, res->end);
+                       if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
+                               done |= IORESOURCE_MEM;
+               }
+       }
+
+       /* if we got at least one of IO, and one of MEM, we can be glad and
+        * activate the PCMCIA subsystem */
+       if (done & (IORESOURCE_MEM | IORESOURCE_IO))
+               s->resource_setup_done = 1;
+
+       return 0;
+}
+
+#else
+
+static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
+{
+       return -ENODEV;
+}
+
+#endif
+
+
 static int nonstatic_init(struct pcmcia_socket *s)
 {
        struct socket_data *data;
@@ -782,6 +847,8 @@ static int nonstatic_init(struct pcmcia_socket *s)
 
        s->resource_data = (void *) data;
 
+       nonstatic_autoadd_resources(s);
+
        return 0;
 }
 
@@ -862,6 +929,8 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
                return -EINVAL;
 
        ret = adjust_io(s, add, start_addr, end_addr);
+       if (!ret)
+               s->resource_setup_new = 1;
 
        return ret ? ret : count;
 }
@@ -912,6 +981,8 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
                return -EINVAL;
 
        ret = adjust_memory(s, add, start_addr, end_addr);
+       if (!ret)
+               s->resource_setup_new = 1;
 
        return ret ? ret : count;
 }