mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 16:41:58 +00:00
[PATCH] libata: make new reset act identical to ->phy_reset register-wise
This patch makes std component operations act identical to ->phy_reset register-wise except for SError clearing on sata_std_hardreset. Note that if a driver only implements/uses hardreset, it should not use ata_std_probeinit() to avoid extra sata_phy_resume() and ata_busy_sleep() compared to ->phy_reset. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
c5014de8a7
commit
3a39746a52
@ -1924,11 +1924,20 @@ static int sata_phy_resume(struct ata_port *ap)
|
|||||||
*
|
*
|
||||||
* @ap is about to be probed. Initialize it. This function is
|
* @ap is about to be probed. Initialize it. This function is
|
||||||
* to be used as standard callback for ata_drive_probe_reset().
|
* to be used as standard callback for ata_drive_probe_reset().
|
||||||
|
*
|
||||||
|
* NOTE!!! Do not use this function as probeinit if a low level
|
||||||
|
* driver implements only hardreset. Just pass NULL as probeinit
|
||||||
|
* in that case. Using this function is probably okay but doing
|
||||||
|
* so makes reset sequence different from the original
|
||||||
|
* ->phy_reset implementation and Jeff nervous. :-P
|
||||||
*/
|
*/
|
||||||
extern void ata_std_probeinit(struct ata_port *ap)
|
extern void ata_std_probeinit(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
|
if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
|
||||||
sata_phy_resume(ap);
|
sata_phy_resume(ap);
|
||||||
|
if (sata_dev_present(ap))
|
||||||
|
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1954,20 +1963,17 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
|
|||||||
|
|
||||||
DPRINTK("ENTER\n");
|
DPRINTK("ENTER\n");
|
||||||
|
|
||||||
|
if (ap->ops->scr_read && !sata_dev_present(ap)) {
|
||||||
|
classes[0] = ATA_DEV_NONE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* determine if device 0/1 are present */
|
/* determine if device 0/1 are present */
|
||||||
if (ata_devchk(ap, 0))
|
if (ata_devchk(ap, 0))
|
||||||
devmask |= (1 << 0);
|
devmask |= (1 << 0);
|
||||||
if (slave_possible && ata_devchk(ap, 1))
|
if (slave_possible && ata_devchk(ap, 1))
|
||||||
devmask |= (1 << 1);
|
devmask |= (1 << 1);
|
||||||
|
|
||||||
/* devchk reports device presence without actual device on
|
|
||||||
* most SATA controllers. Check SStatus and turn devmask off
|
|
||||||
* if link is offline. Note that we should continue resetting
|
|
||||||
* even when it seems like there's no device.
|
|
||||||
*/
|
|
||||||
if (ap->ops->scr_read && !sata_dev_present(ap))
|
|
||||||
devmask = 0;
|
|
||||||
|
|
||||||
/* select device 0 again */
|
/* select device 0 again */
|
||||||
ap->ops->dev_select(ap, 0);
|
ap->ops->dev_select(ap, 0);
|
||||||
|
|
||||||
@ -1989,6 +1995,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
|
|||||||
if (slave_possible && err != 0x81)
|
if (slave_possible && err != 0x81)
|
||||||
classes[1] = ata_dev_try_classify(ap, 1, &err);
|
classes[1] = ata_dev_try_classify(ap, 1, &err);
|
||||||
|
|
||||||
|
out:
|
||||||
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
|
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2047,6 +2054,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ap->ops->dev_select(ap, 0); /* probably unnecessary */
|
||||||
|
|
||||||
*class = ata_dev_try_classify(ap, 0, NULL);
|
*class = ata_dev_try_classify(ap, 0, NULL);
|
||||||
|
|
||||||
DPRINTK("EXIT, class=%u\n", *class);
|
DPRINTK("EXIT, class=%u\n", *class);
|
||||||
@ -2081,11 +2090,9 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
|
|||||||
if (ap->cbl == ATA_CBL_SATA)
|
if (ap->cbl == ATA_CBL_SATA)
|
||||||
sata_print_link_status(ap);
|
sata_print_link_status(ap);
|
||||||
|
|
||||||
/* bail out if no device is present */
|
/* re-enable interrupts */
|
||||||
if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
|
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
||||||
DPRINTK("EXIT, no device\n");
|
ata_irq_on(ap);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is double-select really necessary? */
|
/* is double-select really necessary? */
|
||||||
if (classes[0] != ATA_DEV_NONE)
|
if (classes[0] != ATA_DEV_NONE)
|
||||||
@ -2093,9 +2100,19 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
|
|||||||
if (classes[1] != ATA_DEV_NONE)
|
if (classes[1] != ATA_DEV_NONE)
|
||||||
ap->ops->dev_select(ap, 0);
|
ap->ops->dev_select(ap, 0);
|
||||||
|
|
||||||
/* re-enable interrupts & set up device control */
|
/* bail out if no device is present */
|
||||||
if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
|
if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
|
||||||
ata_irq_on(ap);
|
DPRINTK("EXIT, no device\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up device control */
|
||||||
|
if (ap->ioaddr.ctl_addr) {
|
||||||
|
if (ap->flags & ATA_FLAG_MMIO)
|
||||||
|
writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
|
||||||
|
else
|
||||||
|
outb(ap->ctl, ap->ioaddr.ctl_addr);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTK("EXIT\n");
|
DPRINTK("EXIT\n");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user