libata: isolate and rework cable logic
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 28 Mar 2008 21:33:46 +0000 (14:33 -0700)
committerJeff Garzik <jgarzik@redhat.com>
Thu, 17 Apr 2008 19:44:19 +0000 (15:44 -0400)
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>
drivers/ata/libata-core.c

index 54f8550..9121cc4 100644 (file)
@@ -3885,6 +3885,49 @@ static int ata_is_40wire(struct ata_device *dev)
        return ata_drive_40wire(dev->id);
 }
 
+/**
+ *     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);