From ac371987a81c61c2efbd6931245cdcaf43baad89 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 7 Apr 2008 22:47:19 +0900 Subject: libata: clear SError after link resume SError used to be cleared in ->postreset. This has small hotplug race condition. If a device is plugged in after reset is complete but postreset hasn't run yet, its hotplug event gets lost when SError is cleared. This patch makes sata_link_resume() clear SError. This kills the race condition and makes a lot of sense as some PMP and host PHYs don't work properly without SError cleared. This change makes sata_pmp_std_{pre|post}_reset()'s unnecessary as they become identical to ata_std counterparts. It also simplifies sata_pmp_hardreset() and ahci_vt8251_hardreset(). Signed-off-by: Tejun Heo --- drivers/ata/libata-pmp.c | 93 +----------------------------------------------- 1 file changed, 1 insertion(+), 92 deletions(-) (limited to 'drivers/ata/libata-pmp.c') diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 7f1a87f01ab2..2f8a9577c26d 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -175,49 +175,6 @@ int sata_pmp_scr_write(struct ata_link *link, int reg, u32 val) return 0; } -/** - * sata_pmp_std_prereset - prepare PMP link for reset - * @link: link to be reset - * @deadline: deadline jiffies for the operation - * - * @link is about to be reset. Initialize it. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline) -{ - struct ata_eh_context *ehc = &link->eh_context; - const unsigned long *timing = sata_ehc_deb_timing(ehc); - int rc; - - /* if we're about to do hardreset, nothing more to do */ - if (ehc->i.action & ATA_EH_HARDRESET) - return 0; - - /* resume link */ - rc = sata_link_resume(link, timing, deadline); - if (rc) { - /* phy resume failed */ - ata_link_printk(link, KERN_WARNING, "failed to resume link " - "for reset (errno=%d)\n", rc); - return rc; - } - - /* clear SError bits including .X which blocks the port when set */ - rc = sata_scr_write(link, SCR_ERROR, 0xffffffff); - if (rc) { - ata_link_printk(link, KERN_ERR, - "failed to clear SError (errno=%d)\n", rc); - return rc; - } - - return 0; -} - /** * sata_pmp_std_hardreset - standard hardreset method for PMP link * @link: link to be reset @@ -238,33 +195,13 @@ int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline) int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { - const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); - bool online; u32 tmp; int rc; DPRINTK("ENTER\n"); - /* do hardreset */ - rc = sata_link_hardreset(link, timing, deadline, &online, NULL); - if (rc) { - ata_link_printk(link, KERN_ERR, - "COMRESET failed (errno=%d)\n", rc); - goto out; - } - - /* clear SError bits including .X which blocks the port when set */ - rc = sata_scr_write(link, SCR_ERROR, 0xffffffff); - if (rc) { - ata_link_printk(link, KERN_ERR, "failed to clear SError " - "during hardreset (errno=%d)\n", rc); - goto out; - } + rc = sata_std_hardreset(link, class, deadline); - /* if device is present, follow up with srst to wait for !BSY */ - if (online) - rc = -EAGAIN; - out: /* if SCR isn't accessible, we need to reset the PMP */ if (rc && rc != -EAGAIN && sata_scr_read(link, SCR_STATUS, &tmp)) rc = -ERESTART; @@ -273,34 +210,6 @@ int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class, return rc; } -/** - * ata_std_postreset - standard postreset method for PMP link - * @link: the target ata_link - * @classes: classes of attached devices - * - * This function is invoked after a successful reset. Note that - * the device might have been reset more than once using - * different reset methods before postreset is invoked. - * - * LOCKING: - * Kernel thread context (may sleep) - */ -void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class) -{ - u32 serror; - - DPRINTK("ENTER\n"); - - /* clear SError */ - if (sata_scr_read(link, SCR_ERROR, &serror) == 0) - sata_scr_write(link, SCR_ERROR, serror); - - /* print link status */ - sata_print_link_status(link); - - DPRINTK("EXIT\n"); -} - /** * sata_pmp_read_gscr - read GSCR block of SATA PMP * @dev: PMP device -- cgit v1.2.3