diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 17:32:25 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 17:32:25 -0800 |
commit | 5b8f258758494315b69d568661a2823e24d4ad6f (patch) | |
tree | 7640e4e3d7e30392ac471420b09afbaf70d28c0d | |
parent | 526ea064f953fc5ad2fb905b537f490b9374a0f0 (diff) | |
parent | c7e324f1bd17b25fcdca33bdad01cf6eb8be4933 (diff) |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
sata_sil: add Large Block Transfer support
[libata] ata_piix: cleanup dmi strings checking
DMI: add dmi_match
libata: blacklist NCQ on OCZ CORE 2 SSD (resend)
[libata] Update kernel-doc comments to match source code
libata: perform port detach in EH
libata: when restoring SControl during detach do the PMP links first
libata: beef up iterators
-rw-r--r-- | drivers/ata/ahci.c | 8 | ||||
-rw-r--r-- | drivers/ata/ata_generic.c | 5 | ||||
-rw-r--r-- | drivers/ata/ata_piix.c | 21 | ||||
-rw-r--r-- | drivers/ata/libata-acpi.c | 19 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 204 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 116 | ||||
-rw-r--r-- | drivers/ata/libata-pmp.c | 22 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c | 22 | ||||
-rw-r--r-- | drivers/ata/pata_bf54x.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_it821x.c | 34 | ||||
-rw-r--r-- | drivers/ata/pata_ixp4xx_cf.c | 14 | ||||
-rw-r--r-- | drivers/ata/pata_legacy.c | 18 | ||||
-rw-r--r-- | drivers/ata/pata_oldpiix.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_pdc2027x.c | 29 | ||||
-rw-r--r-- | drivers/ata/pata_platform.c | 14 | ||||
-rw-r--r-- | drivers/ata/pata_radisys.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_rz1000.c | 16 | ||||
-rw-r--r-- | drivers/ata/pata_scc.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_serverworks.c | 1 | ||||
-rw-r--r-- | drivers/ata/pata_sis.c | 1 | ||||
-rw-r--r-- | drivers/ata/sata_mv.c | 1 | ||||
-rw-r--r-- | drivers/ata/sata_sil.c | 98 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 16 | ||||
-rw-r--r-- | include/linux/dmi.h | 3 | ||||
-rw-r--r-- | include/linux/libata.h | 71 |
25 files changed, 457 insertions, 280 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a67b8e7c712..656448c7fef 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1119,14 +1119,14 @@ static void ahci_start_port(struct ata_port *ap) /* turn on LEDs */ if (ap->flags & ATA_FLAG_EM) { - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { emp = &pp->em_priv[link->pmp]; ahci_transmit_led_message(ap, emp->led_state, 4); } } if (ap->flags & ATA_FLAG_SW_ACTIVITY) - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) ahci_init_sw_activity(link); } @@ -1361,7 +1361,7 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf) struct ahci_em_priv *emp; int rc = 0; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { emp = &pp->em_priv[link->pmp]; rc += sprintf(buf, "%lx\n", emp->led_state); } @@ -1941,7 +1941,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) u32 serror; /* determine active link */ - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) if (ata_link_active(link)) break; if (!link) diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 5c33767e66d..dc48a6398ab 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -57,10 +57,7 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused) if (pdev->vendor == PCI_VENDOR_ID_CENATEK) dma_enabled = 0xFF; - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->dma_mode = XFER_MW_DMA_0; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index c11936e13dd..5fdf1678d0c 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1072,20 +1072,13 @@ static int piix_broken_suspend(void) * matching is necessary because dmi_system_id.matches is * limited to four entries. */ - if (dmi_get_system_info(DMI_SYS_VENDOR) && - dmi_get_system_info(DMI_PRODUCT_NAME) && - dmi_get_system_info(DMI_PRODUCT_VERSION) && - dmi_get_system_info(DMI_PRODUCT_SERIAL) && - dmi_get_system_info(DMI_BOARD_VENDOR) && - dmi_get_system_info(DMI_BOARD_NAME) && - dmi_get_system_info(DMI_BOARD_VERSION) && - !strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_NAME), "000000") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_VERSION), "000000") && - !strcmp(dmi_get_system_info(DMI_PRODUCT_SERIAL), "000000") && - !strcmp(dmi_get_system_info(DMI_BOARD_VENDOR), "TOSHIBA") && - !strcmp(dmi_get_system_info(DMI_BOARD_NAME), "Portable PC") && - !strcmp(dmi_get_system_info(DMI_BOARD_VERSION), "Version A0")) + if (dmi_match(DMI_SYS_VENDOR, "TOSHIBA") && + dmi_match(DMI_PRODUCT_NAME, "000000") && + dmi_match(DMI_PRODUCT_VERSION, "000000") && + dmi_match(DMI_PRODUCT_SERIAL, "000000") && + dmi_match(DMI_BOARD_VENDOR, "TOSHIBA") && + dmi_match(DMI_BOARD_NAME, "Portable PC") && + dmi_match(DMI_BOARD_VERSION, "Version A0")) return 1; return 0; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index c012307d0ba..ef02e488d46 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -89,7 +89,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) ap->link.device->acpi_handle = NULL; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { acpi_integer adr = SATA_ADR(ap->port_no, link->pmp); link->device->acpi_handle = @@ -129,8 +129,8 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) struct ata_link *tlink; struct ata_device *tdev; - ata_port_for_each_link(tlink, ap) - ata_link_for_each_dev(tdev, tlink) + ata_for_each_link(tlink, ap, EDGE) + ata_for_each_dev(tdev, tlink, ALL) tdev->flags |= ATA_DFLAG_DETACH; } @@ -588,12 +588,9 @@ int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm) { struct ata_device *dev; - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ENABLED) { unsigned long xfer_mask, udma_mask; - if (!ata_dev_enabled(dev)) - continue; - xfer_mask = ata_acpi_gtm_xfermask(dev, gtm); ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask); @@ -893,7 +890,7 @@ void ata_acpi_on_resume(struct ata_port *ap) * use values set by _STM. Cache _GTF result and * schedule _GTF. */ - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { ata_acpi_clear_gtf(dev); if (ata_dev_enabled(dev) && ata_dev_get_GTF(dev, NULL) >= 0) @@ -904,7 +901,7 @@ void ata_acpi_on_resume(struct ata_port *ap) * there's no reason to evaluate IDE _GTF early * without _STM. Clear cache and schedule _GTF. */ - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { ata_acpi_clear_gtf(dev); if (ata_dev_enabled(dev)) dev->flags |= ATA_DFLAG_ACPI_PENDING; @@ -932,8 +929,8 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) if (state.event == PM_EVENT_ON) acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); - ata_link_for_each_dev(dev, &ap->link) { - if (dev->acpi_handle && ata_dev_enabled(dev)) + ata_for_each_dev(dev, &ap->link, ENABLED) { + if (dev->acpi_handle) acpi_bus_set_power(dev->acpi_handle, state.event == PM_EVENT_ON ? ACPI_STATE_D0 : ACPI_STATE_D3); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bc6695e3c84..fecca4223f8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -163,43 +163,119 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -/* - * Iterator helpers. Don't use directly. +/** + * ata_link_next - link iteration helper + * @link: the previous link, NULL to start + * @ap: ATA port containing links to iterate + * @mode: iteration mode, one of ATA_LITER_* + * + * LOCKING: + * Host lock or EH context. * - * LOCKING: - * Host lock or EH context. + * RETURNS: + * Pointer to the next link. */ -struct ata_link *__ata_port_next_link(struct ata_port *ap, - struct ata_link *link, bool dev_only) +struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, + enum ata_link_iter_mode mode) { + BUG_ON(mode != ATA_LITER_EDGE && + mode != ATA_LITER_PMP_FIRST && mode != ATA_LITER_HOST_FIRST); + /* NULL link indicates start of iteration */ - if (!link) { - if (dev_only && sata_pmp_attached(ap)) - return ap->pmp_link; - return &ap->link; - } + if (!link) + switch (mode) { + case ATA_LITER_EDGE: + case ATA_LITER_PMP_FIRST: + if (sata_pmp_attached(ap)) + return ap->pmp_link; + /* fall through */ + case ATA_LITER_HOST_FIRST: + return &ap->link; + } - /* we just iterated over the host master link, what's next? */ - if (link == &ap->link) { - if (!sata_pmp_attached(ap)) { - if (unlikely(ap->slave_link) && !dev_only) + /* we just iterated over the host link, what's next? */ + if (link == &ap->link) + switch (mode) { + case ATA_LITER_HOST_FIRST: + if (sata_pmp_attached(ap)) + return ap->pmp_link; + /* fall through */ + case ATA_LITER_PMP_FIRST: + if (unlikely(ap->slave_link)) return ap->slave_link; + /* fall through */ + case ATA_LITER_EDGE: return NULL; } - return ap->pmp_link; - } /* slave_link excludes PMP */ if (unlikely(link == ap->slave_link)) return NULL; - /* iterate to the next PMP link */ + /* we were over a PMP link */ if (++link < ap->pmp_link + ap->nr_pmp_links) return link; + + if (mode == ATA_LITER_PMP_FIRST) + return &ap->link; + return NULL; } /** + * ata_dev_next - device iteration helper + * @dev: the previous device, NULL to start + * @link: ATA link containing devices to iterate + * @mode: iteration mode, one of ATA_DITER_* + * + * LOCKING: + * Host lock or EH context. + * + * RETURNS: + * Pointer to the next device. + */ +struct ata_device *ata_dev_next(struct ata_device *dev, struct ata_link *link, + enum ata_dev_iter_mode mode) +{ + BUG_ON(mode != ATA_DITER_ENABLED && mode != ATA_DITER_ENABLED_REVERSE && + mode != ATA_DITER_ALL && mode != ATA_DITER_ALL_REVERSE); + + /* NULL dev indicates start of iteration */ + if (!dev) + switch (mode) { + case ATA_DITER_ENABLED: + case ATA_DITER_ALL: + dev = link->device; + goto check; + case ATA_DITER_ENABLED_REVERSE: + case ATA_DITER_ALL_REVERSE: + dev = link->device + ata_link_max_devices(link) - 1; + goto check; + } + + next: + /* move to the next one */ + switch (mode) { + case ATA_DITER_ENABLED: + case ATA_DITER_ALL: + if (++dev < link->device + ata_link_max_devices(link)) + goto check; + return NULL; + case ATA_DITER_ENABLED_REVERSE: + case ATA_DITER_ALL_REVERSE: + if (--dev >= link->device) + goto check; + return NULL; + } + + check: + if ((mode == ATA_DITER_ENABLED || mode == ATA_DITER_ENABLED_REVERSE) && + !ata_dev_enabled(dev)) + goto next; + return dev; +} + +/** * ata_dev_phys_link - find physical link for a device * @dev: ATA device to look up physical link for * @@ -1107,8 +1183,8 @@ static void ata_lpm_enable(struct ata_host *host) for (i = 0; i < host->n_ports; i++) { ap = host->ports[i]; - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) ata_dev_disable_pm(dev); } } @@ -2594,11 +2670,11 @@ int ata_bus_probe(struct ata_port *ap) ata_port_probe(ap); - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) tries[dev->devno] = ATA_PROBE_MAX_TRIES; retry: - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { /* If we issue an SRST then an ATA drive (not ATAPI) * may change configuration and be in PIO0 timing. If * we do a hard reset (or are coming from power on) @@ -2620,7 +2696,7 @@ int ata_bus_probe(struct ata_port *ap) /* reset and determine device classes */ ap->ops->phy_reset(ap); - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { if (!(ap->flags & ATA_FLAG_DISABLED) && dev->class != ATA_DEV_UNKNOWN) classes[dev->devno] = dev->class; @@ -2636,7 +2712,7 @@ int ata_bus_probe(struct ata_port *ap) specific sequence bass-ackwards so that PDIAG- is released by the slave device */ - ata_link_for_each_dev_reverse(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL_REVERSE) { if (tries[dev->devno]) dev->class = classes[dev->devno]; @@ -2653,24 +2729,19 @@ int ata_bus_probe(struct ata_port *ap) if (ap->ops->cable_detect) ap->cbl = ap->ops->cable_detect(ap); - /* We may have SATA bridge glue hiding here irrespective of the - reported cable types and sensed types */ - ata_link_for_each_dev(dev, &ap->link) { - if (!ata_dev_enabled(dev)) - continue; - /* SATA drives indicate we have a bridge. We don't know which - end of the link the bridge is which is a problem */ + /* We may have SATA bridge glue hiding here irrespective of + * the reported cable types and sensed types. When SATA + * drives indicate we have a bridge, we don't know which end + * of the link the bridge is which is a problem. + */ + ata_for_each_dev(dev, &ap->link, ENABLED) if (ata_id_is_sata(dev->id)) ap->cbl = ATA_CBL_SATA; - } /* After the identify sequence we can now set up the devices. We do this in the normal order so that the user doesn't get confused */ - ata_link_for_each_dev(dev, &ap->link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, &ap->link, ENABLED) { ap->link.eh_context.i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ap->link.eh_context.i.flags &= ~ATA_EHI_PRINTINFO; @@ -2683,9 +2754,8 @@ int ata_bus_probe(struct ata_port *ap) if (rc) goto fail; - ata_link_for_each_dev(dev, &ap->link) - if (ata_dev_enabled(dev)) - return 0; + ata_for_each_dev(dev, &ap->link, ENABLED) + return 0; /* no device present, disable port */ ata_port_disable(ap); @@ -3331,13 +3401,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) int rc = 0, used_dma = 0, found = 0; /* step 1: calculate xfer_mask */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { unsigned long pio_mask, dma_mask; unsigned int mode_mask; - if (!ata_dev_enabled(dev)) - continue; - mode_mask = ATA_DMA_MASK_ATA; if (dev->class == ATA_DEV_ATAPI) mode_mask = ATA_DMA_MASK_ATAPI; @@ -3366,10 +3433,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) goto out; /* step 2: always set host PIO timings */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { if (dev->pio_mode == 0xff) { ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); rc = -EINVAL; @@ -3383,8 +3447,8 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) } /* step 3: set host DMA timings */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev)) + ata_for_each_dev(dev, link, ENABLED) { + if (!ata_dma_enabled(dev)) continue; dev->xfer_mode = dev->dma_mode; @@ -3394,11 +3458,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) } /* step 4: update devices' xfer mode */ - ata_link_for_each_dev(dev, link) { - /* don't update suspended devices' xfer mode */ - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { rc = ata_dev_set_mode(dev); if (rc) goto out; @@ -4048,6 +4108,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, + { "OCZ CORE_SSD", "02.10104", ATA_HORKAGE_NONCQ }, /* Seagate NCQ + FLUSH CACHE firmware bug */ { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ | @@ -4263,9 +4324,9 @@ static int cable_is_40wire(struct ata_port *ap) * - if you have a non detect capable drive you don't want it * to colour the choice */ - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev) && !ata_is_40wire(dev)) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { + if (!ata_is_40wire(dev)) return 0; } } @@ -4672,7 +4733,6 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) /** * ata_qc_new_init - Request an available ATA command, and initialize it * @dev: Device from whom we request an available command structure - * @tag: command tag * * LOCKING: * None. @@ -5218,7 +5278,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, } ap->pflags |= ATA_PFLAG_PM_PENDING; - __ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, HOST_FIRST) { link->eh_info.action |= action; link->eh_info.flags |= ehi_flags; } @@ -6047,8 +6107,6 @@ int ata_host_activate(struct ata_host *host, int irq, static void ata_port_detach(struct ata_port *ap) { unsigned long flags; - struct ata_link *link; - struct ata_device *dev; if (!ap->ops->error_handler) goto skip_eh; @@ -6056,28 +6114,15 @@ static void ata_port_detach(struct ata_port *ap) /* tell EH we're leaving & flush EH */ spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_UNLOADING; + ata_port_schedule_eh(ap); spin_unlock_irqrestore(ap->lock, flags); + /* wait till EH commits suicide */ ata_port_wait_eh(ap); - /* EH is now guaranteed to see UNLOADING - EH context belongs - * to us. Restore SControl and disable all existing devices. - */ - __ata_port_for_each_link(link, ap) { - sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); - ata_link_for_each_dev(dev, link) - ata_dev_disable(dev); - } + /* it better be dead now */ + WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED)); - /* Final freeze & EH. All in-flight commands are aborted. EH - * will be skipped and retrials will be terminated with bad - * target. - */ - spin_lock_irqsave(ap->lock, flags); - ata_port_freeze(ap); /* won't be thawed */ - spin_unlock_irqrestore(ap->lock, flags); - - ata_port_wait_eh(ap); cancel_rearming_delayed_work(&ap->hotplug_task); skip_eh: @@ -6528,7 +6573,8 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops); EXPORT_SYMBOL_GPL(sata_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_info); -EXPORT_SYMBOL_GPL(__ata_port_next_link); +EXPORT_SYMBOL_GPL(ata_link_next); +EXPORT_SYMBOL_GPL(ata_dev_next); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_host_init); EXPORT_SYMBOL_GPL(ata_host_alloc); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 32da9a93ce4..8147a838637 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -422,7 +422,7 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, if (!dev) { ehi->action &= ~action; - ata_link_for_each_dev(tdev, link) + ata_for_each_dev(tdev, link, ALL) ehi->dev_action[tdev->devno] &= ~action; } else { /* doesn't make sense for port-wide EH actions */ @@ -430,7 +430,7 @@ static void ata_eh_clear_action(struct ata_link *link, struct ata_device *dev, /* break ehi->action into ehi->dev_action */ if (ehi->action & action) { - ata_link_for_each_dev(tdev, link) + ata_for_each_dev(tdev, link, ALL) ehi->dev_action[tdev->devno] |= ehi->action & action; ehi->action &= ~action; @@ -491,6 +491,31 @@ enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) return ret; } +static void ata_eh_unload(struct ata_port *ap) +{ + struct ata_link *link; + struct ata_device *dev; + unsigned long flags; + + /* Restore SControl IPM and SPD for the next driver and + * disable attached devices. + */ + ata_for_each_link(link, ap, PMP_FIRST) { + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); + ata_for_each_dev(dev, link, ALL) + ata_dev_disable(dev); + } + + /* freeze and set UNLOADED */ + spin_lock_irqsave(ap->lock, flags); + + ata_port_freeze(ap); /* won't be thawed */ + ap->pflags &= ~ATA_PFLAG_EH_PENDING; /* clear pending from freeze */ + ap->pflags |= ATA_PFLAG_UNLOADED; + + spin_unlock_irqrestore(ap->lock, flags); +} + /** * ata_scsi_error - SCSI layer error handler callback * @host: SCSI host on which error occurred @@ -592,7 +617,7 @@ void ata_scsi_error(struct Scsi_Host *host) /* fetch & clear EH info */ spin_lock_irqsave(ap->lock, flags); - __ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, HOST_FIRST) { struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev; @@ -600,12 +625,9 @@ void ata_scsi_error(struct Scsi_Host *host) link->eh_context.i = link->eh_info; memset(&link->eh_info, 0, sizeof(link->eh_info)); - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { int devno = dev->devno; - if (!ata_dev_enabled(dev)) - continue; - ehc->saved_xfer_mode[devno] = dev->xfer_mode; if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; @@ -621,8 +643,13 @@ void ata_scsi_error(struct Scsi_Host *host) /* invoke EH, skip if unloading or suspended */ if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) ap->ops->error_handler(ap); - else + else { + /* if unloading, commence suicide */ + if ((ap->pflags & ATA_PFLAG_UNLOADING) && + !(ap->pflags & ATA_PFLAG_UNLOADED)) + ata_eh_unload(ap); ata_eh_finish(ap); + } /* process port suspend request */ ata_eh_handle_port_suspend(ap); @@ -644,7 +671,7 @@ void ata_scsi_error(struct Scsi_Host *host) } /* this run is complete, make sure EH info is clear */ - __ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, HOST_FIRST) memset(&link->eh_info, 0, sizeof(link->eh_info)); /* Clear host_eh_scheduled while holding ap->lock such @@ -1025,7 +1052,7 @@ int sata_async_notification(struct ata_port *ap) struct ata_link *link; /* check and notify ATAPI AN */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(sntf & (1 << link->pmp))) continue; @@ -2005,7 +2032,7 @@ void ata_eh_autopsy(struct ata_port *ap) { struct ata_link *link; - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) ata_eh_link_autopsy(link); /* Handle the frigging slave link. Autopsy is done similarly @@ -2219,7 +2246,7 @@ void ata_eh_report(struct ata_port *ap) { struct ata_link *link; - __ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, HOST_FIRST) ata_eh_link_report(link); } @@ -2230,7 +2257,7 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, struct ata_device *dev; if (clear_classes) - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_UNKNOWN; return reset(link, classes, deadline); @@ -2294,7 +2321,7 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* If we issue an SRST then an ATA drive (not ATAPI) * may change configuration and be in PIO0 timing. If * we do a hard reset (or are coming from power on) @@ -2355,7 +2382,7 @@ int ata_eh_reset(struct ata_link *link, int classify, "port disabled. ignoring.\n"); ehc->i.action &= ~ATA_EH_RESET; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; rc = 0; @@ -2369,7 +2396,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * bang classes and return. */ if (reset && !(ehc->i.action & ATA_EH_RESET)) { - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; rc = 0; goto out; @@ -2454,7 +2481,7 @@ int ata_eh_reset(struct ata_link *link, int classify, /* * Post-reset processing */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* After the reset, the device state is PIO 0 and the * controller state is undefined. Reset also wakes up * drives from sleeping mode. @@ -2510,7 +2537,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * can be reliably detected and retried. */ nr_unknown = 0; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { /* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */ if (classes[dev->devno] == ATA_DEV_UNKNOWN) { classes[dev->devno] = ATA_DEV_NONE; @@ -2619,8 +2646,8 @@ static inline void ata_eh_pull_park_action(struct ata_port *ap) spin_lock_irqsave(ap->lock, flags); INIT_COMPLETION(ap->park_req_pending); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { struct ata_eh_info *ehi = &link->eh_info; link->eh_context.i.dev_action[dev->devno] |= @@ -2675,7 +2702,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, * be done backwards such that PDIAG- is released by the slave * device before the master device is identified. */ - ata_link_for_each_dev_reverse(dev, link) { + ata_for_each_dev(dev, link, ALL_REVERSE) { unsigned int action = ata_eh_dev_action(dev); unsigned int readid_flags = 0; @@ -2744,7 +2771,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, /* Configure new devices forward such that user doesn't see * device detection messages backwards. */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (!(new_mask & (1 << dev->devno)) || dev->class == ATA_DEV_PMP) continue; @@ -2793,10 +2820,7 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) int rc; /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ - ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev)) - continue; - + ata_for_each_dev(dev, link, ENABLED) { if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { struct ata_ering_entry *ent; @@ -2813,14 +2837,11 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) rc = ata_do_set_mode(link, r_failed_dev); /* if transfer mode has changed, set DUBIOUS_XFER on device */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ENABLED) { struct ata_eh_context *ehc = &link->eh_context; u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); - if (!ata_dev_enabled(dev)) - continue; - if (dev->xfer_mode != saved_xfer_mode || ata_ncq_enabled(dev) != saved_ncq) dev->flags |= ATA_DFLAG_DUBIOUS_XFER; @@ -2881,9 +2902,8 @@ static int ata_link_nr_enabled(struct ata_link *link) struct ata_device *dev; int cnt = 0; - ata_link_for_each_dev(dev, link) - if (ata_dev_enabled(dev)) - cnt++; + ata_for_each_dev(dev, link, ENABLED) + cnt++; return cnt; } @@ -2892,7 +2912,7 @@ static int ata_link_nr_vacant(struct ata_link *link) struct ata_device *dev; int cnt = 0; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) if (dev->class == ATA_DEV_UNKNOWN) cnt++; return cnt; @@ -2918,7 +2938,7 @@ static int ata_eh_skip_recovery(struct ata_link *link) return 0; /* skip if class codes for all vacant slots are ATA_DEV_NONE */ - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (dev->class == ATA_DEV_UNKNOWN && ehc->classes[dev->devno] != ATA_DEV_NONE) return 0; @@ -3026,7 +3046,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, DPRINTK("ENTER\n"); /* prep for recovery */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* re-enable link? */ @@ -3038,7 +3058,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_done(link, NULL, ATA_EH_ENABLE_LINK); } - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (link->flags & ATA_LFLAG_NO_RETRY) ehc->tries[dev->devno] = 1; else @@ -3068,19 +3088,19 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, goto out; /* prep for EH */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* skip EH if possible. */ if (ata_eh_skip_recovery(link)) ehc->i.action = 0; - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) ehc->classes[dev->devno] = ATA_DEV_UNKNOWN; } /* reset */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; if (!(ehc->i.action & ATA_EH_RESET)) @@ -3105,8 +3125,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_eh_pull_park_action(ap); deadline = jiffies; - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { struct ata_eh_context *ehc = &link->eh_context; unsigned long tmp; @@ -3134,8 +3154,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, deadline = wait_for_completion_timeout(&ap->park_req_pending, deadline - now); } while (deadline); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ALL) { if (!(link->eh_context.unloaded_mask & (1 << dev->devno))) continue; @@ -3146,7 +3166,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, } /* the rest */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_context *ehc = &link->eh_context; /* revalidate existing devices and attach new ones */ @@ -3172,7 +3192,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, * disrupting the current users of the device. */ if (ehc->i.flags & ATA_EHI_DID_RESET) { - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (dev->class != ATA_DEV_ATAPI) continue; rc = atapi_eh_clear_ua(dev); @@ -3183,7 +3203,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, /* configure link power saving */ if (ehc->i.action & ATA_EH_LPM) - ata_link_for_each_dev(dev, link) + ata_for_each_dev(dev, link, ALL) ata_dev_enable_pm(dev, ap->pm_policy); /* this link is okay now */ @@ -3288,7 +3308,7 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, rc = ata_eh_recover(ap, prereset, softreset, hardreset, postreset, NULL); if (rc) { - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) ata_dev_disable(dev); } diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index b65db309c18..98ca07a2db8 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -321,7 +321,7 @@ static void sata_pmp_quirks(struct ata_port *ap) if (vendor == 0x1095 && devid == 0x3726) { /* sil3726 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* Class code report is unreliable and SRST * times out under certain configurations. */ @@ -336,7 +336,7 @@ static void sata_pmp_quirks(struct ata_port *ap) } } else if (vendor == 0x1095 && devid == 0x4723) { /* sil4723 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* class code report is unreliable */ if (link->pmp < 2) link->flags |= ATA_LFLAG_ASSUME_ATA; @@ -348,7 +348,7 @@ static void sata_pmp_quirks(struct ata_port *ap) } } else if (vendor == 0x1095 && devid == 0x4726) { /* sil4726 quirks */ - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { /* Class code report is unreliable and SRST * times out under certain configurations. * Config device can be at port 0 or 5 and @@ -450,7 +450,7 @@ int sata_pmp_attach(struct ata_device *dev) if (ap->ops->pmp_attach) ap->ops->pmp_attach(ap); - ata_port_for_each_link(tlink, ap) + ata_for_each_link(tlink, ap, EDGE) sata_link_init_spd(tlink); ata_acpi_associate_sata_port(ap); @@ -487,7 +487,7 @@ static void sata_pmp_detach(struct ata_device *dev) if (ap->ops->pmp_detach) ap->ops->pmp_detach(ap); - ata_port_for_each_link(tlink, ap) + ata_for_each_link(tlink, ap, EDGE) ata_eh_detach_dev(tlink->device); spin_lock_irqsave(ap->lock, flags); @@ -700,7 +700,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, } /* PMP is reset, SErrors cannot be trusted, scan all */ - ata_port_for_each_link(tlink, ap) { + ata_for_each_link(tlink, ap, EDGE) { struct ata_eh_context *ehc = &tlink->eh_context; ehc->i.probe_mask |= ATA_ALL_DEVICES; @@ -768,7 +768,7 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) spin_lock_irqsave(ap->lock, flags); - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(link->flags & ATA_LFLAG_DISABLED)) continue; @@ -852,7 +852,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) int cnt, rc; pmp_tries = ATA_EH_PMP_TRIES; - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; retry: @@ -861,7 +861,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) rc = ata_eh_recover(ap, ops->prereset, ops->softreset, ops->hardreset, ops->postreset, NULL); if (rc) { - ata_link_for_each_dev(dev, &ap->link) + ata_for_each_dev(dev, &ap->link, ALL) ata_dev_disable(dev); return rc; } @@ -870,7 +870,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) return 0; /* new PMP online */ - ata_port_for_each_link(link, ap) + ata_for_each_link(link, ap, EDGE) link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES; /* fall through */ @@ -942,7 +942,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) } cnt = 0; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { if (!(gscr_error & (1 << link->pmp))) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 47c7afcb36f..0b2e14f6765 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3229,12 +3229,12 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) return; repeat: - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { struct scsi_device *sdev; int channel = 0, id = 0; - if (!ata_dev_enabled(dev) || dev->sdev) + if (dev->sdev) continue; if (ata_is_host_link(link)) @@ -3255,9 +3255,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) * failure occurred, scan would have failed silently. Check * whether all devices are attached. */ - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev) && !dev->sdev) + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { + if (!dev->sdev) goto exit_loop; } } @@ -3381,7 +3381,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) struct ata_port *ap = link->ap; struct ata_device *dev; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { unsigned long flags; if (!(dev->flags & ATA_DFLAG_DETACHED)) @@ -3496,7 +3496,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, if (devno == SCAN_WILD_CARD) { struct ata_link *link; - ata_port_for_each_link(link, ap) { + ata_for_each_link(link, ap, EDGE) { struct ata_eh_info *ehi = &link->eh_info; ehi->probe_mask |= ATA_ALL_DEVICES; ehi->action |= ATA_EH_RESET; @@ -3544,11 +3544,11 @@ void ata_scsi_dev_rescan(struct work_struct *work) spin_lock_irqsave(ap->lock, flags); - ata_port_for_each_link(link, ap) { - ata_link_for_each_dev(dev, link) { + ata_for_each_link(link, ap, EDGE) { + ata_for_each_dev(dev, link, ENABLED) { struct scsi_device *sdev = dev->sdev; - if (!ata_dev_enabled(dev) || !sdev) + if (!sdev) continue; if (scsi_device_get(sdev)) continue; diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 1266924c11f..1050fed96b2 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -356,7 +356,6 @@ static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev) * bfin_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: um - * @udma: udma mode, 0 - 6 * * Set UDMA mode for device. * diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 860ede52628..f828a29d775 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -465,24 +465,22 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->dma_mode = XFER_MW_DMA_0; - /* We do need the right mode information for DMA or PIO - and this comes from the current configuration flags */ - if (ata_id_has_dma(dev->id)) { - ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); - dev->xfer_mode = XFER_MW_DMA_0; - dev->xfer_shift = ATA_SHIFT_MWDMA; - dev->flags &= ~ATA_DFLAG_PIO; - } else { - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = XFER_PIO_0; + dev->dma_mode = XFER_MW_DMA_0; + /* We do need the right mode information for DMA or PIO + and this comes from the current configuration flags */ + if (ata_id_has_dma(dev->id)) { + ata_dev_printk(dev, KERN_INFO, "configured for DMA\n"); + dev->xfer_mode = XFER_MW_DMA_0; + dev->xfer_shift = ATA_SHIFT_MWDMA; + dev->flags &= ~ATA_DFLAG_PIO; + } else { + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } } return 0; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 2014253f6c8..b173c157ab0 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -30,14 +30,12 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } return 0; } diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 930c2208640..6c1d778b63a 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -194,15 +194,12 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - ata_dev_printk(dev, KERN_INFO, - "configured for PIO\n"); - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } + ata_for_each_dev(dev, link, ENABLED) { + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; } return 0; } @@ -641,7 +638,6 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) * qdi6580dp_set_piomode - PIO setup for dual channel * @ap: Port * @adev: Device - * @irq: interrupt line * * In dual channel mode the 6580 has one clock per channel and we have * to software clockswitch in qc_issue. @@ -1028,7 +1024,7 @@ static __init int legacy_init_one(struct legacy_probe *probe) /* Nothing found means we drop the port as its probably not there */ ret = -ENODEV; - ata_link_for_each_dev(dev, &ap->link) { + ata_for_each_dev(dev, &ap->link, ALL) { if (!ata_dev_absent(dev)) { legacy_host[probe->slot] = host; ld->platform_dev = pdev; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index c0dbc46a348..2c1a91c40c1 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -116,7 +116,6 @@ static void oldpiix_set_piomode (struct ata_port *ap, struct ata_device *adev) * oldpiix_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers * * Set MWDMA mode for device, in host controller PCI config space. * diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 0e1c2c1134d..e94efccaa48 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -281,7 +281,6 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long * pdc2027x_set_piomode - Initialize host controller PATA PIO timings * @ap: Port to configure * @adev: um - * @pio: PIO mode, 0 - 4 * * Set PIO mode for device. * @@ -326,7 +325,6 @@ static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings * @ap: Port to configure * @adev: um - * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 * * Set UDMA mode for device. * @@ -406,23 +404,20 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed if (rc < 0) return rc; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { + ata_for_each_dev(dev, link, ENABLED) { + pdc2027x_set_piomode(ap, dev); - pdc2027x_set_piomode(ap, dev); + /* + * Enable prefetch if the device support PIO only. + */ + if (dev->xfer_shift == ATA_SHIFT_PIO) { + u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1)); + ctcr1 |= (1 << 25); + iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); - /* - * Enable prefetch if the device support PIO only. - */ - if (dev->xfer_shift == ATA_SHIFT_PIO) { - u32 ctcr1 = ioread32(dev_mmio(ap, dev, PDC_CTCR1)); - ctcr1 |= (1 << 25); - iowrite32(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); - - PDPRINTK("Turn on prefetch\n"); - } else { - pdc2027x_set_dmamode(ap, dev); - } + PDPRINTK("Turn on prefetch\n"); + } else { + pdc2027x_set_dmamode(ap, dev); } } return 0; diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 77e4e3b17f5..6afa07a3764 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -34,14 +34,12 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); } return 0; } diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 0b0aa452de1..695d44ae52c 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -81,7 +81,6 @@ static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev) * radisys_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: Device to program - * @isich: True if the device is an ICH and has IOCFG registers * * Set MWDMA mode for device, in host controller PCI config space. * diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 7dfd1f3f6f3..46d6bc1bf1e 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -38,15 +38,13 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused) { struct ata_device *dev; - ata_link_for_each_dev(dev, link) { - if (ata_dev_enabled(dev)) { - /* We don't really care */ - dev->pio_mode = XFER_PIO_0; - dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); - } + ata_for_each_dev(dev, link, ENABLED) { + /* We don't really care */ + dev->pio_mode = XFER_PIO_0; + dev->xfer_mode = XFER_PIO_0; + dev->xfer_shift = ATA_SHIFT_PIO; + dev->flags |= ATA_DFLAG_PIO; + ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); } return 0; } diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index cf3707e516a..d447f1cb46e 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -210,7 +210,6 @@ static void scc_set_piomode (struct ata_port *ap, struct ata_device *adev) * scc_set_dmamode - Initialize host controller PATA DMA timings * @ap: Port whose timings we are configuring * @adev: um - * @udma: udma mode, 0 - 6 * * Set UDMA mode for device. * diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 72e41c9f969..8d2fd9dd40c 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -138,7 +138,6 @@ static struct sv_cable_table cable_detect[] = { /** * serverworks_cable_detect - cable detection * @ap: ATA port - * @deadline: deadline jiffies for the operation * * Perform cable detection according to the device and subvendor * identifications diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index e4be55e047f..27ceb42a774 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -112,7 +112,6 @@ static int sis_133_cable_detect(struct ata_port *ap) /** * sis_66_cable_detect - check for 40/80 pin * @ap: Port - * @deadline: deadline jiffies for the operation * * Perform cable detection on the UDMA66, UDMA100 and early UDMA133 * SiS IDE controllers. diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 2b24ae58b52..86918634a4c 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1836,7 +1836,6 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled) /** * mv_err_intr - Handle error interrupts on the port * @ap: ATA channel to manipulate - * @qc: affected command (non-NCQ), or NULL * * Most cases require a full reset of the chip's state machine, * which also performs a COMRESET. diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 031d7b7dee3..564c142b03b 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -46,7 +46,9 @@ #include <linux/libata.h> #define DRV_NAME "sata_sil" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.4" + +#define SIL_DMA_BOUNDARY 0x7fffffffUL enum { SIL_MMIO_BAR = 5, @@ -118,6 +120,10 @@ static void sil_dev_config(struct ata_device *dev); static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); +static void sil_qc_prep(struct ata_queued_cmd *qc); +static void sil_bmdma_setup(struct ata_queued_cmd *qc); +static void sil_bmdma_start(struct ata_queued_cmd *qc); +static void sil_bmdma_stop(struct ata_queued_cmd *qc); static void sil_freeze(struct ata_port *ap); static void sil_thaw(struct ata_port *ap); @@ -167,13 +173,22 @@ static struct pci_driver sil_pci_driver = { }; static struct scsi_host_template sil_sht = { - ATA_BMDMA_SHT(DRV_NAME), + ATA_BASE_SHT(DRV_NAME), + /** These controllers support Large Block Transfer which allows + transfer chunks up to 2GB and which cross 64KB boundaries, + therefore the DMA limits are more relaxed than standard ATA SFF. */ + .dma_boundary = SIL_DMA_BOUNDARY, + .sg_tablesize = ATA_MAX_PRD }; static struct ata_port_operations sil_ops = { .inherits = &ata_bmdma_port_ops, .dev_config = sil_dev_config, .set_mode = sil_set_mode, + .bmdma_setup = sil_bmdma_setup, + .bmdma_start = sil_bmdma_start, + .bmdma_stop = sil_bmdma_stop, + .qc_prep = sil_qc_prep, .freeze = sil_freeze, .thaw = sil_thaw, .scr_read = sil_scr_read, @@ -249,6 +264,83 @@ module_param(slow_down, int, 0444); MODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); +static void sil_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; + void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; + + /* clear start/stop bit - can safely always write 0 */ + iowrite8(0, bmdma2); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); +} + +static void sil_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *bmdma = ap->ioaddr.bmdma_addr; + + /* load PRD table addr. */ + iowrite32(ap->prd_dma, bmdma + ATA_DMA_TABLE_OFS); + + /* issue r/w command */ + ap->ops->sff_exec_command(ap, &qc->tf); +} + +static void sil_bmdma_start(struct ata_queued_cmd *qc) +{ + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + struct ata_port *ap = qc->ap; + void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; + void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; + u8 dmactl = ATA_DMA_START; + + /* set transfer direction, start host DMA transaction + Note: For Large Block Transfer to work, the DMA must be started + using the bmdma2 register. */ + if (!rw) + dmactl |= ATA_DMA_WR; + iowrite8(dmactl, bmdma2); +} + +/* The way God intended PCI IDE scatter/gather lists to look and behave... */ +static void sil_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg; + struct ata_port *ap = qc->ap; + struct ata_prd *prd, *last_prd = NULL; + unsigned int si; + + prd = &ap->prd[0]; + for_each_sg(qc->sg, sg, qc->n_elem, si) { + /* Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + u32 addr = (u32) sg_dma_address(sg); + u32 sg_len = sg_dma_len(sg); + + prd->addr = cpu_to_le32(addr); + prd->flags_len = cpu_to_le32(sg_len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len); + + last_prd = prd; + prd++; + } + + if (likely(last_prd)) + last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); +} + +static void sil_qc_prep(struct ata_queued_cmd *qc) +{ + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + sil_fill_sg(qc); +} + static unsigned char sil_get_device_cache_line(struct pci_dev *pdev) { u8 cache_line = 0; @@ -278,7 +370,7 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) if (rc) return rc; - ata_link_for_each_dev(dev, link) { + ata_for_each_dev(dev, link, ALL) { if (!ata_dev_enabled(dev)) dev_mode[dev->devno] = 0; /* PIO0/1/2 */ else if (dev->flags & ATA_DFLAG_PIO) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 4a597d8c2f7..78b989d202a 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -582,3 +582,19 @@ int dmi_walk(void (*decode)(const struct dmi_header *)) return 0; } EXPORT_SYMBOL_GPL(dmi_walk); + +/** + * dmi_match - compare a string to the dmi field (if exists) + * + * Returns true if the requested field equals to the str (including NULL). + */ +bool dmi_match(enum dmi_field f, const char *str) +{ + const char *info = dmi_get_system_info(f); + + if (info == NULL || str == NULL) + return info == str; + + return !strcmp(info, str); +} +EXPORT_SYMBOL_GPL(dmi_match); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 2bfda178f27..34161907b2f 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -47,6 +47,7 @@ extern int dmi_name_in_vendors(const char *str); extern int dmi_name_in_serial(const char *str); extern int dmi_available; extern int dmi_walk(void (*decode)(const struct dmi_header *)); +extern bool dmi_match(enum dmi_field f, const char *str); #else @@ -61,6 +62,8 @@ static inline int dmi_name_in_serial(const char *s) { return 0; } #define dmi_available 0 static inline int dmi_walk(void (*decode)(const struct dmi_header *)) { return -1; } +static inline bool dmi_match(enum dmi_field f, const char *str) + { return false; } #endif diff --git a/include/linux/libata.h b/include/linux/libata.h index ed3f26eb5df..3449de597ef 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -213,10 +213,11 @@ enum { ATA_PFLAG_FROZEN = (1 << 2), /* port is frozen */ ATA_PFLAG_RECOVERED = (1 << 3), /* recovery action performed */ ATA_PFLAG_LOADING = (1 << 4), /* boot/loading probe */ - ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */ ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */ ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */ ATA_PFLAG_RESETTING = (1 << 8), /* reset in progress */ + ATA_PFLAG_UNLOADING = (1 << 9), /* driver is being unloaded */ + ATA_PFLAG_UNLOADED = (1 << 10), /* driver is unloaded */ ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ @@ -1285,26 +1286,62 @@ static inline int ata_link_active(struct ata_link *link) return ata_tag_valid(link->active_tag) || link->sactive; } -extern struct ata_link *__ata_port_next_link(struct ata_port *ap, - struct ata_link *link, - bool dev_only); +/* + * Iterators + * + * ATA_LITER_* constants are used to select link iteration mode and + * ATA_DITER_* device iteration mode. + * + * For a custom iteration directly using ata_{link|dev}_next(), if + * @link or @dev, respectively, is NULL, the first element is + * returned. @dev and @link can be any valid device or link and the + * next element according to the iteration mode will be returned. + * After the last element, NULL is returned. + */ +enum ata_link_iter_mode { + ATA_LITER_EDGE, /* if present, PMP links only; otherwise, + * host link. no slave link */ + ATA_LITER_HOST_FIRST, /* host link followed by PMP or slave links */ + ATA_LITER_PMP_FIRST, /* PMP links followed by host link, + * slave link still comes after host link */ +}; -#define __ata_port_for_each_link(link, ap) \ - for ((link) = __ata_port_next_link((ap), NULL, false); (link); \ - (link) = __ata_port_next_link((ap), (link), false)) +enum ata_dev_iter_mode { + ATA_DITER_ENABLED, + ATA_DITER_ENABLED_REVERSE, + ATA_DITER_ALL, + ATA_DITER_ALL_REVERSE, +}; -#define ata_port_for_each_link(link, ap) \ - for ((link) = __ata_port_next_link((ap), NULL, true); (link); \ - (link) = __ata_port_next_link((ap), (link), true)) +extern struct ata_link *ata_link_next(struct ata_link *link, + struct ata_port *ap, + enum ata_link_iter_mode mode); -#define ata_link_for_each_dev(dev, link) \ - for ((dev) = (link)->device; \ - (dev) < (link)->device + ata_link_max_devices(link) || ((dev) = NULL); \ - (dev)++) +extern struct ata_device *ata_dev_next(struct ata_device *dev, + struct ata_link *link, + enum ata_dev_iter_mode mode); + +/* + * Shortcut notation for iterations + * + * ata_for_each_link() iterates over each link of @ap according to + * @mode. @link points to the current link in the loop. @link is + * NULL after loop termination. ata_for_each_dev() works the same way + * except that it iterates over each device of @link. + * + * Note that the mode prefixes ATA_{L|D}ITER_ shouldn't need to be + * specified when using the following shorthand notations. Only the + * mode itself (EDGE, HOST_FIRST, ENABLED, etc...) should be + * specified. This not only increases brevity but also makes it + * impossible to use ATA_LITER_* for device iteration or vice-versa. + */ +#define ata_for_each_link(link, ap, mode) \ + for ((link) = ata_link_next(NULL, (ap), ATA_LITER_##mode); (link); \ + (link) = ata_link_next((link), (ap), ATA_LITER_##mode)) -#define ata_link_for_each_dev_reverse(dev, link) \ - for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \ - (dev) >= (link)->device || ((dev) = NULL); (dev)--) +#define ata_for_each_dev(dev, link, mode) \ + for ((dev) = ata_dev_next(NULL, (link), ATA_DITER_##mode); (dev); \ + (dev) = ata_dev_next((dev), (link), ATA_DITER_##mode)) /** * ata_ncq_enabled - Test whether NCQ is enabled |