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 | ||
