Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[pandora-kernel.git] / drivers / ide / ide-probe.c
index 21cdd9c..4aa76c4 100644 (file)
@@ -39,8 +39,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
 /**
  *     generic_id              -       add a generic drive id
  *     @drive: drive to make an ID block for
@@ -640,7 +638,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
        return drive->present;
 }
 
-static void hwif_release_dev (struct device *dev)
+static void hwif_release_dev(struct device *dev)
 {
        ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
 
@@ -992,10 +990,14 @@ static void ide_port_setup_devices(ide_hwif_t *hwif)
        mutex_unlock(&ide_cfg_mtx);
 }
 
+static ide_hwif_t *ide_ports[MAX_HWIFS];
+
 void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
 {
        ide_hwgroup_t *hwgroup = hwif->hwgroup;
 
+       ide_ports[hwif->index] = NULL;
+
        spin_lock_irq(&ide_lock);
        /*
         * Remove us from the hwgroup, and free
@@ -1054,8 +1056,9 @@ static int init_irq (ide_hwif_t *hwif)
         * Group up with any other hwifs that share our irq(s).
         */
        for (index = 0; index < MAX_HWIFS; index++) {
-               ide_hwif_t *h = &ide_hwifs[index];
-               if (h->hwgroup) {  /* scan only initialized hwif's */
+               ide_hwif_t *h = ide_ports[index];
+
+               if (h && h->hwgroup) {  /* scan only initialized ports */
                        if (hwif->irq == h->irq) {
                                hwif->sharing_irq = h->sharing_irq = 1;
                                if (hwif->chipset != ide_pci ||
@@ -1109,6 +1112,8 @@ static int init_irq (ide_hwif_t *hwif)
                hwgroup->timer.data = (unsigned long) hwgroup;
        }
 
+       ide_ports[hwif->index] = hwif;
+
        /*
         * Allocate the irq, if not already obtained for another hwif
         */
@@ -1576,15 +1581,18 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
                if (hws[i] == NULL)
                        continue;
 
+               hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+               if (hwif == NULL)
+                       continue;
+
                idx = ide_find_port_slot(d);
                if (idx < 0) {
                        printk(KERN_ERR "%s: no free slot for interface\n",
                                        d ? d->name : "ide");
+                       kfree(hwif);
                        continue;
                }
 
-               hwif = &ide_hwifs[idx];
-
                ide_init_port_data(hwif, idx);
 
                host->ports[i] = hwif;
@@ -1721,12 +1729,17 @@ int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
                 struct ide_host **hostp)
 {
        struct ide_host *host;
+       int rc;
 
        host = ide_host_alloc(d, hws);
        if (host == NULL)
                return -ENOMEM;
 
-       ide_host_register(host, d, hws);
+       rc = ide_host_register(host, d, hws);
+       if (rc) {
+               ide_host_free(host);
+               return rc;
+       }
 
        if (hostp)
                *hostp = host;
@@ -1735,7 +1748,7 @@ int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
 }
 EXPORT_SYMBOL_GPL(ide_host_add);
 
-void ide_host_remove(struct ide_host *host)
+void ide_host_free(struct ide_host *host)
 {
        ide_hwif_t *hwif;
        int i;
@@ -1746,12 +1759,25 @@ void ide_host_remove(struct ide_host *host)
                if (hwif == NULL)
                        continue;
 
-               ide_unregister(hwif);
                ide_free_port_slot(hwif->index);
+               kfree(hwif);
        }
 
        kfree(host);
 }
+EXPORT_SYMBOL_GPL(ide_host_free);
+
+void ide_host_remove(struct ide_host *host)
+{
+       int i;
+
+       for (i = 0; i < MAX_HWIFS; i++) {
+               if (host->ports[i])
+                       ide_unregister(host->ports[i]);
+       }
+
+       ide_host_free(host);
+}
 EXPORT_SYMBOL_GPL(ide_host_remove);
 
 void ide_port_scan(ide_hwif_t *hwif)