[PATCH] libata: use new SCR and on/offline functions
Use new SCR and on/offline functions. Note that for LLDD which know it implements SCR callbacks, SCR functions are guaranteed to succeed and ata_port_online() == !ata_port_offline(). Signed-off-by: Tejun Heo <htejun@gmail.com>
This commit is contained in:
Родитель
34bf21704c
Коммит
81952c5497
|
@ -567,7 +567,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
if (!sata_dev_present(ap)) {
|
if (ata_port_offline(ap)) {
|
||||||
DPRINTK("PHY reports no device\n");
|
DPRINTK("PHY reports no device\n");
|
||||||
*class = ATA_DEV_NONE;
|
*class = ATA_DEV_NONE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -640,7 +640,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
|
||||||
msleep(150);
|
msleep(150);
|
||||||
|
|
||||||
*class = ATA_DEV_NONE;
|
*class = ATA_DEV_NONE;
|
||||||
if (sata_dev_present(ap)) {
|
if (ata_port_online(ap)) {
|
||||||
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
|
if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
reason = "device not ready";
|
reason = "device not ready";
|
||||||
|
@ -670,7 +670,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
rc = sata_std_hardreset(ap, class);
|
rc = sata_std_hardreset(ap, class);
|
||||||
ahci_start_engine(ap);
|
ahci_start_engine(ap);
|
||||||
|
|
||||||
if (rc == 0 && sata_dev_present(ap))
|
if (rc == 0 && ata_port_online(ap))
|
||||||
*class = ahci_dev_classify(ap);
|
*class = ahci_dev_classify(ap);
|
||||||
if (*class == ATA_DEV_UNKNOWN)
|
if (*class == ATA_DEV_UNKNOWN)
|
||||||
*class = ATA_DEV_NONE;
|
*class = ATA_DEV_NONE;
|
||||||
|
|
|
@ -1494,13 +1494,11 @@ static void sata_print_link_status(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u32 sstatus, scontrol, tmp;
|
u32 sstatus, scontrol, tmp;
|
||||||
|
|
||||||
if (!ap->ops->scr_read)
|
if (sata_scr_read(ap, SCR_STATUS, &sstatus))
|
||||||
return;
|
return;
|
||||||
|
sata_scr_read(ap, SCR_CONTROL, &scontrol);
|
||||||
|
|
||||||
sstatus = scr_read(ap, SCR_STATUS);
|
if (ata_port_online(ap)) {
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
|
||||||
|
|
||||||
if (sata_dev_present(ap)) {
|
|
||||||
tmp = (sstatus >> 4) & 0xf;
|
tmp = (sstatus >> 4) & 0xf;
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"ata%u: SATA link up %s (SStatus %X SControl %X)\n",
|
"ata%u: SATA link up %s (SStatus %X SControl %X)\n",
|
||||||
|
@ -1531,17 +1529,18 @@ void __sata_phy_reset(struct ata_port *ap)
|
||||||
|
|
||||||
if (ap->flags & ATA_FLAG_SATA_RESET) {
|
if (ap->flags & ATA_FLAG_SATA_RESET) {
|
||||||
/* issue phy wake/reset */
|
/* issue phy wake/reset */
|
||||||
scr_write_flush(ap, SCR_CONTROL, 0x301);
|
sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
|
||||||
/* Couldn't find anything in SATA I/II specs, but
|
/* Couldn't find anything in SATA I/II specs, but
|
||||||
* AHCI-1.1 10.4.2 says at least 1 ms. */
|
* AHCI-1.1 10.4.2 says at least 1 ms. */
|
||||||
mdelay(1);
|
mdelay(1);
|
||||||
}
|
}
|
||||||
scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
|
/* phy wake/clear reset */
|
||||||
|
sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
|
||||||
|
|
||||||
/* wait for phy to become ready, if necessary */
|
/* wait for phy to become ready, if necessary */
|
||||||
do {
|
do {
|
||||||
msleep(200);
|
msleep(200);
|
||||||
sstatus = scr_read(ap, SCR_STATUS);
|
sata_scr_read(ap, SCR_STATUS, &sstatus);
|
||||||
if ((sstatus & 0xf) != 1)
|
if ((sstatus & 0xf) != 1)
|
||||||
break;
|
break;
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
@ -1550,7 +1549,7 @@ void __sata_phy_reset(struct ata_port *ap)
|
||||||
sata_print_link_status(ap);
|
sata_print_link_status(ap);
|
||||||
|
|
||||||
/* TODO: phy layer with polling, timeouts, etc. */
|
/* TODO: phy layer with polling, timeouts, etc. */
|
||||||
if (sata_dev_present(ap))
|
if (!ata_port_offline(ap))
|
||||||
ata_port_probe(ap);
|
ata_port_probe(ap);
|
||||||
else
|
else
|
||||||
ata_port_disable(ap);
|
ata_port_disable(ap);
|
||||||
|
@ -1638,11 +1637,12 @@ void ata_port_disable(struct ata_port *ap)
|
||||||
*/
|
*/
|
||||||
int sata_down_spd_limit(struct ata_port *ap)
|
int sata_down_spd_limit(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u32 spd, mask;
|
u32 sstatus, spd, mask;
|
||||||
int highbit;
|
int rc, highbit;
|
||||||
|
|
||||||
if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
|
rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
|
||||||
return -EOPNOTSUPP;
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
mask = ap->sata_spd_limit;
|
mask = ap->sata_spd_limit;
|
||||||
if (mask <= 1)
|
if (mask <= 1)
|
||||||
|
@ -1650,7 +1650,7 @@ int sata_down_spd_limit(struct ata_port *ap)
|
||||||
highbit = fls(mask) - 1;
|
highbit = fls(mask) - 1;
|
||||||
mask &= ~(1 << highbit);
|
mask &= ~(1 << highbit);
|
||||||
|
|
||||||
spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf;
|
spd = (sstatus >> 4) & 0xf;
|
||||||
if (spd <= 1)
|
if (spd <= 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
spd--;
|
spd--;
|
||||||
|
@ -1700,11 +1700,9 @@ int sata_set_spd_needed(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u32 scontrol;
|
u32 scontrol;
|
||||||
|
|
||||||
if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
|
if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
|
||||||
|
|
||||||
return __sata_set_spd_needed(ap, &scontrol);
|
return __sata_set_spd_needed(ap, &scontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1719,20 +1717,22 @@ int sata_set_spd_needed(struct ata_port *ap)
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* 0 if spd doesn't need to be changed, 1 if spd has been
|
* 0 if spd doesn't need to be changed, 1 if spd has been
|
||||||
* changed. -EOPNOTSUPP if SCR registers are inaccessible.
|
* changed. Negative errno if SCR registers are inaccessible.
|
||||||
*/
|
*/
|
||||||
int sata_set_spd(struct ata_port *ap)
|
int sata_set_spd(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u32 scontrol;
|
u32 scontrol;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
|
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||||
return -EOPNOTSUPP;
|
return rc;
|
||||||
|
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
|
||||||
if (!__sata_set_spd_needed(ap, &scontrol))
|
if (!__sata_set_spd_needed(ap, &scontrol))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
scr_write(ap, SCR_CONTROL, scontrol);
|
if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2336,20 +2336,26 @@ static int sata_phy_resume(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
unsigned long timeout = jiffies + (HZ * 5);
|
unsigned long timeout = jiffies + (HZ * 5);
|
||||||
u32 scontrol, sstatus;
|
u32 scontrol, sstatus;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
|
||||||
scontrol = (scontrol & 0x0f0) | 0x300;
|
scontrol = (scontrol & 0x0f0) | 0x300;
|
||||||
scr_write_flush(ap, SCR_CONTROL, scontrol);
|
|
||||||
|
if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* Wait for phy to become ready, if necessary. */
|
/* Wait for phy to become ready, if necessary. */
|
||||||
do {
|
do {
|
||||||
msleep(200);
|
msleep(200);
|
||||||
sstatus = scr_read(ap, SCR_STATUS);
|
if ((rc = sata_scr_read(ap, SCR_STATUS, &sstatus)))
|
||||||
|
return rc;
|
||||||
if ((sstatus & 0xf) != 1)
|
if ((sstatus & 0xf) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
} while (time_before(jiffies, timeout));
|
} while (time_before(jiffies, timeout));
|
||||||
|
|
||||||
return -1;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2367,21 +2373,20 @@ static int sata_phy_resume(struct ata_port *ap)
|
||||||
*/
|
*/
|
||||||
void ata_std_probeinit(struct ata_port *ap)
|
void ata_std_probeinit(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
|
u32 scontrol;
|
||||||
u32 spd;
|
|
||||||
|
|
||||||
/* resume link */
|
/* resume link */
|
||||||
sata_phy_resume(ap);
|
sata_phy_resume(ap);
|
||||||
|
|
||||||
/* init sata_spd_limit to the current value */
|
/* init sata_spd_limit to the current value */
|
||||||
spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4;
|
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
|
||||||
if (spd)
|
int spd = (scontrol >> 4) & 0xf;
|
||||||
ap->sata_spd_limit &= (1 << spd) - 1;
|
ap->sata_spd_limit &= (1 << spd) - 1;
|
||||||
|
|
||||||
/* wait for device */
|
|
||||||
if (sata_dev_present(ap))
|
|
||||||
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait for device */
|
||||||
|
if (ata_port_online(ap))
|
||||||
|
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2406,7 +2411,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
if (ap->ops->scr_read && !sata_dev_present(ap)) {
|
if (ata_port_offline(ap)) {
|
||||||
classes[0] = ATA_DEV_NONE;
|
classes[0] = ATA_DEV_NONE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2457,6 +2462,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
|
||||||
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
{
|
{
|
||||||
u32 scontrol;
|
u32 scontrol;
|
||||||
|
int rc;
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
|
@ -2466,17 +2472,25 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
* reconfiguration. This works for at least ICH7 AHCI
|
* reconfiguration. This works for at least ICH7 AHCI
|
||||||
* and Sil3124.
|
* and Sil3124.
|
||||||
*/
|
*/
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
scontrol = (scontrol & 0x0f0) | 0x302;
|
scontrol = (scontrol & 0x0f0) | 0x302;
|
||||||
scr_write_flush(ap, SCR_CONTROL, scontrol);
|
|
||||||
|
if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
sata_set_spd(ap);
|
sata_set_spd(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* issue phy wake/reset */
|
/* issue phy wake/reset */
|
||||||
scontrol = scr_read(ap, SCR_CONTROL);
|
if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
scontrol = (scontrol & 0x0f0) | 0x301;
|
scontrol = (scontrol & 0x0f0) | 0x301;
|
||||||
scr_write_flush(ap, SCR_CONTROL, scontrol);
|
|
||||||
|
if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
|
/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
|
||||||
* 10.4.2 says at least 1 ms.
|
* 10.4.2 says at least 1 ms.
|
||||||
|
@ -2487,7 +2501,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
sata_phy_resume(ap);
|
sata_phy_resume(ap);
|
||||||
|
|
||||||
/* TODO: phy layer with polling, timeouts, etc. */
|
/* TODO: phy layer with polling, timeouts, etc. */
|
||||||
if (!sata_dev_present(ap)) {
|
if (ata_port_offline(ap)) {
|
||||||
*class = ATA_DEV_NONE;
|
*class = ATA_DEV_NONE;
|
||||||
DPRINTK("EXIT, link offline\n");
|
DPRINTK("EXIT, link offline\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2527,8 +2541,7 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
/* print link status */
|
/* print link status */
|
||||||
if (ap->cbl == ATA_CBL_SATA)
|
sata_print_link_status(ap);
|
||||||
sata_print_link_status(ap);
|
|
||||||
|
|
||||||
/* re-enable interrupts */
|
/* re-enable interrupts */
|
||||||
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
||||||
|
@ -2575,7 +2588,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes)
|
||||||
ata_reset_fn_t hardreset;
|
ata_reset_fn_t hardreset;
|
||||||
|
|
||||||
hardreset = NULL;
|
hardreset = NULL;
|
||||||
if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read)
|
if (sata_scr_valid(ap))
|
||||||
hardreset = sata_std_hardreset;
|
hardreset = sata_std_hardreset;
|
||||||
|
|
||||||
return ata_drive_probe_reset(ap, ata_std_probeinit,
|
return ata_drive_probe_reset(ap, ata_std_probeinit,
|
||||||
|
|
|
@ -1309,8 +1309,8 @@ static void mv_err_intr(struct ata_port *ap)
|
||||||
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||||
|
|
||||||
if (EDMA_ERR_SERR & edma_err_cause) {
|
if (EDMA_ERR_SERR & edma_err_cause) {
|
||||||
serr = scr_read(ap, SCR_ERROR);
|
sata_scr_read(ap, SCR_ERROR, &serr);
|
||||||
scr_write_flush(ap, SCR_ERROR, serr);
|
sata_scr_write_flush(ap, SCR_ERROR, serr);
|
||||||
}
|
}
|
||||||
if (EDMA_ERR_SELF_DIS & edma_err_cause) {
|
if (EDMA_ERR_SELF_DIS & edma_err_cause) {
|
||||||
struct mv_port_priv *pp = ap->private_data;
|
struct mv_port_priv *pp = ap->private_data;
|
||||||
|
@ -1934,15 +1934,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
|
||||||
|
|
||||||
/* Issue COMRESET via SControl */
|
/* Issue COMRESET via SControl */
|
||||||
comreset_retry:
|
comreset_retry:
|
||||||
scr_write_flush(ap, SCR_CONTROL, 0x301);
|
sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
|
||||||
__msleep(1, can_sleep);
|
__msleep(1, can_sleep);
|
||||||
|
|
||||||
scr_write_flush(ap, SCR_CONTROL, 0x300);
|
sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
|
||||||
__msleep(20, can_sleep);
|
__msleep(20, can_sleep);
|
||||||
|
|
||||||
timeout = jiffies + msecs_to_jiffies(200);
|
timeout = jiffies + msecs_to_jiffies(200);
|
||||||
do {
|
do {
|
||||||
sstatus = scr_read(ap, SCR_STATUS) & 0x3;
|
sata_scr_read(ap, SCR_STATUS, &sstatus);
|
||||||
|
sstatus &= 0x3;
|
||||||
if ((sstatus == 3) || (sstatus == 0))
|
if ((sstatus == 3) || (sstatus == 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1959,11 +1960,12 @@ comreset_retry:
|
||||||
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
|
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
|
||||||
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
|
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
|
||||||
|
|
||||||
if (sata_dev_present(ap)) {
|
if (ata_port_online(ap)) {
|
||||||
ata_port_probe(ap);
|
ata_port_probe(ap);
|
||||||
} else {
|
} else {
|
||||||
|
sata_scr_read(ap, SCR_STATUS, &sstatus);
|
||||||
printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
|
printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
|
||||||
ap->id, scr_read(ap, SCR_STATUS));
|
ap->id, sstatus);
|
||||||
ata_port_disable(ap);
|
ata_port_disable(ap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ static int sil24_softreset(struct ata_port *ap, unsigned int *class)
|
||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
if (!sata_dev_present(ap)) {
|
if (ata_port_offline(ap)) {
|
||||||
DPRINTK("PHY reports no device\n");
|
DPRINTK("PHY reports no device\n");
|
||||||
*class = ATA_DEV_NONE;
|
*class = ATA_DEV_NONE;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -531,7 +531,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
sata_set_spd(ap);
|
sata_set_spd(ap);
|
||||||
|
|
||||||
tout_msec = 100;
|
tout_msec = 100;
|
||||||
if (sata_dev_present(ap))
|
if (ata_port_online(ap))
|
||||||
tout_msec = 5000;
|
tout_msec = 5000;
|
||||||
|
|
||||||
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
|
writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
|
||||||
|
@ -544,7 +544,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
|
||||||
msleep(100);
|
msleep(100);
|
||||||
|
|
||||||
if (tmp & PORT_CS_DEV_RST) {
|
if (tmp & PORT_CS_DEV_RST) {
|
||||||
if (!sata_dev_present(ap))
|
if (ata_port_offline(ap))
|
||||||
return 0;
|
return 0;
|
||||||
reason = "link not ready";
|
reason = "link not ready";
|
||||||
goto err;
|
goto err;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче