/** * vt6420_prereset - prereset for vt6420 * @link: target ATA link * @deadline: deadline jiffies for the operation * * SCR registers on vt6420 are pieces of shit and may hang the * whole machine completely if accessed with the wrong timing. * To avoid such catastrophe, vt6420 doesn't provide generic SCR * access operations, but uses SStatus and SControl only during * boot probing in controlled way. * * As the old (pre EH update) probing code is proven to work, we * strictly follow the access pattern. * * LOCKING: * Kernel thread context (may sleep) * * RETURNS: * 0 on success, -errno otherwise. */ static int vt6420_prereset(struct ata_link *link, unsigned long deadline) { struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &ap->link.eh_context; unsigned long timeout = jiffies + (HZ * 5); u32 sstatus, scontrol; int online; /* don't do any SCR stuff if we're not loading */ if (!(ap->pflags & ATA_PFLAG_LOADING)) goto skip_scr; /* Resume phy. This is the old SATA resume sequence */ svia_scr_write(link, SCR_CONTROL, 0x300); svia_scr_read(link, SCR_CONTROL, &scontrol); /* flush */ /* wait for phy to become ready, if necessary */ do { ata_msleep(link->ap, 200); svia_scr_read(link, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); /* open code sata_print_link_status() */ svia_scr_read(link, SCR_STATUS, &sstatus); svia_scr_read(link, SCR_CONTROL, &scontrol); online = (sstatus & 0xf) == 0x3; #ifdef CONFIG_DEBUG_PRINTK ata_port_printk(ap, KERN_INFO, "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n", online ? "up" : "down", sstatus, scontrol); #else ata_port_; #endif /* SStatus is read one more time */ svia_scr_read(link, SCR_STATUS, &sstatus); if (!online) { /* tell EH to bail */ ehc->i.action &= ~ATA_EH_RESET; return 0; } skip_scr: /* wait for !BSY */ ata_sff_wait_ready(link, deadline); return 0; }
static int vt6420_prereset(struct ata_link *link, unsigned long deadline) { struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &ap->link.eh_context; unsigned long timeout = jiffies + (HZ * 5); u32 sstatus, scontrol; int online; if (!(ap->pflags & ATA_PFLAG_LOADING)) goto skip_scr; svia_scr_write(link, SCR_CONTROL, 0x300); svia_scr_read(link, SCR_CONTROL, &scontrol); do { msleep(200); svia_scr_read(link, SCR_STATUS, &sstatus); if ((sstatus & 0xf) != 1) break; } while (time_before(jiffies, timeout)); svia_scr_read(link, SCR_STATUS, &sstatus); svia_scr_read(link, SCR_CONTROL, &scontrol); online = (sstatus & 0xf) == 0x3; ata_port_printk(ap, KERN_INFO, "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n", online ? "up" : "down", sstatus, scontrol); svia_scr_read(link, SCR_STATUS, &sstatus); if (!online) { ehc->i.action &= ~ATA_EH_RESET; return 0; } skip_scr: ata_sff_wait_ready(link, deadline); return 0; }