diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 9c07b88..8b58597 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -288,6 +288,7 @@ static const struct ata_port_operations piix_pata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .cable_detect = ata_cable_40wire, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -300,7 +301,6 @@ static const struct ata_port_operations piix_pata_ops = { .thaw = ata_bmdma_thaw, .error_handler = piix_pata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, - .cable_detect = ata_cable_40wire, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -322,6 +322,7 @@ static const struct ata_port_operations ich_pata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .cable_detect = ich_pata_cable_detect, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -334,7 +335,6 @@ static const struct ata_port_operations ich_pata_ops = { .thaw = ata_bmdma_thaw, .error_handler = piix_pata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, - .cable_detect = ich_pata_cable_detect, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, @@ -353,6 +353,7 @@ static const struct ata_port_operations piix_sata_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .cable_detect = ata_cable_sata, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3ca9c61..dbd590a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3035,7 +3035,7 @@ int ata_wait_ready(struct ata_port *ap, unsigned long deadline) warned = 1; } - msleep(50); + msleep(5); } } @@ -3072,7 +3072,7 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask, break; if (time_after(jiffies, deadline)) return -EBUSY; - msleep(50); /* give drive a breather */ + msleep(5); /* give drive a breather */ } if (dev1) { rc = ata_wait_ready(ap, deadline); @@ -3101,23 +3101,13 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, DPRINTK("ata%u: bus reset via SRST\n", ap->print_id); /* software reset. causes dev0 to be selected */ - iowrite8(ap->ctl, ioaddr->ctl_addr); - udelay(20); /* FIXME: flush */ iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); - udelay(20); /* FIXME: flush */ + ata_pause(ap); iowrite8(ap->ctl, ioaddr->ctl_addr); + ata_pause(ap); - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); + /* spec mandates ">= 2ms" before checking status */ + msleep(2); /* Before we perform post reset processing we want to see if * the bus shows 0xFF because the odd clown forgets the D7 @@ -3363,6 +3353,35 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline) "link for reset (errno=%d)\n", rc); } + return 0; +} + +/** + * sata_std_prereset - prepare for reset + * @ap: ATA port to be reset + * @deadline: deadline jiffies for the operation + * + * @ap is about to be reset. Initialize it. Failure from + * prereset makes libata abort whole reset sequence and give up + * that port, so prereset should be best-effort. It does its + * best to prepare for reset sequence but if things go wrong, it + * should just whine, not fail. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +int sata_std_prereset(struct ata_port *ap, unsigned long deadline) +{ + struct ata_eh_context *ehc = &ap->eh_context; + int rc; + + rc = ata_std_prereset(ap, deadline); + if (rc) + return rc; + /* Wait for !BSY if the controller can wait for the first D2H * Reg FIS and we don't know that no device is attached. */ @@ -3404,9 +3423,13 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes, if (ata_port_offline(ap)) { classes[0] = ATA_DEV_NONE; + classes[1] = ATA_DEV_NONE; goto out; } + /* set up Device Control */ + iowrite8(ap->ctl, ap->ioaddr.ctl_addr); + /* determine if device 0/1 are present */ if (ata_devchk(ap, 0)) devmask |= (1 << 0); @@ -3419,6 +3442,7 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes, /* issue bus reset */ DPRINTK("about to softreset, devmask=%x\n", devmask); rc = ata_bus_softreset(ap, devmask, deadline); + /* if link is occupied, -ENODEV too is an error */ if (rc && (rc != -ENODEV || sata_scr_valid(ap))) { ata_port_printk(ap, KERN_ERR, "SRST failed (errno=%d)\n", rc); @@ -3534,7 +3558,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class, } /* wait a while before checking status, see SRST for more info */ - msleep(150); + msleep(3); rc = ata_wait_ready(ap, deadline); /* link occupied, -ENODEV too is an error */ @@ -6837,6 +6861,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_freeze); EXPORT_SYMBOL_GPL(ata_bmdma_thaw); EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh); EXPORT_SYMBOL_GPL(ata_bmdma_error_handler); +EXPORT_SYMBOL_GPL(sata_bmdma_error_handler); EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(ata_dev_disable); @@ -6847,6 +6872,7 @@ EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_prereset); +EXPORT_SYMBOL_GPL(sata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_port_hardreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index e35d134..3233fe9 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -503,6 +503,27 @@ void ata_bmdma_error_handler(struct ata_port *ap) } /** + * sata_bmdma_error_handler - Stock SATA error handler for BMDMA controller + * @ap: port to handle error for + * + * Stock error handler for BMDMA controller. + * + * LOCKING: + * Kernel thread context (may sleep) + */ +void sata_bmdma_error_handler(struct ata_port *ap) +{ + ata_reset_fn_t hardreset; + + hardreset = NULL; + if (sata_scr_valid(ap)) + hardreset = sata_std_hardreset; + + ata_bmdma_drive_eh(ap, sata_std_prereset, ata_std_softreset, hardreset, + ata_std_postreset); +} + +/** * ata_bmdma_post_internal_cmd - Stock post_internal_cmd for * BMDMA controller * @qc: internal command to clean up diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index a3b339b..feac2c3 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -202,7 +202,7 @@ static const struct ata_port_operations sil_ops = { .data_xfer = ata_data_xfer, .freeze = sil_freeze, .thaw = sil_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 221099d..852e1e0 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -119,7 +119,7 @@ static const struct ata_port_operations sis_ops = { .data_xfer = ata_data_xfer, .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index bcb2cd8..362ad0b 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -343,7 +343,7 @@ static const struct ata_port_operations k2_sata_ops = { .data_xfer = ata_data_xfer, .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index 6815de7..29c7be7 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -112,7 +112,7 @@ static const struct ata_port_operations uli_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index e8b90e7..1a26aea 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -174,7 +174,7 @@ static const struct ata_port_operations vt6421_pata_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .cable_detect = vt6421_pata_cable_detect, @@ -205,7 +205,7 @@ static const struct ata_port_operations vt6421_sata_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .cable_detect = ata_cable_sata, diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 8133017..177552b 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -331,7 +331,7 @@ static const struct ata_port_operations vsc_sata_ops = { .data_xfer = ata_data_xfer, .freeze = vsc_freeze, .thaw = vsc_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = sata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_clear = ata_bmdma_irq_clear, .irq_on = ata_irq_on, diff --git a/include/linux/libata.h b/include/linux/libata.h index 85f7b1b..5f75d45 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -674,6 +674,7 @@ extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param, extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param, unsigned long deadline); extern int ata_std_prereset(struct ata_port *ap, unsigned long deadline); +extern int sata_std_prereset(struct ata_port *ap, unsigned long deadline); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes, unsigned long deadline); extern int sata_port_hardreset(struct ata_port *ap, const unsigned long *timing, @@ -786,6 +787,7 @@ extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); extern void ata_bmdma_error_handler(struct ata_port *ap); +extern void sata_bmdma_error_handler(struct ata_port *ap); extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc); extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status, int in_wq);