Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / pcmcia / rsrc_nonstatic.c
index 5876bab..0f8b157 100644 (file)
@@ -12,7 +12,6 @@
  * (C) 1999            David A. Hinds
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -61,7 +60,7 @@ struct socket_data {
        unsigned int                    rsrc_mem_probe;
 };
 
-static DECLARE_MUTEX(rsrc_sem);
+static DEFINE_MUTEX(rsrc_mutex);
 #define MEM_PROBE_LOW  (1 << 0)
 #define MEM_PROBE_HIGH (1 << 1)
 
@@ -75,10 +74,9 @@ static DECLARE_MUTEX(rsrc_sem);
 static struct resource *
 make_resource(unsigned long b, unsigned long n, int flags, char *name)
 {
-       struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+       struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
 
        if (res) {
-               memset(res, 0, sizeof(*res));
                res->name = name;
                res->start = b;
                res->end = b + n - 1;
@@ -200,12 +198,11 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
           base, base+num-1);
 
     /* First, what does a floating port look like? */
-    b = kmalloc(256, GFP_KERNEL);
+    b = kzalloc(256, GFP_KERNEL);
     if (!b) {
             printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
             return;
     }
-    memset(b, 0, 256);
     for (i = base, most = 0; i < base+num; i += 8) {
        res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
        if (!res)
@@ -372,6 +369,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;
@@ -404,99 +404,111 @@ 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 */
 
-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;
        struct socket_data *s_data = s->resource_data;
+       unsigned long ok = 0;
 
        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;
+               ok += do_mem_probe(mm.base, mm.num, s);
        }
+       if (ok > 0)
+               return 0;
+       return -ENODEV;
 }
 
 #endif /* CONFIG_PCMCIA_PROBE */
 
 
 /*
- * Locking note: Must be called with skt_sem held!
+ * Locking note: Must be called with skt_mutex 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;
+
+       if (!probe_mem)
+               return 0;
 
-               down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
 
-               probe_mask = MEM_PROBE_LOW;
-               if (s->features & SS_CAP_PAGE_REGS)
-                       probe_mask = MEM_PROBE_HIGH;
+       if (s->features & SS_CAP_PAGE_REGS)
+               probe_mask = MEM_PROBE_HIGH;
 
-               if (probe_mask & ~s_data->rsrc_mem_probe) {
+       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);
-               }
+       mutex_unlock(&rsrc_mutex);
 
-               up(&rsrc_sem);
-       }
+       return ret;
 }
 
 struct pcmcia_align_data {
@@ -572,7 +584,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
        struct socket_data *s_data = s->resource_data;
        int ret = -ENOMEM;
 
-       down(&rsrc_sem);
+       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;
@@ -583,7 +595,7 @@ 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;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -601,7 +613,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
 
 ======================================================================*/
 
-struct resource *nonstatic_find_io_region(unsigned long base, int num,
+static struct resource *nonstatic_find_io_region(unsigned long base, int num,
                   unsigned long align, struct pcmcia_socket *s)
 {
        struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
@@ -617,7 +629,7 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num,
        data.offset = base & data.mask;
        data.map = &s_data->io_db;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
        if (s->cb_dev) {
                ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -626,7 +638,7 @@ 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);
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        if (ret != 0) {
                kfree(res);
@@ -635,8 +647,8 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num,
        return res;
 }
 
-struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align,
-                                int low, struct pcmcia_socket *s)
+static struct resource * nonstatic_find_mem_region(u_long base, u_long num,
+               u_long align, int low, struct pcmcia_socket *s)
 {
        struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
        struct socket_data *s_data = s->resource_data;
@@ -659,7 +671,7 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig
                        min = 0x100000UL + base;
                }
 
-               down(&rsrc_sem);
+               mutex_lock(&rsrc_mutex);
 #ifdef CONFIG_PCI
                if (s->cb_dev) {
                        ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -669,7 +681,7 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig
 #endif
                        ret = allocate_resource(&iomem_resource, res, num, min,
                                                max, 1, pcmcia_align, &data);
-               up(&rsrc_sem);
+               mutex_unlock(&rsrc_mutex);
                if (ret == 0 || low)
                        break;
                low = 1;
@@ -683,27 +695,23 @@ struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long alig
 }
 
 
-static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
+static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
 {
-       u_long base, num;
        struct socket_data *data = s->resource_data;
-       int ret;
-
-       base = adj->resource.memory.Base;
-       num = adj->resource.memory.Size;
-       if ((num == 0) || (base+num-1 < base))
-               return CS_BAD_SIZE;
+       unsigned long size = end - start + 1;
+       int ret = 0;
 
-       ret = CS_SUCCESS;
+       if (end < start)
+               return -EINVAL;
 
-       down(&rsrc_sem);
-       switch (adj->Action) {
+       mutex_lock(&rsrc_mutex);
+       switch (action) {
        case ADD_MANAGED_RESOURCE:
-               ret = add_interval(&data->mem_db, base, num);
+               ret = add_interval(&data->mem_db, start, size);
                break;
        case REMOVE_MANAGED_RESOURCE:
-               ret = sub_interval(&data->mem_db, base, num);
-               if (ret == CS_SUCCESS) {
+               ret = sub_interval(&data->mem_db, start, size);
+               if (!ret) {
                        struct pcmcia_socket *socket;
                        down_read(&pcmcia_socket_list_rwsem);
                        list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
@@ -712,47 +720,46 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj)
                }
                break;
        default:
-               ret = CS_UNSUPPORTED_FUNCTION;
+               ret = -EINVAL;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
 
 
-static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
+static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
 {
        struct socket_data *data = s->resource_data;
-       kio_addr_t base, num;
-       int ret = CS_SUCCESS;
-
-       base = adj->resource.io.BasePort;
-       num = adj->resource.io.NumPorts;
-       if ((base < 0) || (base > 0xffff))
-               return CS_BAD_BASE;
-       if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
-               return CS_BAD_SIZE;
-
-       down(&rsrc_sem);
-       switch (adj->Action) {
+       unsigned long size = end - start + 1;
+       int ret = 0;
+
+       if (end < start)
+               return -EINVAL;
+
+       if (end > IO_SPACE_LIMIT)
+               return -EINVAL;
+
+       mutex_lock(&rsrc_mutex);
+       switch (action) {
        case ADD_MANAGED_RESOURCE:
-               if (add_interval(&data->io_db, base, num) != 0) {
-                       ret = CS_IN_USE;
+               if (add_interval(&data->io_db, start, size) != 0) {
+                       ret = -EBUSY;
                        break;
                }
 #ifdef CONFIG_PCMCIA_PROBE
                if (probe_io)
-                       do_io_probe(s, base, num);
+                       do_io_probe(s, start, size);
 #endif
                break;
        case REMOVE_MANAGED_RESOURCE:
-               sub_interval(&data->io_db, base, num);
+               sub_interval(&data->io_db, start, size);
                break;
        default:
-               ret = CS_UNSUPPORTED_FUNCTION;
+               ret = -EINVAL;
                break;
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 
        return ret;
 }
@@ -760,29 +767,97 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj)
 
 static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
 {
+       unsigned long end;
+
        switch (adj->Resource) {
        case RES_MEMORY_RANGE:
-               return adjust_memory(s, adj);
+               end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
+               return adjust_memory(s, adj->Action, adj->resource.memory.Base, end);
        case RES_IO_RANGE:
-               return adjust_io(s, adj);
+               end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
+               return adjust_io(s, adj->Action, adj->resource.io.BasePort, end);
        }
        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)
+       /* 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;
 
-       data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+       data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
-       memset(data, 0, sizeof(struct socket_data));
 
        data->mem_db.next = &data->mem_db;
        data->io_db.next = &data->io_db;
 
        s->resource_data = (void *) data;
 
+       nonstatic_autoadd_resources(s);
+
        return 0;
 }
 
@@ -791,7 +866,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
        struct socket_data *data = s->resource_data;
        struct resource_map *p, *q;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        for (p = data->mem_db.next; p != &data->mem_db; p = q) {
                q = p->next;
                kfree(p);
@@ -800,7 +875,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
                q = p->next;
                kfree(p);
        }
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
 }
 
 
@@ -825,7 +900,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
        struct resource_map *p;
        ssize_t ret = 0;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        data = s->resource_data;
 
        for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -837,7 +912,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf)
                                 ((unsigned long) p->base + p->num - 1));
        }
 
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
        return (ret);
 }
 
@@ -845,30 +920,26 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
 {
        struct pcmcia_socket *s = class_get_devdata(class_dev);
        unsigned long start_addr, end_addr;
-       unsigned int add = 1;
-       adjust_t adj;
+       unsigned int add = ADD_MANAGED_RESOURCE;
        ssize_t ret = 0;
 
        ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
        if (ret != 2) {
                ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
-               add = 0;
+               add = REMOVE_MANAGED_RESOURCE;
                if (ret != 2) {
                        ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
-                       add = 1;
+                       add = ADD_MANAGED_RESOURCE;
                        if (ret != 2)
                                return -EINVAL;
                }
        }
-       if (end_addr <= start_addr)
+       if (end_addr < start_addr)
                return -EINVAL;
 
-       adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE;
-       adj.Resource = RES_IO_RANGE;
-       adj.resource.io.BasePort = start_addr;
-       adj.resource.io.NumPorts = end_addr - start_addr + 1;
-
-       ret = adjust_io(s, &adj);
+       ret = adjust_io(s, add, start_addr, end_addr);
+       if (!ret)
+               s->resource_setup_new = 1;
 
        return ret ? ret : count;
 }
@@ -881,7 +952,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
        struct resource_map *p;
        ssize_t ret = 0;
 
-       down(&rsrc_sem);
+       mutex_lock(&rsrc_mutex);
        data = s->resource_data;
 
        for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -893,7 +964,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
                                 ((unsigned long) p->base + p->num - 1));
        }
 
-       up(&rsrc_sem);
+       mutex_unlock(&rsrc_mutex);
        return (ret);
 }
 
@@ -901,30 +972,26 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
 {
        struct pcmcia_socket *s = class_get_devdata(class_dev);
        unsigned long start_addr, end_addr;
-       unsigned int add = 1;
-       adjust_t adj;
+       unsigned int add = ADD_MANAGED_RESOURCE;
        ssize_t ret = 0;
 
        ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
        if (ret != 2) {
                ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
-               add = 0;
+               add = REMOVE_MANAGED_RESOURCE;
                if (ret != 2) {
                        ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
-                       add = 1;
+                       add = ADD_MANAGED_RESOURCE;
                        if (ret != 2)
                                return -EINVAL;
                }
        }
-       if (end_addr <= start_addr)
+       if (end_addr < start_addr)
                return -EINVAL;
 
-       adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE;
-       adj.Resource = RES_MEMORY_RANGE;
-       adj.resource.memory.Base = start_addr;
-       adj.resource.memory.Size = end_addr - start_addr + 1;
-
-       ret = adjust_memory(s, &adj);
+       ret = adjust_memory(s, add, start_addr, end_addr);
+       if (!ret)
+               s->resource_setup_new = 1;
 
        return ret ? ret : count;
 }
@@ -936,7 +1003,8 @@ static struct class_device_attribute *pccard_rsrc_attributes[] = {
        NULL,
 };
 
-static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
+static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev,
+                                          struct class_interface *class_intf)
 {
        struct pcmcia_socket *s = class_get_devdata(class_dev);
        struct class_device_attribute **attr;
@@ -953,7 +1021,8 @@ static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
        return ret;
 }
 
-static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
+static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev,
+                                              struct class_interface *class_intf)
 {
        struct pcmcia_socket *s = class_get_devdata(class_dev);
        struct class_device_attribute **attr;