Commit 1eca4365 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

libata: beef up iterators

There currently are the following looping constructs.

* __ata_port_for_each_link() for all available links
* ata_port_for_each_link() for edge links
* ata_link_for_each_dev() for all devices
* ata_link_for_each_dev_reverse() for all devices in reverse order

Now there's a need for looping construct which is similar to
__ata_port_for_each_link() but iterates over PMP links before the host
link.  Instead of adding another one with long name, do the following
cleanup.

* Implement and export ata_link_next() and ata_dev_next() which take
  @mode parameter and can be used to build custom loop.
* Implement ata_for_each_link() and ata_for_each_dev() which take
  looping mode explicitly.

The following iteration modes are implemented.

* ATA_LITER_EDGE		: loop over edge links
* ATA_LITER_HOST_FIRST		: loop over all links, host link first
* ATA_LITER_PMP_FIRST		: loop over all links, PMP links first

* ATA_DITER_ENABLED		: loop over enabled devices
* ATA_DITER_ENABLED_REVERSE	: loop over enabled devices in reverse order
* ATA_DITER_ALL			: loop over all devices
* ATA_DITER_ALL_REVERSE		: loop over all devices in reverse order

This change removes exlicit device enabledness checks from many loops
and makes it clear which ones are iterated over in which direction.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 3c92ec8a
...@@ -1119,14 +1119,14 @@ static void ahci_start_port(struct ata_port *ap) ...@@ -1119,14 +1119,14 @@ static void ahci_start_port(struct ata_port *ap)
/* turn on LEDs */ /* turn on LEDs */
if (ap->flags & ATA_FLAG_EM) { 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]; emp = &pp->em_priv[link->pmp];
ahci_transmit_led_message(ap, emp->led_state, 4); ahci_transmit_led_message(ap, emp->led_state, 4);
} }
} }
if (ap->flags & ATA_FLAG_SW_ACTIVITY) 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); ahci_init_sw_activity(link);
} }
...@@ -1361,7 +1361,7 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf) ...@@ -1361,7 +1361,7 @@ static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
struct ahci_em_priv *emp; struct ahci_em_priv *emp;
int rc = 0; int rc = 0;
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
emp = &pp->em_priv[link->pmp]; emp = &pp->em_priv[link->pmp];
rc += sprintf(buf, "%lx\n", emp->led_state); rc += sprintf(buf, "%lx\n", emp->led_state);
} }
...@@ -1941,7 +1941,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ...@@ -1941,7 +1941,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
u32 serror; u32 serror;
/* determine active link */ /* determine active link */
ata_port_for_each_link(link, ap) ata_for_each_link(link, ap, EDGE)
if (ata_link_active(link)) if (ata_link_active(link))
break; break;
if (!link) if (!link)
......
...@@ -57,10 +57,7 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused) ...@@ -57,10 +57,7 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
if (pdev->vendor == PCI_VENDOR_ID_CENATEK) if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
dma_enabled = 0xFF; dma_enabled = 0xFF;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (!ata_dev_enabled(dev))
continue;
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->dma_mode = XFER_MW_DMA_0; dev->dma_mode = XFER_MW_DMA_0;
......
...@@ -89,7 +89,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) ...@@ -89,7 +89,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap)
ap->link.device->acpi_handle = NULL; 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); acpi_integer adr = SATA_ADR(ap->port_no, link->pmp);
link->device->acpi_handle = link->device->acpi_handle =
...@@ -129,8 +129,8 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) ...@@ -129,8 +129,8 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
struct ata_link *tlink; struct ata_link *tlink;
struct ata_device *tdev; struct ata_device *tdev;
ata_port_for_each_link(tlink, ap) ata_for_each_link(tlink, ap, EDGE)
ata_link_for_each_dev(tdev, tlink) ata_for_each_dev(tdev, tlink, ALL)
tdev->flags |= ATA_DFLAG_DETACH; tdev->flags |= ATA_DFLAG_DETACH;
} }
...@@ -588,12 +588,9 @@ int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm) ...@@ -588,12 +588,9 @@ int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm)
{ {
struct ata_device *dev; 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; unsigned long xfer_mask, udma_mask;
if (!ata_dev_enabled(dev))
continue;
xfer_mask = ata_acpi_gtm_xfermask(dev, gtm); xfer_mask = ata_acpi_gtm_xfermask(dev, gtm);
ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask); ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask);
...@@ -893,7 +890,7 @@ void ata_acpi_on_resume(struct ata_port *ap) ...@@ -893,7 +890,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
* use values set by _STM. Cache _GTF result and * use values set by _STM. Cache _GTF result and
* schedule _GTF. * schedule _GTF.
*/ */
ata_link_for_each_dev(dev, &ap->link) { ata_for_each_dev(dev, &ap->link, ALL) {
ata_acpi_clear_gtf(dev); ata_acpi_clear_gtf(dev);
if (ata_dev_enabled(dev) && if (ata_dev_enabled(dev) &&
ata_dev_get_GTF(dev, NULL) >= 0) ata_dev_get_GTF(dev, NULL) >= 0)
...@@ -904,7 +901,7 @@ void ata_acpi_on_resume(struct ata_port *ap) ...@@ -904,7 +901,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
* there's no reason to evaluate IDE _GTF early * there's no reason to evaluate IDE _GTF early
* without _STM. Clear cache and schedule _GTF. * 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); ata_acpi_clear_gtf(dev);
if (ata_dev_enabled(dev)) if (ata_dev_enabled(dev))
dev->flags |= ATA_DFLAG_ACPI_PENDING; dev->flags |= ATA_DFLAG_ACPI_PENDING;
...@@ -932,8 +929,8 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) ...@@ -932,8 +929,8 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
if (state.event == PM_EVENT_ON) if (state.event == PM_EVENT_ON)
acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
ata_link_for_each_dev(dev, &ap->link) { ata_for_each_dev(dev, &ap->link, ENABLED) {
if (dev->acpi_handle && ata_dev_enabled(dev)) if (dev->acpi_handle)
acpi_bus_set_power(dev->acpi_handle, acpi_bus_set_power(dev->acpi_handle,
state.event == PM_EVENT_ON ? state.event == PM_EVENT_ON ?
ACPI_STATE_D0 : ACPI_STATE_D3); ACPI_STATE_D0 : ACPI_STATE_D3);
......
...@@ -163,42 +163,118 @@ MODULE_LICENSE("GPL"); ...@@ -163,42 +163,118 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); 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: * LOCKING:
* Host lock or EH context. * 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 *ata_link_next(struct ata_link *link, struct ata_port *ap,
struct ata_link *link, bool dev_only) 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 */ /* NULL link indicates start of iteration */
if (!link) { if (!link)
if (dev_only && sata_pmp_attached(ap)) switch (mode) {
case ATA_LITER_EDGE:
case ATA_LITER_PMP_FIRST:
if (sata_pmp_attached(ap))
return ap->pmp_link; return ap->pmp_link;
/* fall through */
case ATA_LITER_HOST_FIRST:
return &ap->link; return &ap->link;
} }
/* we just iterated over the host master link, what's next? */ /* we just iterated over the host link, what's next? */
if (link == &ap->link) { if (link == &ap->link)
if (!sata_pmp_attached(ap)) { switch (mode) {
if (unlikely(ap->slave_link) && !dev_only) 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; return ap->slave_link;
/* fall through */
case ATA_LITER_EDGE:
return NULL; return NULL;
} }
return ap->pmp_link;
}
/* slave_link excludes PMP */ /* slave_link excludes PMP */
if (unlikely(link == ap->slave_link)) if (unlikely(link == ap->slave_link))
return NULL; return NULL;
/* iterate to the next PMP link */ /* we were over a PMP link */
if (++link < ap->pmp_link + ap->nr_pmp_links) if (++link < ap->pmp_link + ap->nr_pmp_links)
return link; return link;
if (mode == ATA_LITER_PMP_FIRST)
return &ap->link;
return NULL; 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 * ata_dev_phys_link - find physical link for a device
* @dev: ATA device to look up physical link for * @dev: ATA device to look up physical link for
...@@ -1107,8 +1183,8 @@ static void ata_lpm_enable(struct ata_host *host) ...@@ -1107,8 +1183,8 @@ static void ata_lpm_enable(struct ata_host *host)
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
ap = host->ports[i]; ap = host->ports[i];
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
ata_link_for_each_dev(dev, link) ata_for_each_dev(dev, link, ALL)
ata_dev_disable_pm(dev); ata_dev_disable_pm(dev);
} }
} }
...@@ -2594,11 +2670,11 @@ int ata_bus_probe(struct ata_port *ap) ...@@ -2594,11 +2670,11 @@ int ata_bus_probe(struct ata_port *ap)
ata_port_probe(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; tries[dev->devno] = ATA_PROBE_MAX_TRIES;
retry: 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) /* If we issue an SRST then an ATA drive (not ATAPI)
* may change configuration and be in PIO0 timing. If * may change configuration and be in PIO0 timing. If
* we do a hard reset (or are coming from power on) * we do a hard reset (or are coming from power on)
...@@ -2620,7 +2696,7 @@ int ata_bus_probe(struct ata_port *ap) ...@@ -2620,7 +2696,7 @@ int ata_bus_probe(struct ata_port *ap)
/* reset and determine device classes */ /* reset and determine device classes */
ap->ops->phy_reset(ap); 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) && if (!(ap->flags & ATA_FLAG_DISABLED) &&
dev->class != ATA_DEV_UNKNOWN) dev->class != ATA_DEV_UNKNOWN)
classes[dev->devno] = dev->class; classes[dev->devno] = dev->class;
...@@ -2636,7 +2712,7 @@ int ata_bus_probe(struct ata_port *ap) ...@@ -2636,7 +2712,7 @@ int ata_bus_probe(struct ata_port *ap)
specific sequence bass-ackwards so that PDIAG- is released by specific sequence bass-ackwards so that PDIAG- is released by
the slave device */ 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]) if (tries[dev->devno])
dev->class = classes[dev->devno]; dev->class = classes[dev->devno];
...@@ -2653,24 +2729,19 @@ int ata_bus_probe(struct ata_port *ap) ...@@ -2653,24 +2729,19 @@ int ata_bus_probe(struct ata_port *ap)
if (ap->ops->cable_detect) if (ap->ops->cable_detect)
ap->cbl = ap->ops->cable_detect(ap); ap->cbl = ap->ops->cable_detect(ap);
/* We may have SATA bridge glue hiding here irrespective of the /* We may have SATA bridge glue hiding here irrespective of
reported cable types and sensed types */ * the reported cable types and sensed types. When SATA
ata_link_for_each_dev(dev, &ap->link) { * drives indicate we have a bridge, we don't know which end
if (!ata_dev_enabled(dev)) * of the link the bridge is which is a problem.
continue; */
/* SATA drives indicate we have a bridge. We don't know which ata_for_each_dev(dev, &ap->link, ENABLED)
end of the link the bridge is which is a problem */
if (ata_id_is_sata(dev->id)) if (ata_id_is_sata(dev->id))
ap->cbl = ATA_CBL_SATA; ap->cbl = ATA_CBL_SATA;
}
/* After the identify sequence we can now set up the devices. We do /* 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 */ this in the normal order so that the user doesn't get confused */
ata_link_for_each_dev(dev, &ap->link) { ata_for_each_dev(dev, &ap->link, ENABLED) {
if (!ata_dev_enabled(dev))
continue;
ap->link.eh_context.i.flags |= ATA_EHI_PRINTINFO; ap->link.eh_context.i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev); rc = ata_dev_configure(dev);
ap->link.eh_context.i.flags &= ~ATA_EHI_PRINTINFO; ap->link.eh_context.i.flags &= ~ATA_EHI_PRINTINFO;
...@@ -2683,8 +2754,7 @@ int ata_bus_probe(struct ata_port *ap) ...@@ -2683,8 +2754,7 @@ int ata_bus_probe(struct ata_port *ap)
if (rc) if (rc)
goto fail; goto fail;
ata_link_for_each_dev(dev, &ap->link) ata_for_each_dev(dev, &ap->link, ENABLED)
if (ata_dev_enabled(dev))
return 0; return 0;
/* no device present, disable port */ /* no device present, disable port */
...@@ -3331,13 +3401,10 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) ...@@ -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; int rc = 0, used_dma = 0, found = 0;
/* step 1: calculate xfer_mask */ /* 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 long pio_mask, dma_mask;
unsigned int mode_mask; unsigned int mode_mask;
if (!ata_dev_enabled(dev))
continue;
mode_mask = ATA_DMA_MASK_ATA; mode_mask = ATA_DMA_MASK_ATA;
if (dev->class == ATA_DEV_ATAPI) if (dev->class == ATA_DEV_ATAPI)
mode_mask = ATA_DMA_MASK_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) ...@@ -3366,10 +3433,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
goto out; goto out;
/* step 2: always set host PIO timings */ /* step 2: always set host PIO timings */
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (!ata_dev_enabled(dev))
continue;
if (dev->pio_mode == 0xff) { if (dev->pio_mode == 0xff) {
ata_dev_printk(dev, KERN_WARNING, "no PIO support\n"); ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
rc = -EINVAL; rc = -EINVAL;
...@@ -3383,8 +3447,8 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) ...@@ -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 */ /* step 3: set host DMA timings */
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev)) if (!ata_dma_enabled(dev))
continue; continue;
dev->xfer_mode = dev->dma_mode; 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) ...@@ -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 */ /* step 4: update devices' xfer mode */
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
/* don't update suspended devices' xfer mode */
if (!ata_dev_enabled(dev))
continue;
rc = ata_dev_set_mode(dev); rc = ata_dev_set_mode(dev);
if (rc) if (rc)
goto out; goto out;
...@@ -4263,9 +4323,9 @@ static int cable_is_40wire(struct ata_port *ap) ...@@ -4263,9 +4323,9 @@ static int cable_is_40wire(struct ata_port *ap)
* - if you have a non detect capable drive you don't want it * - if you have a non detect capable drive you don't want it
* to colour the choice * to colour the choice
*/ */
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev) && !ata_is_40wire(dev)) if (!ata_is_40wire(dev))
return 0; return 0;
} }
} }
...@@ -5218,7 +5278,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, ...@@ -5218,7 +5278,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg,
} }
ap->pflags |= ATA_PFLAG_PM_PENDING; 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.action |= action;
link->eh_info.flags |= ehi_flags; link->eh_info.flags |= ehi_flags;
} }
...@@ -6063,9 +6123,9 @@ static void ata_port_detach(struct ata_port *ap) ...@@ -6063,9 +6123,9 @@ static void ata_port_detach(struct ata_port *ap)
/* EH is now guaranteed to see UNLOADING - EH context belongs /* EH is now guaranteed to see UNLOADING - EH context belongs
* to us. Restore SControl and disable all existing devices. * to us. Restore SControl and disable all existing devices.
*/ */
__ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, HOST_FIRST) {
sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
ata_link_for_each_dev(dev, link) ata_for_each_dev(dev, link, ALL)
ata_dev_disable(dev); ata_dev_disable(dev);
} }
...@@ -6528,7 +6588,8 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops); ...@@ -6528,7 +6588,8 @@ EXPORT_SYMBOL_GPL(ata_base_port_ops);
EXPORT_SYMBOL_GPL(sata_port_ops); EXPORT_SYMBOL_GPL(sata_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_ops); EXPORT_SYMBOL_GPL(ata_dummy_port_ops);
EXPORT_SYMBOL_GPL(ata_dummy_port_info); 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_std_bios_param);
EXPORT_SYMBOL_GPL(ata_host_init); EXPORT_SYMBOL_GPL(ata_host_init);
EXPORT_SYMBOL_GPL(ata_host_alloc); EXPORT_SYMBOL_GPL(ata_host_alloc);
......
This diff is collapsed.
...@@ -321,7 +321,7 @@ static void sata_pmp_quirks(struct ata_port *ap) ...@@ -321,7 +321,7 @@ static void sata_pmp_quirks(struct ata_port *ap)
if (vendor == 0x1095 && devid == 0x3726) { if (vendor == 0x1095 && devid == 0x3726) {
/* sil3726 quirks */ /* sil3726 quirks */
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
/* Class code report is unreliable and SRST /* Class code report is unreliable and SRST
* times out under certain configurations. * times out under certain configurations.
*/ */
...@@ -336,7 +336,7 @@ static void sata_pmp_quirks(struct ata_port *ap) ...@@ -336,7 +336,7 @@ static void sata_pmp_quirks(struct ata_port *ap)
} }
} else if (vendor == 0x1095 && devid == 0x4723) { } else if (vendor == 0x1095 && devid == 0x4723) {
/* sil4723 quirks */ /* sil4723 quirks */
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
/* class code report is unreliable */ /* class code report is unreliable */
if (link->pmp < 2) if (link->pmp < 2)
link->flags |= ATA_LFLAG_ASSUME_ATA; link->flags |= ATA_LFLAG_ASSUME_ATA;
...@@ -348,7 +348,7 @@ static void sata_pmp_quirks(struct ata_port *ap) ...@@ -348,7 +348,7 @@ static void sata_pmp_quirks(struct ata_port *ap)
} }
} else if (vendor == 0x1095 && devid == 0x4726) { } else if (vendor == 0x1095 && devid == 0x4726) {
/* sil4726 quirks */ /* sil4726 quirks */
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
/* Class code report is unreliable and SRST /* Class code report is unreliable and SRST
* times out under certain configurations. * times out under certain configurations.
* Config device can be at port 0 or 5 and * Config device can be at port 0 or 5 and
...@@ -450,7 +450,7 @@ int sata_pmp_attach(struct ata_device *dev) ...@@ -450,7 +450,7 @@ int sata_pmp_attach(struct ata_device *dev)
if (ap->ops->pmp_attach) if (ap->ops->pmp_attach)
ap->ops->pmp_attach(ap); ap->ops->pmp_attach(ap);
ata_port_for_each_link(tlink, ap) ata_for_each_link(tlink, ap, EDGE)
sata_link_init_spd(tlink); sata_link_init_spd(tlink);
ata_acpi_associate_sata_port(ap); ata_acpi_associate_sata_port(ap);
...@@ -487,7 +487,7 @@ static void sata_pmp_detach(struct ata_device *dev) ...@@ -487,7 +487,7 @@ static void sata_pmp_detach(struct ata_device *dev)
if (ap->ops->pmp_detach) if (ap->ops->pmp_detach)
ap->ops->pmp_detach(ap); 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); ata_eh_detach_dev(tlink->device);
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
...@@ -700,7 +700,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, ...@@ -700,7 +700,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
} }
/* PMP is reset, SErrors cannot be trusted, scan all */ /* 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; struct ata_eh_context *ehc = &tlink->eh_context;
ehc->i.probe_mask |= ATA_ALL_DEVICES; ehc->i.probe_mask |= ATA_ALL_DEVICES;
...@@ -768,7 +768,7 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) ...@@ -768,7 +768,7 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
spin_lock_irqsave(ap->lock, flags); 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)) if (!(link->flags & ATA_LFLAG_DISABLED))
continue; continue;
...@@ -852,7 +852,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) ...@@ -852,7 +852,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
int cnt, rc; int cnt, rc;
pmp_tries = ATA_EH_PMP_TRIES; 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; link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES;
retry: retry:
...@@ -861,7 +861,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) ...@@ -861,7 +861,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
rc = ata_eh_recover(ap, ops->prereset, ops->softreset, rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
ops->hardreset, ops->postreset, NULL); ops->hardreset, ops->postreset, NULL);
if (rc) { if (rc) {
ata_link_for_each_dev(dev, &ap->link) ata_for_each_dev(dev, &ap->link, ALL)
ata_dev_disable(dev); ata_dev_disable(dev);
return rc; return rc;
} }
...@@ -870,7 +870,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) ...@@ -870,7 +870,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
return 0; return 0;
/* new PMP online */ /* 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; link_tries[link->pmp] = ATA_EH_PMP_LINK_TRIES;
/* fall through */ /* fall through */
...@@ -942,7 +942,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap) ...@@ -942,7 +942,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
} }
cnt = 0; cnt = 0;
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
if (!(gscr_error & (1 << link->pmp))) if (!(gscr_error & (1 << link->pmp)))
continue; continue;
......
...@@ -3229,12 +3229,12 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) ...@@ -3229,12 +3229,12 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
return; return;
repeat: repeat:
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
struct scsi_device *sdev; struct scsi_device *sdev;
int channel = 0, id = 0; int channel = 0, id = 0;
if (!ata_dev_enabled(dev) || dev->sdev) if (dev->sdev)
continue; continue;
if (ata_is_host_link(link)) if (ata_is_host_link(link))
...@@ -3255,9 +3255,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync) ...@@ -3255,9 +3255,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
* failure occurred, scan would have failed silently. Check * failure occurred, scan would have failed silently. Check
* whether all devices are attached. * whether all devices are attached.
*/ */
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev) && !dev->sdev) if (!dev->sdev)
goto exit_loop; goto exit_loop;
} }
} }
...@@ -3381,7 +3381,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link) ...@@ -3381,7 +3381,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
struct ata_port *ap = link->ap; struct ata_port *ap = link->ap;
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ALL) {
unsigned long flags; unsigned long flags;
if (!(dev->flags & ATA_DFLAG_DETACHED)) if (!(dev->flags & ATA_DFLAG_DETACHED))
...@@ -3496,7 +3496,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, ...@@ -3496,7 +3496,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
if (devno == SCAN_WILD_CARD) { if (devno == SCAN_WILD_CARD) {
struct ata_link *link; 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; struct ata_eh_info *ehi = &link->eh_info;
ehi->probe_mask |= ATA_ALL_DEVICES; ehi->probe_mask |= ATA_ALL_DEVICES;
ehi->action |= ATA_EH_RESET; ehi->action |= ATA_EH_RESET;
...@@ -3544,11 +3544,11 @@ void ata_scsi_dev_rescan(struct work_struct *work) ...@@ -3544,11 +3544,11 @@ void ata_scsi_dev_rescan(struct work_struct *work)
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
ata_port_for_each_link(link, ap) { ata_for_each_link(link, ap, EDGE) {
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
struct scsi_device *sdev = dev->sdev; struct scsi_device *sdev = dev->sdev;
if (!ata_dev_enabled(dev) || !sdev) if (!sdev)
continue; continue;
if (scsi_device_get(sdev)) if (scsi_device_get(sdev))
continue; continue;
......
...@@ -465,8 +465,7 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus ...@@ -465,8 +465,7 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
{ {
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->dma_mode = XFER_MW_DMA_0; dev->dma_mode = XFER_MW_DMA_0;
...@@ -484,7 +483,6 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus ...@@ -484,7 +483,6 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
dev->flags |= ATA_DFLAG_PIO; dev->flags |= ATA_DFLAG_PIO;
} }
} }
}
return 0; return 0;
} }
......
...@@ -30,15 +30,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) ...@@ -30,15 +30,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
{ {
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) {
ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n");
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO; dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO; dev->flags |= ATA_DFLAG_PIO;
} }
}
return 0; return 0;
} }
......
...@@ -194,16 +194,13 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused) ...@@ -194,16 +194,13 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) { ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
ata_dev_printk(dev, KERN_INFO,
"configured for PIO\n");
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO; dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO; dev->flags |= ATA_DFLAG_PIO;
} }
}
return 0; return 0;
} }
...@@ -1028,7 +1025,7 @@ static __init int legacy_init_one(struct legacy_probe *probe) ...@@ -1028,7 +1025,7 @@ static __init int legacy_init_one(struct legacy_probe *probe)
/* Nothing found means we drop the port as its probably not there */ /* Nothing found means we drop the port as its probably not there */
ret = -ENODEV; ret = -ENODEV;
ata_link_for_each_dev(dev, &ap->link) { ata_for_each_dev(dev, &ap->link, ALL) {
if (!ata_dev_absent(dev)) { if (!ata_dev_absent(dev)) {
legacy_host[probe->slot] = host; legacy_host[probe->slot] = host;
ld->platform_dev = pdev; ld->platform_dev = pdev;
......
...@@ -406,9 +406,7 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed ...@@ -406,9 +406,7 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed
if (rc < 0) if (rc < 0)
return rc; return rc;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) {
pdc2027x_set_piomode(ap, dev); pdc2027x_set_piomode(ap, dev);
/* /*
...@@ -424,7 +422,6 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed ...@@ -424,7 +422,6 @@ static int pdc2027x_set_mode(struct ata_link *link, struct ata_device **r_failed
pdc2027x_set_dmamode(ap, dev); pdc2027x_set_dmamode(ap, dev);
} }
} }
}
return 0; return 0;
} }
......
...@@ -34,15 +34,13 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu ...@@ -34,15 +34,13 @@ static int pata_platform_set_mode(struct ata_link *link, struct ata_device **unu
{ {
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = dev->xfer_mode = XFER_PIO_0; dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
dev->xfer_shift = ATA_SHIFT_PIO; dev->xfer_shift = ATA_SHIFT_PIO;
dev->flags |= ATA_DFLAG_PIO; dev->flags |= ATA_DFLAG_PIO;
ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
} }
}
return 0; return 0;
} }
......
...@@ -38,8 +38,7 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused) ...@@ -38,8 +38,7 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
{ {
struct ata_device *dev; struct ata_device *dev;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ENABLED) {
if (ata_dev_enabled(dev)) {
/* We don't really care */ /* We don't really care */
dev->pio_mode = XFER_PIO_0; dev->pio_mode = XFER_PIO_0;
dev->xfer_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0;
...@@ -47,7 +46,6 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused) ...@@ -47,7 +46,6 @@ static int rz1000_set_mode(struct ata_link *link, struct ata_device **unused)
dev->flags |= ATA_DFLAG_PIO; dev->flags |= ATA_DFLAG_PIO;
ata_dev_printk(dev, KERN_INFO, "configured for PIO\n"); ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
} }
}
return 0; return 0;
} }
......
...@@ -278,7 +278,7 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) ...@@ -278,7 +278,7 @@ static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed)
if (rc) if (rc)
return rc; return rc;
ata_link_for_each_dev(dev, link) { ata_for_each_dev(dev, link, ALL) {
if (!ata_dev_enabled(dev)) if (!ata_dev_enabled(dev))
dev_mode[dev->devno] = 0; /* PIO0/1/2 */ dev_mode[dev->devno] = 0; /* PIO0/1/2 */
else if (dev->flags & ATA_DFLAG_PIO) else if (dev->flags & ATA_DFLAG_PIO)
......
...@@ -1285,26 +1285,62 @@ static inline int ata_link_active(struct ata_link *link) ...@@ -1285,26 +1285,62 @@ static inline int ata_link_active(struct ata_link *link)
return ata_tag_valid(link->active_tag) || link->sactive; 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, * Iterators
bool dev_only); *
* 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) \ enum ata_dev_iter_mode {
for ((link) = __ata_port_next_link((ap), NULL, false); (link); \ ATA_DITER_ENABLED,
(link) = __ata_port_next_link((ap), (link), false)) ATA_DITER_ENABLED_REVERSE,
ATA_DITER_ALL,
ATA_DITER_ALL_REVERSE,
};
#define ata_port_for_each_link(link, ap) \ extern struct ata_link *ata_link_next(struct ata_link *link,
for ((link) = __ata_port_next_link((ap), NULL, true); (link); \ struct ata_port *ap,
(link) = __ata_port_next_link((ap), (link), true)) enum ata_link_iter_mode mode);
#define ata_link_for_each_dev(dev, link) \ extern struct ata_device *ata_dev_next(struct ata_device *dev,
for ((dev) = (link)->device; \ struct ata_link *link,
(dev) < (link)->device + ata_link_max_devices(link) || ((dev) = NULL); \ enum ata_dev_iter_mode mode);
(dev)++)
/*
* 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) \ #define ata_for_each_dev(dev, link, mode) \
for ((dev) = (link)->device + ata_link_max_devices(link) - 1; \ for ((dev) = ata_dev_next(NULL, (link), ATA_DITER_##mode); (dev); \
(dev) >= (link)->device || ((dev) = NULL); (dev)--) (dev) = ata_dev_next((dev), (link), ATA_DITER_##mode))
/** /**
* ata_ncq_enabled - Test whether NCQ is enabled * ata_ncq_enabled - Test whether NCQ is enabled
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment