[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:
Tejun Heo 2006-05-15 20:57:47 +09:00
Родитель 34bf21704c
Коммит 81952c5497
4 изменённых файлов: 75 добавлений и 60 удалений

Просмотреть файл

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