--- /dev/null
+From aadffb682cc5572f48cc24883681db65530bd284 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Thu, 31 Jul 2008 17:02:41 +0900
+Subject: [PATCH] libata: reimplement link iterator
+References: bnc#441420
+
+Implement __ata_port_next_link() and reimplement
+__ata_port_for_each_link() and ata_port_for_each_link() using it.
+This removes relatively large inlined code and makes iteration easier
+to extend.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Signed-off-by: Tejun Heo <teheo@suse.de>
+---
+ drivers/ata/libata-core.c | 30 ++++++++++++++++++++++++++++++
+ include/linux/libata.h | 35 +++++++++--------------------------
+ 2 files changed, 39 insertions(+), 26 deletions(-)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -163,6 +163,35 @@ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
+
+
++/*
++ * Iterator helpers. Don't use directly.
++ *
++ * LOCKING:
++ * Host lock or EH context.
++ */
++struct ata_link *__ata_port_next_link(struct ata_port *ap,
++ struct ata_link *link, bool dev_only)
++{
++ /* NULL link indicates start of iteration */
++ if (!link) {
++ if (dev_only && sata_pmp_attached(ap))
++ return ap->pmp_link;
++ return &ap->link;
++ }
++
++ /* we just iterated over the host link, what's next? */
++ if (ata_is_host_link(link)) {
++ if (!sata_pmp_attached(ap))
++ return NULL;
++ return ap->pmp_link;
++ }
++
++ /* iterate to the next PMP link */
++ if (++link < ap->pmp_link + ap->nr_pmp_links)
++ return link;
++ return NULL;
++}
++
+ /**
+ * ata_force_cbl - force cable type according to libata.force
+ * @ap: ATA port of interest
+@@ -6333,6 +6362,7 @@ 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_std_bios_param);
+ EXPORT_SYMBOL_GPL(ata_host_init);
+ EXPORT_SYMBOL_GPL(ata_host_alloc);
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -1266,34 +1266,17 @@ static inline int ata_link_active(struct
+ return ata_tag_valid(link->active_tag) || link->sactive;
+ }
+
+-static inline struct ata_link *ata_port_first_link(struct ata_port *ap)
+-{
+- if (sata_pmp_attached(ap))
+- return ap->pmp_link;
+- return &ap->link;
+-}
+-
+-static inline struct ata_link *ata_port_next_link(struct ata_link *link)
+-{
+- struct ata_port *ap = link->ap;
+-
+- if (ata_is_host_link(link)) {
+- if (!sata_pmp_attached(ap))
+- return NULL;
+- return ap->pmp_link;
+- }
+-
+- if (++link < ap->nr_pmp_links + ap->pmp_link)
+- return link;
+- return NULL;
+-}
+-
+-#define __ata_port_for_each_link(lk, ap) \
+- for ((lk) = &(ap)->link; (lk); (lk) = ata_port_next_link(lk))
++extern struct ata_link *__ata_port_next_link(struct ata_port *ap,
++ struct ata_link *link,
++ bool dev_only);
++
++#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))
+
+ #define ata_port_for_each_link(link, ap) \
+- for ((link) = ata_port_first_link(ap); (link); \
+- (link) = ata_port_next_link(link))
++ for ((link) = __ata_port_next_link((ap), NULL, true); (link); \
++ (link) = __ata_port_next_link((ap), (link), true))
+
+ #define ata_link_for_each_dev(dev, link) \
+ for ((dev) = (link)->device; \