From: Alan Cox Signed-off-by: Alan Cox Signed-off-by: Andrew Morton --- drivers/ata/libata-core.c | 48 +++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff -puN drivers/ata/libata-core.c~libata-isolate-and-rework-cable-logic drivers/ata/libata-core.c --- a/drivers/ata/libata-core.c~libata-isolate-and-rework-cable-logic +++ a/drivers/ata/libata-core.c @@ -4274,6 +4274,49 @@ static int ata_is_40wire(struct ata_devi } /** + * 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 * @@ -4341,10 +4384,7 @@ static void ata_dev_xfermask(struct ata_ */ 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); _