diff options
-rw-r--r-- | drivers/scsi/libata-core.c | 143 | ||||
-rw-r--r-- | include/linux/libata.h | 1 |
2 files changed, 140 insertions, 4 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 3acf56200d87..63488673765f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -65,6 +65,7 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, | |||
65 | struct ata_device *dev, | 65 | struct ata_device *dev, |
66 | u16 heads, | 66 | u16 heads, |
67 | u16 sectors); | 67 | u16 sectors); |
68 | static int ata_down_sata_spd_limit(struct ata_port *ap); | ||
68 | static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); | 69 | static int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); |
69 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, | 70 | static unsigned int ata_dev_set_xfermode(struct ata_port *ap, |
70 | struct ata_device *dev); | 71 | struct ata_device *dev); |
@@ -1596,6 +1597,120 @@ void ata_port_disable(struct ata_port *ap) | |||
1596 | ap->flags |= ATA_FLAG_PORT_DISABLED; | 1597 | ap->flags |= ATA_FLAG_PORT_DISABLED; |
1597 | } | 1598 | } |
1598 | 1599 | ||
1600 | /** | ||
1601 | * ata_down_sata_spd_limit - adjust SATA spd limit downward | ||
1602 | * @ap: Port to adjust SATA spd limit for | ||
1603 | * | ||
1604 | * Adjust SATA spd limit of @ap downward. Note that this | ||
1605 | * function only adjusts the limit. The change must be applied | ||
1606 | * using ata_set_sata_spd(). | ||
1607 | * | ||
1608 | * LOCKING: | ||
1609 | * Inherited from caller. | ||
1610 | * | ||
1611 | * RETURNS: | ||
1612 | * 0 on success, negative errno on failure | ||
1613 | */ | ||
1614 | static int ata_down_sata_spd_limit(struct ata_port *ap) | ||
1615 | { | ||
1616 | u32 spd, mask; | ||
1617 | int highbit; | ||
1618 | |||
1619 | if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) | ||
1620 | return -EOPNOTSUPP; | ||
1621 | |||
1622 | mask = ap->sata_spd_limit; | ||
1623 | if (mask <= 1) | ||
1624 | return -EINVAL; | ||
1625 | highbit = fls(mask) - 1; | ||
1626 | mask &= ~(1 << highbit); | ||
1627 | |||
1628 | spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf; | ||
1629 | if (spd <= 1) | ||
1630 | return -EINVAL; | ||
1631 | spd--; | ||
1632 | mask &= (1 << spd) - 1; | ||
1633 | if (!mask) | ||
1634 | return -EINVAL; | ||
1635 | |||
1636 | ap->sata_spd_limit = mask; | ||
1637 | |||
1638 | printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n", | ||
1639 | ap->id, sata_spd_string(fls(mask))); | ||
1640 | |||
1641 | return 0; | ||
1642 | } | ||
1643 | |||
1644 | static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol) | ||
1645 | { | ||
1646 | u32 spd, limit; | ||
1647 | |||
1648 | if (ap->sata_spd_limit == UINT_MAX) | ||
1649 | limit = 0; | ||
1650 | else | ||
1651 | limit = fls(ap->sata_spd_limit); | ||
1652 | |||
1653 | spd = (*scontrol >> 4) & 0xf; | ||
1654 | *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4); | ||
1655 | |||
1656 | return spd != limit; | ||
1657 | } | ||
1658 | |||
1659 | /** | ||
1660 | * ata_set_sata_spd_needed - is SATA spd configuration needed | ||
1661 | * @ap: Port in question | ||
1662 | * | ||
1663 | * Test whether the spd limit in SControl matches | ||
1664 | * @ap->sata_spd_limit. This function is used to determine | ||
1665 | * whether hardreset is necessary to apply SATA spd | ||
1666 | * configuration. | ||
1667 | * | ||
1668 | * LOCKING: | ||
1669 | * Inherited from caller. | ||
1670 | * | ||
1671 | * RETURNS: | ||
1672 | * 1 if SATA spd configuration is needed, 0 otherwise. | ||
1673 | */ | ||
1674 | static int ata_set_sata_spd_needed(struct ata_port *ap) | ||
1675 | { | ||
1676 | u32 scontrol; | ||
1677 | |||
1678 | if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) | ||
1679 | return 0; | ||
1680 | |||
1681 | scontrol = scr_read(ap, SCR_CONTROL); | ||
1682 | |||
1683 | return __ata_set_sata_spd_needed(ap, &scontrol); | ||
1684 | } | ||
1685 | |||
1686 | /** | ||
1687 | * ata_set_sata_spd - set SATA spd according to spd limit | ||
1688 | * @ap: Port to set SATA spd for | ||
1689 | * | ||
1690 | * Set SATA spd of @ap according to sata_spd_limit. | ||
1691 | * | ||
1692 | * LOCKING: | ||
1693 | * Inherited from caller. | ||
1694 | * | ||
1695 | * RETURNS: | ||
1696 | * 0 if spd doesn't need to be changed, 1 if spd has been | ||
1697 | * changed. -EOPNOTSUPP if SCR registers are inaccessible. | ||
1698 | */ | ||
1699 | static int ata_set_sata_spd(struct ata_port *ap) | ||
1700 | { | ||
1701 | u32 scontrol; | ||
1702 | |||
1703 | if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read) | ||
1704 | return -EOPNOTSUPP; | ||
1705 | |||
1706 | scontrol = scr_read(ap, SCR_CONTROL); | ||
1707 | if (!__ata_set_sata_spd_needed(ap, &scontrol)) | ||
1708 | return 0; | ||
1709 | |||
1710 | scr_write(ap, SCR_CONTROL, scontrol); | ||
1711 | return 1; | ||
1712 | } | ||
1713 | |||
1599 | /* | 1714 | /* |
1600 | * This mode timing computation functionality is ported over from | 1715 | * This mode timing computation functionality is ported over from |
1601 | * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik | 1716 | * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik |
@@ -2165,7 +2280,14 @@ static int sata_phy_resume(struct ata_port *ap) | |||
2165 | void ata_std_probeinit(struct ata_port *ap) | 2280 | void ata_std_probeinit(struct ata_port *ap) |
2166 | { | 2281 | { |
2167 | if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { | 2282 | if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { |
2283 | u32 spd; | ||
2284 | |||
2168 | sata_phy_resume(ap); | 2285 | sata_phy_resume(ap); |
2286 | |||
2287 | spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; | ||
2288 | if (spd) | ||
2289 | ap->sata_spd_limit &= (1 << spd) - 1; | ||
2290 | |||
2169 | if (sata_dev_present(ap)) | 2291 | if (sata_dev_present(ap)) |
2170 | ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); | 2292 | ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); |
2171 | } | 2293 | } |
@@ -2253,18 +2375,30 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) | |||
2253 | 2375 | ||
2254 | DPRINTK("ENTER\n"); | 2376 | DPRINTK("ENTER\n"); |
2255 | 2377 | ||
2256 | /* Issue phy wake/reset */ | 2378 | if (ata_set_sata_spd_needed(ap)) { |
2379 | /* SATA spec says nothing about how to reconfigure | ||
2380 | * spd. To be on the safe side, turn off phy during | ||
2381 | * reconfiguration. This works for at least ICH7 AHCI | ||
2382 | * and Sil3124. | ||
2383 | */ | ||
2384 | scontrol = scr_read(ap, SCR_CONTROL); | ||
2385 | scontrol = (scontrol & 0x0f0) | 0x302; | ||
2386 | scr_write_flush(ap, SCR_CONTROL, scontrol); | ||
2387 | |||
2388 | ata_set_sata_spd(ap); | ||
2389 | } | ||
2390 | |||
2391 | /* issue phy wake/reset */ | ||
2257 | scontrol = scr_read(ap, SCR_CONTROL); | 2392 | scontrol = scr_read(ap, SCR_CONTROL); |
2258 | scontrol = (scontrol & 0x0f0) | 0x301; | 2393 | scontrol = (scontrol & 0x0f0) | 0x301; |
2259 | scr_write_flush(ap, SCR_CONTROL, scontrol); | 2394 | scr_write_flush(ap, SCR_CONTROL, scontrol); |
2260 | 2395 | ||
2261 | /* | 2396 | /* Couldn't find anything in SATA I/II specs, but AHCI-1.1 |
2262 | * Couldn't find anything in SATA I/II specs, but AHCI-1.1 | ||
2263 | * 10.4.2 says at least 1 ms. | 2397 | * 10.4.2 says at least 1 ms. |
2264 | */ | 2398 | */ |
2265 | msleep(1); | 2399 | msleep(1); |
2266 | 2400 | ||
2267 | /* Bring phy back */ | 2401 | /* bring phy back */ |
2268 | sata_phy_resume(ap); | 2402 | sata_phy_resume(ap); |
2269 | 2403 | ||
2270 | /* TODO: phy layer with polling, timeouts, etc. */ | 2404 | /* TODO: phy layer with polling, timeouts, etc. */ |
@@ -4454,6 +4588,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, | |||
4454 | ap->flags |= ent->host_flags; | 4588 | ap->flags |= ent->host_flags; |
4455 | ap->ops = ent->port_ops; | 4589 | ap->ops = ent->port_ops; |
4456 | ap->cbl = ATA_CBL_NONE; | 4590 | ap->cbl = ATA_CBL_NONE; |
4591 | ap->sata_spd_limit = UINT_MAX; | ||
4457 | ap->active_tag = ATA_TAG_POISON; | 4592 | ap->active_tag = ATA_TAG_POISON; |
4458 | ap->last_ctl = 0xFF; | 4593 | ap->last_ctl = 0xFF; |
4459 | 4594 | ||
diff --git a/include/linux/libata.h b/include/linux/libata.h index 0f8e3720edd9..a5207e66ca52 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -397,6 +397,7 @@ struct ata_port { | |||
397 | unsigned int mwdma_mask; | 397 | unsigned int mwdma_mask; |
398 | unsigned int udma_mask; | 398 | unsigned int udma_mask; |
399 | unsigned int cbl; /* cable type; ATA_CBL_xxx */ | 399 | unsigned int cbl; /* cable type; ATA_CBL_xxx */ |
400 | unsigned int sata_spd_limit; /* SATA PHY speed limit */ | ||
400 | 401 | ||
401 | struct ata_device device[ATA_MAX_DEVICES]; | 402 | struct ata_device device[ATA_MAX_DEVICES]; |
402 | 403 | ||