summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-03-28 14:33:46 -0700
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:19 -0400
commit15a5551c847c8787d6cd75b8cf7682cd6d642e1b (patch)
tree8a48f734a41b4856448d4c715d572fb6057b68cc /drivers/ata/libata-core.c
parentd21279f4125893c63ec285962e1f2164b4d71117 (diff)
libata: isolate and rework cable logic
Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 54f85508bc6..9121cc443be 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3886,6 +3886,49 @@ static int ata_is_40wire(struct ata_device *dev)
}
/**
+ * cable_is_40wire - 40/80/SATA decider
+ * @ap: port to consider
+ *
+ * This function encapsulates the policy for speed management
+ * in one place. At the moment we don't cache the result but
+ * there is a good case for setting ap->cbl to the result when
+ * we are called with unknown cables (and figuring out if it
+ * impacts hotplug at all).
+ *
+ * Return 1 if the cable appears to be 40 wire.
+ */
+
+static int cable_is_40wire(struct ata_port *ap)
+{
+ struct ata_link *link;
+ struct ata_device *dev;
+
+ /* If the controller thinks we are 40 wire, we are */
+ if (ap->cbl == ATA_CBL_PATA40)
+ return 1;
+ /* If the controller thinks we are 80 wire, we are */
+ if (ap->cbl == ATA_CBL_PATA80 || ap->cbl == ATA_CBL_SATA)
+ return 0;
+ /* If the controller doesn't know we scan
+
+ - Note: We look for all 40 wire detects at this point.
+ Any 80 wire detect is taken to be 80 wire cable
+ because
+ - In many setups only the one drive (slave if present)
+ will give a valid detect
+ - 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_is_40wire(dev))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/**
* ata_dev_xfermask - Compute supported xfermask of the given device
* @dev: Device to compute xfermask for
*
@@ -3953,10 +3996,7 @@ static void ata_dev_xfermask(struct ata_device *dev)
*/
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
/* UDMA/44 or higher would be available */
- if ((ap->cbl == ATA_CBL_PATA40) ||
- (ata_is_40wire(dev) &&
- (ap->cbl == ATA_CBL_PATA_UNK ||
- ap->cbl == ATA_CBL_PATA80))) {
+ if (cable_is_40wire(ap)) {
ata_dev_printk(dev, KERN_WARNING,
"limited to UDMA/33 due to 40-wire cable\n");
xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);