X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=drivers%2Fide%2Fide-probe.c;h=994e41099b42e5e95ed08cce0154bb89b6e727b0;hb=56831a1a883bb8376ea56ce8f3b1d5844c94d257;hp=84a89561ec0f253316f4068187a512d74bb01d26;hpb=48c3c1072651922ed153bcf0a33ea82cf20df390;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 84a89561ec0..994e41099b4 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -39,8 +39,6 @@ #include #include -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 @@ -136,18 +134,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) #endif ide_fix_driveid(id); -#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) - /* - * EATA SCSI controllers do a hardware ATA emulation: - * Ignore them if there is a driver for them available. - */ - if ((id->model[0] == 'P' && id->model[1] == 'M') || - (id->model[0] == 'S' && id->model[1] == 'K')) { - printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model); - goto err_misc; - } -#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */ - /* * WIN_IDENTIFY returns little-endian info, * WIN_PIDENTIFY *usually* returns little-endian info. @@ -169,7 +155,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) if (strstr(id->model, "E X A B Y T E N E S T")) goto err_misc; - printk("%s: %s, ", drive->name, id->model); + printk(KERN_INFO "%s: %s, ", drive->name, id->model); + drive->present = 1; drive->dead = 0; @@ -178,16 +165,17 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) */ if (cmd == WIN_PIDENTIFY) { u8 type = (id->config >> 8) & 0x1f; - printk("ATAPI "); + + printk(KERN_CONT "ATAPI "); switch (type) { case ide_floppy: if (!strstr(id->model, "CD-ROM")) { if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) - printk("cdrom or floppy?, assuming "); + printk(KERN_CONT "cdrom or floppy?, assuming "); if (drive->media != ide_cdrom) { - printk ("FLOPPY"); + printk(KERN_CONT "FLOPPY"); drive->removable = 1; break; } @@ -200,25 +188,25 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) /* kludge for Apple PowerBook internal zip */ if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) { - printk ("FLOPPY"); + printk(KERN_CONT "FLOPPY"); type = ide_floppy; break; } #endif - printk ("CD/DVD-ROM"); + printk(KERN_CONT "CD/DVD-ROM"); break; case ide_tape: - printk ("TAPE"); + printk(KERN_CONT "TAPE"); break; case ide_optical: - printk ("OPTICAL"); + printk(KERN_CONT "OPTICAL"); drive->removable = 1; break; default: - printk("UNKNOWN (type %d)", type); + printk(KERN_CONT "UNKNOWN (type %d)", type); break; } - printk (" drive\n"); + printk(KERN_CONT " drive\n"); drive->media = type; /* an ATAPI device ignores DRDY */ drive->ready_stat = 0; @@ -238,7 +226,9 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) drive->removable = 1; drive->media = ide_disk; - printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" ); + + printk(KERN_CONT "%s DISK drive\n", + (id->config == 0x848a) ? "CFA" : "ATA"); return; @@ -389,7 +379,7 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd) /* Mmmm.. multiple IRQs.. * don't know which was ours */ - printk("%s: IRQ probe failed (0x%lx)\n", + printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n", drive->name, cookie); } } @@ -458,7 +448,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) return 4; } #ifdef DEBUG - printk("probing for %s: present=%d, media=%d, probetype=%s\n", + printk(KERN_INFO "probing for %s: present=%d, media=%d, probetype=%s\n", drive->name, drive->present, drive->media, (cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI"); #endif @@ -536,7 +526,8 @@ static void enable_nest (ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u8 stat; - printk("%s: enabling %s -- ", hwif->name, drive->id->model); + printk(KERN_INFO "%s: enabling %s -- ", hwif->name, drive->id->model); + SELECT_DRIVE(drive); msleep(50); tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST); @@ -640,7 +631,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); @@ -885,7 +876,7 @@ static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) if (m && m->hwgroup && m->hwgroup != new->hwgroup) { if (!new->hwgroup) return; - printk("%s: potential irq problem with %s and %s\n", + printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n", hwif->name, new->name, m->name); } if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ @@ -992,6 +983,45 @@ 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 + * the hwgroup if we were the only member + */ + if (hwif->next == hwif) { + BUG_ON(hwgroup->hwif != hwif); + kfree(hwgroup); + } else { + /* There is another interface in hwgroup. + * Unlink us, and set hwgroup->drive and ->hwif to + * something sane. + */ + ide_hwif_t *g = hwgroup->hwif; + + while (g->next != hwif) + g = g->next; + g->next = hwif->next; + if (hwgroup->hwif == hwif) { + /* Chose a random hwif for hwgroup->hwif. + * It's guaranteed that there are no drives + * left in the hwgroup. + */ + BUG_ON(hwgroup->drive != NULL); + hwgroup->hwif = g; + } + BUG_ON(hwgroup->hwif == hwif); + } + spin_unlock_irq(&ide_lock); +} + /* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. @@ -1019,8 +1049,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 || @@ -1074,6 +1105,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 */ @@ -1102,17 +1135,17 @@ static int init_irq (ide_hwif_t *hwif) } #if !defined(__mc68000__) - printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, + printk(KERN_INFO "%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, io_ports->data_addr, io_ports->status_addr, io_ports->ctl_addr, hwif->irq); #else - printk("%s at 0x%08lx on irq %d", hwif->name, + printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name, io_ports->data_addr, hwif->irq); #endif /* __mc68000__ */ if (match) - printk(" (%sed with %s)", + printk(KERN_CONT " (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name); - printk("\n"); + printk(KERN_CONT "\n"); mutex_unlock(&ide_cfg_mtx); return 0; @@ -1247,7 +1280,7 @@ static int hwif_init(ide_hwif_t *hwif) if (!hwif->irq) { hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); if (!hwif->irq) { - printk("%s: DISABLED, NO IRQ\n", hwif->name); + printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); return 0; } } @@ -1277,16 +1310,16 @@ static int hwif_init(ide_hwif_t *hwif) */ hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); if (!hwif->irq) { - printk("%s: Disabled unable to get IRQ %d.\n", + printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", hwif->name, old_irq); goto out; } if (init_irq(hwif)) { - printk("%s: probed IRQ %d and default IRQ %d failed.\n", + printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n", hwif->name, old_irq, hwif->irq); goto out; } - printk("%s: probed IRQ %d failed, using default.\n", + printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n", hwif->name, hwif->irq); done: @@ -1470,18 +1503,20 @@ static int ide_sysfs_register_port(ide_hwif_t *hwif) return rc; } +static unsigned int ide_indexes; + /** - * ide_find_port_slot - find free ide_hwifs[] slot + * ide_find_port_slot - find free port slot * @d: IDE port info * - * Return the new hwif. If we are out of free slots return NULL. + * Return the new port slot index or -ENOENT if we are out of free slots. */ -static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) +static int ide_find_port_slot(const struct ide_port_info *d) { - ide_hwif_t *hwif; - int i; + int idx = -ENOENT; u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1; + u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;; /* * Claim an unassigned slot. @@ -1493,35 +1528,33 @@ static ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d) * Unless there is a bootable card that does not use the standard * ports 0x1f0/0x170 (the ide0/ide1 defaults). */ - if (bootable) { - i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0; - - for (; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown) - goto out_found; - } + mutex_lock(&ide_cfg_mtx); + if (MAX_HWIFS == 1) { + if (ide_indexes == 0 && i == 0) + idx = 1; } else { - for (i = 2; i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown) - goto out_found; - } - for (i = 0; i < 2 && i < MAX_HWIFS; i++) { - hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown) - goto out_found; + if (bootable) { + if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1) + idx = ffz(ide_indexes | i); + } else { + if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1) + idx = ffz(ide_indexes | 3); + else if ((ide_indexes & 3) != 3) + idx = ffz(ide_indexes); } } + if (idx >= 0) + ide_indexes |= (1 << idx); + mutex_unlock(&ide_cfg_mtx); - printk(KERN_ERR "%s: no free slot for interface\n", - d ? d->name : "ide"); - - return NULL; + return idx; +} -out_found: - ide_init_port_data(hwif, i); - return hwif; +static void ide_free_port_slot(int idx) +{ + mutex_lock(&ide_cfg_mtx); + ide_indexes &= ~(1 << idx); + mutex_unlock(&ide_cfg_mtx); } struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, @@ -1536,17 +1569,29 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, for (i = 0; i < MAX_HWIFS; i++) { ide_hwif_t *hwif; + int idx; if (hws[i] == NULL) continue; - hwif = ide_find_port_slot(d); - if (hwif) { - hwif->chipset = hws[i]->chipset; + hwif = kzalloc(sizeof(*hwif), GFP_KERNEL); + if (hwif == NULL) + continue; - host->ports[i] = hwif; - host->n_ports++; + 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; } + + ide_init_port_data(hwif, idx); + + hwif->host = host; + + host->ports[i] = hwif; + host->n_ports++; } if (host->n_ports == 0) { @@ -1554,6 +1599,12 @@ struct ide_host *ide_host_alloc_all(const struct ide_port_info *d, return NULL; } + if (hws[0]) + host->dev[0] = hws[0]->dev; + + if (d) + host->host_flags = d->host_flags; + return host; } EXPORT_SYMBOL_GPL(ide_host_alloc_all); @@ -1574,19 +1625,16 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, hw_regs_t **hws) { ide_hwif_t *hwif, *mate = NULL; - u8 idx[MAX_HWIFS]; - int i, rc = 0; + int i, j = 0; for (i = 0; i < MAX_HWIFS; i++) { - idx[i] = host->ports[i] ? host->ports[i]->index : 0xff; + hwif = host->ports[i]; - if (idx[i] == 0xff) { + if (hwif == NULL) { mate = NULL; continue; } - hwif = &ide_hwifs[idx[i]]; - ide_init_port_hw(hwif, hws[i]); ide_port_apply_params(hwif); @@ -1608,10 +1656,10 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } for (i = 0; i < MAX_HWIFS; i++) { - if (idx[i] == 0xff) - continue; + hwif = host->ports[i]; - hwif = &ide_hwifs[idx[i]]; + if (hwif == NULL) + continue; if (ide_probe_port(hwif) == 0) hwif->present = 1; @@ -1625,19 +1673,20 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } for (i = 0; i < MAX_HWIFS; i++) { - if (idx[i] == 0xff) - continue; + hwif = host->ports[i]; - hwif = &ide_hwifs[idx[i]]; + if (hwif == NULL) + continue; if (hwif_init(hwif) == 0) { printk(KERN_INFO "%s: failed to initialize IDE " "interface\n", hwif->name); hwif->present = 0; - rc = -1; continue; } + j++; + if (hwif->present) ide_port_setup_devices(hwif); @@ -1648,10 +1697,10 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } for (i = 0; i < MAX_HWIFS; i++) { - if (idx[i] == 0xff) - continue; + hwif = host->ports[i]; - hwif = &ide_hwifs[idx[i]]; + if (hwif == NULL) + continue; if (hwif->chipset == ide_unknown) hwif->chipset = ide_generic; @@ -1661,10 +1710,10 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, } for (i = 0; i < MAX_HWIFS; i++) { - if (idx[i] == 0xff) - continue; + hwif = host->ports[i]; - hwif = &ide_hwifs[idx[i]]; + if (hwif == NULL) + continue; ide_sysfs_register_port(hwif); ide_proc_register_port(hwif); @@ -1673,10 +1722,52 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, ide_proc_port_register_devices(hwif); } - return rc; + return j ? 0 : -1; } EXPORT_SYMBOL_GPL(ide_host_register); +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; + + rc = ide_host_register(host, d, hws); + if (rc) { + ide_host_free(host); + return rc; + } + + if (hostp) + *hostp = host; + + return 0; +} +EXPORT_SYMBOL_GPL(ide_host_add); + +void ide_host_free(struct ide_host *host) +{ + ide_hwif_t *hwif; + int i; + + for (i = 0; i < MAX_HWIFS; i++) { + hwif = host->ports[i]; + + if (hwif == NULL) + continue; + + 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; @@ -1686,7 +1777,7 @@ void ide_host_remove(struct ide_host *host) ide_unregister(host->ports[i]); } - kfree(host); + ide_host_free(host); } EXPORT_SYMBOL_GPL(ide_host_remove); @@ -1749,7 +1840,6 @@ static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) { - struct ide_host *host; hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; memset(&hw, 0, sizeof(hw)); @@ -1762,12 +1852,6 @@ int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) (d->host_flags & IDE_HFLAG_SINGLE)) return -ENOENT; - host = ide_host_alloc(d, hws); - if (host == NULL) - return -ENOMEM; - - ide_host_register(host, d, hws); - - return 0; + return ide_host_add(d, hws, NULL); } EXPORT_SYMBOL_GPL(ide_legacy_device_add);