From bd3adca52bc43b72c75db3e4c7809d47923b154c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 2 Nov 2007 09:32:38 +0800 Subject: libata-acpi: add ACPI _PSx method ACPI spec (ver 3.0a, p289) requires IDE power on/off executes ACPI _PSx methods. As recently most PATA drivers use libata, this patch adds _PSx method support in libata. ACPI spec doesn't mention if SATA requires the same _PSx method. Signed-off-by: Shaohua Li Acked-by: Len Brown Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 21a81cd148e..1d7faab6481 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2747,6 +2747,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) if (ap->ops->port_suspend) rc = ap->ops->port_suspend(ap, ap->pm_mesg); + ata_acpi_set_state(ap, PMSG_SUSPEND); out: /* report result */ spin_lock_irqsave(ap->lock, flags); @@ -2792,6 +2793,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED)); + ata_acpi_set_state(ap, PMSG_ON); + if (ap->ops->port_resume) rc = ap->ops->port_resume(ap); -- cgit v1.2.3-70-g09d2 From 02c05a27e884c9655dae5b1c8bc0cd89c060c43d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:54 +0900 Subject: libata: factor out ata_eh_schedule_probe() Factor out ata_eh_schedule_probe() from ata_eh_handle_dev_fail() and ata_eh_recover(). This is to improve maintainability and make future changes easier. In the previous revision, ata_dev_enabled() test was accidentally dropped while factoring out. This problem was spotted by Bartlomiej. Signed-off-by: Tejun Heo Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 1d7faab6481..b16c81a24ba 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2375,6 +2375,22 @@ static int ata_eh_skip_recovery(struct ata_link *link) return 1; } +static int ata_eh_schedule_probe(struct ata_device *dev) +{ + struct ata_eh_context *ehc = &dev->link->eh_context; + + if (!(ehc->i.probe_mask & (1 << dev->devno)) || + (ehc->did_probe_mask & (1 << dev->devno))) + return 0; + + ata_eh_detach_dev(dev); + ata_dev_init(dev); + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + + return 1; +} + static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) { struct ata_eh_context *ehc = &dev->link->eh_context; @@ -2406,16 +2422,9 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) if (ata_link_offline(dev->link)) ata_eh_detach_dev(dev); - /* probe if requested */ - if ((ehc->i.probe_mask & (1 << dev->devno)) && - !(ehc->did_probe_mask & (1 << dev->devno))) { - ata_eh_detach_dev(dev); - ata_dev_init(dev); - + /* schedule probe if necessary */ + if (ata_eh_schedule_probe(dev)) ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; - ehc->did_probe_mask |= (1 << dev->devno); - ehc->i.action |= ATA_EH_SOFTRESET; - } return 1; } else { @@ -2492,14 +2501,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, if (dev->flags & ATA_DFLAG_DETACH) ata_eh_detach_dev(dev); - if (!ata_dev_enabled(dev) && - ((ehc->i.probe_mask & (1 << dev->devno)) && - !(ehc->did_probe_mask & (1 << dev->devno)))) { - ata_eh_detach_dev(dev); - ata_dev_init(dev); - ehc->did_probe_mask |= (1 << dev->devno); - ehc->i.action |= ATA_EH_SOFTRESET; - } + /* schedule probe if necessary */ + if (!ata_dev_enabled(dev)) + ata_eh_schedule_probe(dev); } } -- cgit v1.2.3-70-g09d2 From 6f1d1e3a03fd04a9d9c82fd3cf414020097bb142 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:55 +0900 Subject: libata: move ata_set_mode() to libata-eh.c Move ata_set_mode() to libata-eh.c. ata_set_mode() is surely an EH action and will be more tightly coupled with the rest of error handling. Move it to libata-eh.c. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 25 ------------------------- drivers/ata/libata-eh.c | 25 +++++++++++++++++++++++++ drivers/ata/libata.h | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8c7af2c8e8d..86c10cc751e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3182,31 +3182,6 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) return rc; } -/** - * ata_set_mode - Program timings and issue SET FEATURES - XFER - * @link: link on which timings will be programmed - * @r_failed_dev: out paramter for failed device - * - * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If - * ata_set_mode() fails, pointer to the failing device is - * returned in @r_failed_dev. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - * RETURNS: - * 0 on success, negative errno otherwise - */ -int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) -{ - struct ata_port *ap = link->ap; - - /* has private set_mode? */ - if (ap->ops->set_mode) - return ap->ops->set_mode(link, r_failed_dev); - return ata_do_set_mode(link, r_failed_dev); -} - /** * ata_tf_to_host - issue ATA taskfile to host controller * @ap: port to which command is being issued diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index b16c81a24ba..ebab7595890 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2329,6 +2329,31 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, return rc; } +/** + * ata_set_mode - Program timings and issue SET FEATURES - XFER + * @link: link on which timings will be programmed + * @r_failed_dev: out paramter for failed device + * + * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If + * ata_set_mode() fails, pointer to the failing device is + * returned in @r_failed_dev. + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * 0 on success, negative errno otherwise + */ +int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) +{ + struct ata_port *ap = link->ap; + + /* has private set_mode? */ + if (ap->ops->set_mode) + return ap->ops->set_mode(link, r_failed_dev); + return ata_do_set_mode(link, r_failed_dev); +} + static int ata_link_nr_enabled(struct ata_link *link) { struct ata_device *dev; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 8cf0874f248..409ffb9af16 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -86,7 +86,6 @@ extern int ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_link *link); extern int sata_set_spd_needed(struct ata_link *link); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); -extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern void ata_sg_clean(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); @@ -187,6 +186,7 @@ extern void ata_eh_report(struct ata_port *ap); extern int ata_eh_reset(struct ata_link *link, int classify, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset); +extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset, -- cgit v1.2.3-70-g09d2 From 3884f7b0a8382b89d8ca5da23bd98e3e15fc805b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:56 +0900 Subject: libata: clean up EH speed down implementation Clean up EH speed down implementation. * is_io boolean variable is replaced eflags. is_io is ATA_EFLAG_IS_IO. * Error categories now have names. * Better comments. * Reorder 5min and 10min rules in ata_eh_speed_down_verdict() * Use local variable @link to cache @dev->link in ata_eh_speed_down() These changes are to improve readability and ease further changes. This patch doesn't introduce any behavior change. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 117 ++++++++++++++++++++++++++++++------------------ include/linux/libata.h | 2 +- 2 files changed, 74 insertions(+), 45 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ebab7595890..b01ade10272 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -46,9 +46,20 @@ #include "libata.h" enum { + /* speed down verdicts */ ATA_EH_SPDN_NCQ_OFF = (1 << 0), ATA_EH_SPDN_SPEED_DOWN = (1 << 1), ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2), + + /* error flags */ + ATA_EFLAG_IS_IO = (1 << 0), + + /* error categories */ + ATA_ECAT_NONE = 0, + ATA_ECAT_ATA_BUS = 1, + ATA_ECAT_TOUT_HSM = 2, + ATA_ECAT_UNK_DEV = 3, + ATA_ECAT_NR = 4, }; /* Waiting in ->prereset can never be reliable. It's sometimes nice @@ -218,7 +229,7 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset, #endif /* CONFIG_PCI */ -static void ata_ering_record(struct ata_ering *ering, int is_io, +static void ata_ering_record(struct ata_ering *ering, unsigned int eflags, unsigned int err_mask) { struct ata_ering_entry *ent; @@ -229,7 +240,7 @@ static void ata_ering_record(struct ata_ering *ering, int is_io, ering->cursor %= ATA_ERING_SIZE; ent = &ering->ring[ering->cursor]; - ent->is_io = is_io; + ent->eflags = eflags; ent->err_mask = err_mask; ent->timestamp = get_jiffies_64(); } @@ -1451,20 +1462,20 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return action; } -static int ata_eh_categorize_error(int is_io, unsigned int err_mask) +static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask) { if (err_mask & AC_ERR_ATA_BUS) - return 1; + return ATA_ECAT_ATA_BUS; if (err_mask & AC_ERR_TIMEOUT) - return 2; + return ATA_ECAT_TOUT_HSM; - if (is_io) { + if (eflags & ATA_EFLAG_IS_IO) { if (err_mask & AC_ERR_HSM) - return 2; + return ATA_ECAT_TOUT_HSM; if ((err_mask & (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV) - return 3; + return ATA_ECAT_UNK_DEV; } return 0; @@ -1472,13 +1483,13 @@ static int ata_eh_categorize_error(int is_io, unsigned int err_mask) struct speed_down_verdict_arg { u64 since; - int nr_errors[4]; + int nr_errors[ATA_ECAT_NR]; }; static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) { struct speed_down_verdict_arg *arg = void_arg; - int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask); + int cat = ata_eh_categorize_error(ent->eflags, ent->err_mask); if (ent->timestamp < arg->since) return -1; @@ -1495,22 +1506,33 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) * whether NCQ needs to be turned off, transfer speed should be * stepped down, or falling back to PIO is necessary. * - * Cat-1 is ATA_BUS error for any command. + * ECAT_ATA_BUS : ATA_BUS error for any command + * + * ECAT_TOUT_HSM : TIMEOUT for any command or HSM violation for + * IO commands + * + * ECAT_UNK_DEV : Unknown DEV error for IO commands + * + * Verdicts are * - * Cat-2 is TIMEOUT for any command or HSM violation for known - * supported commands. + * NCQ_OFF : Turn off NCQ. * - * Cat-3 is is unclassified DEV error for known supported - * command. + * SPEED_DOWN : Speed down transfer speed but don't fall back + * to PIO. * - * NCQ needs to be turned off if there have been more than 3 - * Cat-2 + Cat-3 errors during last 10 minutes. + * FALLBACK_TO_PIO : Fall back to PIO. * - * Speed down is necessary if there have been more than 3 Cat-1 + - * Cat-2 errors or 10 Cat-3 errors during last 10 minutes. + * Even if multiple verdicts are returned, only one action is + * taken per error. ering is cleared after an action is taken. * - * Falling back to PIO mode is necessary if there have been more - * than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes. + * 1. If more than 10 ATA_BUS, TOUT_HSM or UNK_DEV errors + * ocurred during last 5 mins, FALLBACK_TO_PIO + * + * 2. If more than 3 TOUT_HSM or UNK_DEV errors occurred + * during last 10 mins, NCQ_OFF. + * + * 3. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 10 + * UNK_DEV errors occurred during last 10 mins, SPEED_DOWN. * * LOCKING: * Inherited from caller. @@ -1525,23 +1547,29 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) struct speed_down_verdict_arg arg; unsigned int verdict = 0; - /* scan past 10 mins of error history */ + /* scan past 5 mins of error history */ memset(&arg, 0, sizeof(arg)); - arg.since = j64 - min(j64, j10mins); + arg.since = j64 - min(j64, j5mins); ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg); - if (arg.nr_errors[2] + arg.nr_errors[3] > 3) - verdict |= ATA_EH_SPDN_NCQ_OFF; - if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10) - verdict |= ATA_EH_SPDN_SPEED_DOWN; + if (arg.nr_errors[ATA_ECAT_ATA_BUS] + + arg.nr_errors[ATA_ECAT_TOUT_HSM] + + arg.nr_errors[ATA_ECAT_UNK_DEV] > 10) + verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO; - /* scan past 3 mins of error history */ + /* scan past 10 mins of error history */ memset(&arg, 0, sizeof(arg)); - arg.since = j64 - min(j64, j5mins); + arg.since = j64 - min(j64, j10mins); ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg); - if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10) - verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO; + if (arg.nr_errors[ATA_ECAT_TOUT_HSM] + + arg.nr_errors[ATA_ECAT_UNK_DEV] > 3) + verdict |= ATA_EH_SPDN_NCQ_OFF; + + if (arg.nr_errors[ATA_ECAT_ATA_BUS] + + arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 || + arg.nr_errors[ATA_ECAT_UNK_DEV] > 10) + verdict |= ATA_EH_SPDN_SPEED_DOWN; return verdict; } @@ -1549,7 +1577,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) /** * ata_eh_speed_down - record error and speed down if necessary * @dev: Failed device - * @is_io: Did the device fail during normal IO? + * @eflags: mask of ATA_EFLAG_* flags * @err_mask: err_mask of the error * * Record error and examine error history to determine whether @@ -1563,18 +1591,19 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) * RETURNS: * Determined recovery action. */ -static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io, - unsigned int err_mask) +static unsigned int ata_eh_speed_down(struct ata_device *dev, + unsigned int eflags, unsigned int err_mask) { + struct ata_link *link = dev->link; unsigned int verdict; unsigned int action = 0; /* don't bother if Cat-0 error */ - if (ata_eh_categorize_error(is_io, err_mask) == 0) + if (ata_eh_categorize_error(eflags, err_mask) == 0) return 0; /* record error and determine whether speed down is necessary */ - ata_ering_record(&dev->ering, is_io, err_mask); + ata_ering_record(&dev->ering, eflags, err_mask); verdict = ata_eh_speed_down_verdict(dev); /* turn off NCQ? */ @@ -1590,7 +1619,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io, /* speed down? */ if (verdict & ATA_EH_SPDN_SPEED_DOWN) { /* speed down SATA link speed if possible */ - if (sata_down_spd_limit(dev->link) == 0) { + if (sata_down_spd_limit(link) == 0) { action |= ATA_EH_HARDRESET; goto done; } @@ -1621,7 +1650,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io, * SATA. Consider it only for PATA. */ if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) && - (dev->link->ap->cbl != ATA_CBL_SATA) && + (link->ap->cbl != ATA_CBL_SATA) && (dev->xfer_shift != ATA_SHIFT_PIO)) { if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) { dev->spdn_cnt = 0; @@ -1653,8 +1682,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &link->eh_context; struct ata_device *dev; - unsigned int all_err_mask = 0; - int tag, is_io = 0; + unsigned int all_err_mask = 0, eflags = 0; + int tag; u32 serror; int rc; @@ -1713,15 +1742,15 @@ static void ata_eh_link_autopsy(struct ata_link *link) ehc->i.dev = qc->dev; all_err_mask |= qc->err_mask; if (qc->flags & ATA_QCFLAG_IO) - is_io = 1; + eflags |= ATA_EFLAG_IS_IO; } /* enforce default EH actions */ if (ap->pflags & ATA_PFLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) ehc->i.action |= ATA_EH_SOFTRESET; - else if ((is_io && all_err_mask) || - (!is_io && (all_err_mask & ~AC_ERR_DEV))) + else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) || + (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV))) ehc->i.action |= ATA_EH_REVALIDATE; /* If we have offending qcs and the associated failed device, @@ -1744,7 +1773,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) dev = link->device; if (dev) - ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask); + ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask); DPRINTK("EXIT\n"); } diff --git a/include/linux/libata.h b/include/linux/libata.h index ca347b01864..74f1255e252 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -482,7 +482,7 @@ struct ata_port_stats { }; struct ata_ering_entry { - int is_io; + unsigned int eflags; unsigned int err_mask; u64 timestamp; }; -- cgit v1.2.3-70-g09d2 From 663f99b86ac7d4c0eed8c239638da0ea8849288b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:57 +0900 Subject: libata: adjust speed down rules Speed down rules were too conservative. Adjust them a bit. * More than 10 timeouts can't happen in 5 minutes as command timeout is 30secs. Lower the limit for rule #1 to 6. * 10 timeouts is too high for rule #3 too. Lower it to 6. * SATAPI can benefit from falling back to PIO too. Allow SATAPI devices to fall back to PIO. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index b01ade10272..7d766ada7a5 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1525,13 +1525,13 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) * Even if multiple verdicts are returned, only one action is * taken per error. ering is cleared after an action is taken. * - * 1. If more than 10 ATA_BUS, TOUT_HSM or UNK_DEV errors + * 1. If more than 6 ATA_BUS, TOUT_HSM or UNK_DEV errors * ocurred during last 5 mins, FALLBACK_TO_PIO * * 2. If more than 3 TOUT_HSM or UNK_DEV errors occurred * during last 10 mins, NCQ_OFF. * - * 3. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 10 + * 3. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6 * UNK_DEV errors occurred during last 10 mins, SPEED_DOWN. * * LOCKING: @@ -1554,7 +1554,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) if (arg.nr_errors[ATA_ECAT_ATA_BUS] + arg.nr_errors[ATA_ECAT_TOUT_HSM] + - arg.nr_errors[ATA_ECAT_UNK_DEV] > 10) + arg.nr_errors[ATA_ECAT_UNK_DEV] > 6) verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO; /* scan past 10 mins of error history */ @@ -1568,7 +1568,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) if (arg.nr_errors[ATA_ECAT_ATA_BUS] + arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 || - arg.nr_errors[ATA_ECAT_UNK_DEV] > 10) + arg.nr_errors[ATA_ECAT_UNK_DEV] > 6) verdict |= ATA_EH_SPDN_SPEED_DOWN; return verdict; @@ -1647,10 +1647,10 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, } /* Fall back to PIO? Slowing down to PIO is meaningless for - * SATA. Consider it only for PATA. + * SATA ATA devices. Consider it only for PATA and SATAPI. */ if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) && - (link->ap->cbl != ATA_CBL_SATA) && + (link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) && (dev->xfer_shift != ATA_SHIFT_PIO)) { if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) { dev->spdn_cnt = 0; -- cgit v1.2.3-70-g09d2 From 00115e0f5bc3bfdf3f3855ad89c8895f10458f92 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:58 +0900 Subject: libata: implement ATA_DFLAG_DUBIOUS_XFER ATA_DFLAG_DUBIOUS_XFER is set whenever data transfer speed or method changes and gets cleared when data transfer command succeeds in the newly configured transfer mode. This will be used to improve speed down logic. Signed-off-by: Tejun Heo --- drivers/ata/libata-core.c | 19 +++++++++++++++++++ drivers/ata/libata-eh.c | 33 +++++++++++++++++++++++++++++++-- include/linux/libata.h | 3 +++ 3 files changed, 53 insertions(+), 2 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 86c10cc751e..124b6f111cc 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5797,6 +5797,22 @@ static void fill_result_tf(struct ata_queued_cmd *qc) ap->ops->tf_read(ap, &qc->result_tf); } +static void ata_verify_xfer(struct ata_queued_cmd *qc) +{ + struct ata_device *dev = qc->dev; + + if (ata_tag_internal(qc->tag)) + return; + + if (ata_is_nodata(qc->tf.protocol)) + return; + + if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol)) + return; + + dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER; +} + /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete @@ -5868,6 +5884,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc) break; } + if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) + ata_verify_xfer(qc); + __ata_qc_complete(qc); } else { if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7d766ada7a5..359a5ace847 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -456,9 +456,20 @@ void ata_scsi_error(struct Scsi_Host *host) spin_lock_irqsave(ap->lock, flags); __ata_port_for_each_link(link, ap) { + struct ata_eh_context *ehc = &link->eh_context; + struct ata_device *dev; + memset(&link->eh_context, 0, sizeof(link->eh_context)); link->eh_context.i = link->eh_info; memset(&link->eh_info, 0, sizeof(link->eh_info)); + + ata_link_for_each_dev(dev, link) { + int devno = dev->devno; + + ehc->saved_xfer_mode[devno] = dev->xfer_mode; + if (ata_ncq_enabled(dev)) + ehc->saved_ncq_enabled |= 1 << devno; + } } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2376,11 +2387,27 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) { struct ata_port *ap = link->ap; + struct ata_device *dev; + int rc; /* has private set_mode? */ if (ap->ops->set_mode) - return ap->ops->set_mode(link, r_failed_dev); - return ata_do_set_mode(link, r_failed_dev); + rc = ap->ops->set_mode(link, r_failed_dev); + else + rc = ata_do_set_mode(link, r_failed_dev); + + /* if transfer mode has changed, set DUBIOUS_XFER on device */ + ata_link_for_each_dev(dev, link) { + struct ata_eh_context *ehc = &link->eh_context; + u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; + u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); + + if (dev->xfer_mode != saved_xfer_mode || + ata_ncq_enabled(dev) != saved_ncq) + dev->flags |= ATA_DFLAG_DUBIOUS_XFER; + } + + return rc; } static int ata_link_nr_enabled(struct ata_link *link) @@ -2441,6 +2468,8 @@ static int ata_eh_schedule_probe(struct ata_device *dev) ata_dev_init(dev); ehc->did_probe_mask |= (1 << dev->devno); ehc->i.action |= ATA_EH_SOFTRESET; + ehc->saved_xfer_mode[dev->devno] = 0; + ehc->saved_ncq_enabled &= ~(1 << dev->devno); return 1; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 74f1255e252..131fb6625e1 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -143,6 +143,7 @@ enum { ATA_DFLAG_NCQ_OFF = (1 << 13), /* device limited to non-NCQ mode */ ATA_DFLAG_SPUNDOWN = (1 << 14), /* XXX: for spindown_compat */ ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ + ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */ ATA_DFLAG_INIT_MASK = (1 << 24) - 1, ATA_DFLAG_DETACH = (1 << 24), @@ -560,6 +561,8 @@ struct ata_eh_context { int tries[ATA_MAX_DEVICES]; unsigned int classes[ATA_MAX_DEVICES]; unsigned int did_probe_mask; + unsigned int saved_ncq_enabled; + u8 saved_xfer_mode[ATA_MAX_DEVICES]; }; struct ata_acpi_drive -- cgit v1.2.3-70-g09d2 From 76326ac1ac1f524014ef36986fed97796b28ec6b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 27 Nov 2007 19:28:59 +0900 Subject: libata: implement fast speed down for unverified data transfer mode It's very likely that the configured data transfer mode is the wrong one if device fails data transfers right after initial data transfer mode configuration (including NCQ on/off and xfermode). libata EH needs to speed down fast before upper layers give up on probing. This patch implement fast speed down rules to handle such cases better. Error occured while data transfer hasn't been verified trigger fast back-to-back speed down actions until data transfer works. This change will make cable mis-detection and other initial configuration problems corrected before partition scanning code gives up. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 97 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 14 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 359a5ace847..3a2f7ef3e60 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -50,16 +50,23 @@ enum { ATA_EH_SPDN_NCQ_OFF = (1 << 0), ATA_EH_SPDN_SPEED_DOWN = (1 << 1), ATA_EH_SPDN_FALLBACK_TO_PIO = (1 << 2), + ATA_EH_SPDN_KEEP_ERRORS = (1 << 3), /* error flags */ ATA_EFLAG_IS_IO = (1 << 0), + ATA_EFLAG_DUBIOUS_XFER = (1 << 1), /* error categories */ ATA_ECAT_NONE = 0, ATA_ECAT_ATA_BUS = 1, ATA_ECAT_TOUT_HSM = 2, ATA_ECAT_UNK_DEV = 3, - ATA_ECAT_NR = 4, + ATA_ECAT_DUBIOUS_ATA_BUS = 4, + ATA_ECAT_DUBIOUS_TOUT_HSM = 5, + ATA_ECAT_DUBIOUS_UNK_DEV = 6, + ATA_ECAT_NR = 7, + + ATA_ECAT_DUBIOUS_BASE = ATA_ECAT_DUBIOUS_ATA_BUS, }; /* Waiting in ->prereset can never be reliable. It's sometimes nice @@ -245,6 +252,15 @@ static void ata_ering_record(struct ata_ering *ering, unsigned int eflags, ent->timestamp = get_jiffies_64(); } +static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering) +{ + struct ata_ering_entry *ent = &ering->ring[ering->cursor]; + + if (ent->err_mask) + return ent; + return NULL; +} + static void ata_ering_clear(struct ata_ering *ering) { memset(ering, 0, sizeof(*ering)); @@ -1473,20 +1489,29 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, return action; } -static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask) +static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask, + int *xfer_ok) { + int base = 0; + + if (!(eflags & ATA_EFLAG_DUBIOUS_XFER)) + *xfer_ok = 1; + + if (!*xfer_ok) + base = ATA_ECAT_DUBIOUS_BASE; + if (err_mask & AC_ERR_ATA_BUS) - return ATA_ECAT_ATA_BUS; + return base + ATA_ECAT_ATA_BUS; if (err_mask & AC_ERR_TIMEOUT) - return ATA_ECAT_TOUT_HSM; + return base + ATA_ECAT_TOUT_HSM; if (eflags & ATA_EFLAG_IS_IO) { if (err_mask & AC_ERR_HSM) - return ATA_ECAT_TOUT_HSM; + return base + ATA_ECAT_TOUT_HSM; if ((err_mask & (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV) - return ATA_ECAT_UNK_DEV; + return base + ATA_ECAT_UNK_DEV; } return 0; @@ -1494,18 +1519,22 @@ static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask) struct speed_down_verdict_arg { u64 since; + int xfer_ok; int nr_errors[ATA_ECAT_NR]; }; static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) { struct speed_down_verdict_arg *arg = void_arg; - int cat = ata_eh_categorize_error(ent->eflags, ent->err_mask); + int cat; if (ent->timestamp < arg->since) return -1; + cat = ata_eh_categorize_error(ent->eflags, ent->err_mask, + &arg->xfer_ok); arg->nr_errors[cat]++; + return 0; } @@ -1524,6 +1553,9 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) * * ECAT_UNK_DEV : Unknown DEV error for IO commands * + * ECAT_DUBIOUS_* : Identical to above three but occurred while + * data transfer hasn't been verified. + * * Verdicts are * * NCQ_OFF : Turn off NCQ. @@ -1534,15 +1566,27 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) * FALLBACK_TO_PIO : Fall back to PIO. * * Even if multiple verdicts are returned, only one action is - * taken per error. ering is cleared after an action is taken. + * taken per error. An action triggered by non-DUBIOUS errors + * clears ering, while one triggered by DUBIOUS_* errors doesn't. + * This is to expedite speed down decisions right after device is + * initially configured. + * + * The followings are speed down rules. #1 and #2 deal with + * DUBIOUS errors. * - * 1. If more than 6 ATA_BUS, TOUT_HSM or UNK_DEV errors + * 1. If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors + * occurred during last 5 mins, SPEED_DOWN and FALLBACK_TO_PIO. + * + * 2. If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors + * occurred during last 5 mins, NCQ_OFF. + * + * 3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors * ocurred during last 5 mins, FALLBACK_TO_PIO * - * 2. If more than 3 TOUT_HSM or UNK_DEV errors occurred + * 4. If more than 3 TOUT_HSM or UNK_DEV errors occurred * during last 10 mins, NCQ_OFF. * - * 3. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6 + * 5. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6 * UNK_DEV errors occurred during last 10 mins, SPEED_DOWN. * * LOCKING: @@ -1563,6 +1607,15 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev) arg.since = j64 - min(j64, j5mins); ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg); + if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] + + arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1) + verdict |= ATA_EH_SPDN_SPEED_DOWN | + ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS; + + if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] + + arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1) + verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS; + if (arg.nr_errors[ATA_ECAT_ATA_BUS] + arg.nr_errors[ATA_ECAT_TOUT_HSM] + arg.nr_errors[ATA_ECAT_UNK_DEV] > 6) @@ -1606,11 +1659,12 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, unsigned int eflags, unsigned int err_mask) { struct ata_link *link = dev->link; + int xfer_ok = 0; unsigned int verdict; unsigned int action = 0; /* don't bother if Cat-0 error */ - if (ata_eh_categorize_error(eflags, err_mask) == 0) + if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0) return 0; /* record error and determine whether speed down is necessary */ @@ -1673,7 +1727,8 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, return 0; done: /* device has been slowed down, blow error history */ - ata_ering_clear(&dev->ering); + if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS)) + ata_ering_clear(&dev->ering); return action; } @@ -1783,8 +1838,11 @@ static void ata_eh_link_autopsy(struct ata_link *link) ata_dev_enabled(link->device)))) dev = link->device; - if (dev) + if (dev) { + if (dev->flags & ATA_DFLAG_DUBIOUS_XFER) + eflags |= ATA_EFLAG_DUBIOUS_XFER; ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask); + } DPRINTK("EXIT\n"); } @@ -2390,6 +2448,17 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) struct ata_device *dev; int rc; + /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ + ata_link_for_each_dev(dev, link) { + if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { + struct ata_ering_entry *ent; + + ent = ata_ering_top(&dev->ering); + if (ent) + ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER; + } + } + /* has private set_mode? */ if (ap->ops->set_mode) rc = ap->ops->set_mode(link, r_failed_dev); -- cgit v1.2.3-70-g09d2 From e39eec13ff8c58520d77b5f977b1e0fa067fbd2c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 1 Dec 2007 18:05:39 -0500 Subject: [libata] Build fix WRT ata_is_xxx() new API introduction Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 3a2f7ef3e60..d7d5a5ae04e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1987,7 +1987,7 @@ static void ata_eh_link_report(struct ata_link *link) dma_str[qc->dma_dir]); } - if (is_atapi_taskfile(&qc->tf)) + if (ata_is_atapi(qc->tf.protocol)) snprintf(cdb_buf, sizeof(cdb_buf), "cdb %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n ", -- cgit v1.2.3-70-g09d2 From e6a73ab1c8e814ac7b0d69f44fde63299b639489 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 13 Dec 2007 16:01:37 -0800 Subject: drivers/ata/libata-eh.c: fix printk warning drivers/ata/libata-eh.c: In function `ata_port_pbar_desc': drivers/ata/libata-eh.c:215: warning: long long unsigned int format, long unsigned int arg (arg 4) Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d7d5a5ae04e..1bc1acf3bbb 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -231,7 +231,8 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset, if (offset < 0) ata_port_desc(ap, "%s %s%llu@0x%llx", name, type, len, start); else - ata_port_desc(ap, "%s 0x%llx", name, start + offset); + ata_port_desc(ap, "%s 0x%llx", name, + start + (unsigned long long)offset); } #endif /* CONFIG_PCI */ -- cgit v1.2.3-70-g09d2 From 0dc36888d4422140f9eaf50f24953ec109f750a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 18 Dec 2007 16:34:43 -0500 Subject: libata: rename ATA_PROT_ATAPI_* to ATAPI_PROT_* ATA_PROT_ATAPI_* are ugly and naming schemes between ATA_PROT_* and ATA_PROT_ATAPI_* are inconsistent causing confusion. Rename them to ATAPI_PROT_* and make them consistent with ATA counterpart. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 28 ++++++++++++++-------------- drivers/ata/libata-eh.c | 8 ++++---- drivers/ata/libata-scsi.c | 10 +++++----- drivers/ata/libata-sff.c | 2 +- drivers/ata/pata_pdc202xx_old.c | 5 ++--- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_inic162x.c | 2 +- drivers/ata/sata_promise.c | 26 ++++++++++++-------------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sx4.c | 2 +- drivers/scsi/ipr.c | 6 +++--- drivers/scsi/libsas/sas_ata.c | 2 +- include/linux/ata.h | 12 ++++++------ 13 files changed, 52 insertions(+), 55 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c9e6bd4d068..2c9745a74d5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4678,8 +4678,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) */ static int atapi_qc_may_overflow(struct ata_queued_cmd *qc) { - if (qc->tf.protocol != ATA_PROT_ATAPI && - qc->tf.protocol != ATA_PROT_ATAPI_DMA) + if (qc->tf.protocol != ATAPI_PROT_PIO && + qc->tf.protocol != ATAPI_PROT_DMA) return 0; if (qc->tf.flags & ATA_TFLAG_WRITE) @@ -5161,13 +5161,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) ata_altstatus(ap); /* flush */ switch (qc->tf.protocol) { - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: ap->hsm_task_state = HSM_ST; break; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: ap->hsm_task_state = HSM_ST_LAST; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: ap->hsm_task_state = HSM_ST_LAST; /* initiate bmdma */ ap->ops->bmdma_start(qc); @@ -5518,7 +5518,7 @@ fsm_start: case HSM_ST: /* complete command or read/write the data register */ - if (qc->tf.protocol == ATA_PROT_ATAPI) { + if (qc->tf.protocol == ATAPI_PROT_PIO) { /* ATAPI PIO protocol */ if ((status & ATA_DRQ) == 0) { /* No more data to transfer or device error. @@ -6073,11 +6073,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_PIO: case ATA_PROT_NODATA: - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: qc->tf.flags |= ATA_TFLAG_POLLING; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) /* see ata_dma_blacklisted() */ BUG(); @@ -6141,8 +6141,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) break; - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: if (qc->tf.flags & ATA_TFLAG_POLLING) ata_qc_set_polling(qc); @@ -6156,7 +6156,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ata_port_queue_task(ap, ata_pio_task, qc, 0); break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING); ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ @@ -6217,7 +6217,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap, break; case HSM_ST_LAST: if (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA) { + qc->tf.protocol == ATAPI_PROT_DMA) { /* check status of DMA engine */ host_stat = ap->ops->bmdma_status(ap); VPRINTK("ata%u: host_stat 0x%X\n", @@ -6259,7 +6259,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap, ata_hsm_move(ap, qc, status, 0); if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA)) + qc->tf.protocol == ATAPI_PROT_DMA)) ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); return 1; /* irq handled */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 1bc1acf3bbb..419552603a1 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1299,10 +1299,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) /* is it pointless to prefer PIO for "safety reasons"? */ if (ap->flags & ATA_FLAG_PIO_DMA) { - tf.protocol = ATA_PROT_ATAPI_DMA; + tf.protocol = ATAPI_PROT_DMA; tf.feature |= ATAPI_PKT_DMA; } else { - tf.protocol = ATA_PROT_ATAPI; + tf.protocol = ATAPI_PROT_PIO; tf.lbam = SCSI_SENSE_BUFFERSIZE; tf.lbah = 0; } @@ -1979,8 +1979,8 @@ static void ata_eh_link_report(struct ata_link *link) [ATA_PROT_PIO] = "pio", [ATA_PROT_DMA] = "dma", [ATA_PROT_NCQ] = "ncq", - [ATA_PROT_ATAPI] = "pio", - [ATA_PROT_ATAPI_DMA] = "dma", + [ATAPI_PROT_PIO] = "pio", + [ATAPI_PROT_DMA] = "dma", }; snprintf(data_buf, sizeof(data_buf), " %s %u %s", diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 021cdc4cc26..5fd780e509d 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2354,10 +2354,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->tf.command = ATA_CMD_PACKET; if (ata_pio_use_silly(ap)) { - qc->tf.protocol = ATA_PROT_ATAPI_DMA; + qc->tf.protocol = ATAPI_PROT_DMA; qc->tf.feature |= ATAPI_PKT_DMA; } else { - qc->tf.protocol = ATA_PROT_ATAPI; + qc->tf.protocol = ATAPI_PROT_PIO; qc->tf.lbam = SCSI_SENSE_BUFFERSIZE; qc->tf.lbah = 0; } @@ -2528,12 +2528,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) if (using_pio || nodata) { /* no data, or PIO data xfer */ if (nodata) - qc->tf.protocol = ATA_PROT_ATAPI_NODATA; + qc->tf.protocol = ATAPI_PROT_NODATA; else - qc->tf.protocol = ATA_PROT_ATAPI; + qc->tf.protocol = ATAPI_PROT_PIO; } else { /* DMA data xfer */ - qc->tf.protocol = ATA_PROT_ATAPI_DMA; + qc->tf.protocol = ATAPI_PROT_DMA; qc->tf.feature |= ATAPI_PKT_DMA; if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE)) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index fd5fe4e7e75..edeb4bea586 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -417,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset, ap->hsm_task_state = HSM_ST_IDLE; if (qc && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATA_PROT_ATAPI_DMA)) { + qc->tf.protocol == ATAPI_PROT_DMA)) { u8 host_stat; host_stat = ap->ops->bmdma_status(ap); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 6c9689b59b0..3ed866723e0 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) pdc202xx_set_dmamode(ap, qc->dev); /* Cases the state machine will not complete correctly without help */ - if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATA_PROT_ATAPI_DMA) - { + if ((tf->flags & ATA_TFLAG_LBA48) || tf->protocol == ATAPI_PROT_DMA) { len = qc->nbytes / 2; if (tf->flags & ATA_TFLAG_WRITE) @@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no); /* Cases the state machine will not complete correctly */ - if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) { + if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) { iowrite32(0, atapi_reg); iowrite8(ioread8(clock) & ~sel66, clock); } diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index bd4c2a3c88d..459cb7bb7d7 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -455,7 +455,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc) adma_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 323c087e8cc..96e614a1c16 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = { }; static struct ata_port_info inic_port_info = { - /* For some reason, ATA_PROT_ATAPI is broken on this + /* For some reason, ATAPI_PROT_PIO is broken on this * controller, and no, PIO_POLLING does't fix it. It somehow * manages to report the wrong ireason and ignoring ireason * results in machine lock up. Tell libata to always prefer diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 9638faaa811..01738d736d4 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -456,13 +456,13 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) * and seq id (byte 2) */ switch (qc->tf.protocol) { - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: if (!(qc->tf.flags & ATA_TFLAG_WRITE)) buf32[0] = cpu_to_le32(PDC_PKT_READ); else buf32[0] = 0; break; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: buf32[0] = cpu_to_le32(PDC_PKT_NODATA); break; default: @@ -489,7 +489,7 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc) buf[19] = qc->tf.lbal; /* set feature and byte counter registers */ - if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) + if (qc->tf.protocol != ATAPI_PROT_DMA) feature = PDC_FEATURE_ATAPI_PIO; else feature = PDC_FEATURE_ATAPI_DMA; @@ -619,14 +619,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) pdc_pkt_footer(&qc->tf, pp->pkt, i); break; - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: pdc_fill_sg(qc); break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: pdc_fill_sg(qc); /*FALLTHROUGH*/ - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: pdc_atapi_pkt(qc); break; @@ -746,8 +746,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap, switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NODATA: - case ATA_PROT_ATAPI_DMA: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_DMA: + case ATAPI_PROT_NODATA: qc->err_mask |= ac_err_mask(ata_wait_idle(ap)); ata_qc_complete(qc); handled = 1; @@ -892,7 +892,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc) static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) { switch (qc->tf.protocol) { - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) break; /*FALLTHROUGH*/ @@ -900,7 +900,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_POLLING) break; /*FALLTHROUGH*/ - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: case ATA_PROT_DMA: pdc_packet_start(qc); return 0; @@ -914,16 +914,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc) static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON(tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); ata_tf_load(ap, tf); } static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { - WARN_ON(tf->protocol == ATA_PROT_DMA || - tf->protocol == ATA_PROT_ATAPI_DMA); + WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA); ata_exec_command(ap, tf); } diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index c68b241805f..4e5f07bdd06 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -376,7 +376,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) qs_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 4d857185f33..3de0c27caf5 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -700,7 +700,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc) pdc20621_packet_start(qc); return 0; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: BUG(); break; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 0841df01bc1..3e78bc2d917 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5222,12 +5222,12 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; break; - case ATA_PROT_ATAPI: - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_PIO: + case ATAPI_PROT_NODATA: regs->flags |= IPR_ATA_FLAG_PACKET_CMD; break; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: regs->flags |= IPR_ATA_FLAG_PACKET_CMD; regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; break; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 831294de1d8..f78d0605747 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -200,7 +200,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) case ATA_PROT_NCQ: task->ata_task.use_ncq = 1; /* fall through */ - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: case ATA_PROT_DMA: task->ata_task.dma_xfer = 1; break; diff --git a/include/linux/ata.h b/include/linux/ata.h index c17e9404c88..bc55471a4b2 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -341,9 +341,9 @@ enum ata_tf_protocols { ATA_PROT_PIO, /* PIO data xfer */ ATA_PROT_DMA, /* DMA */ ATA_PROT_NCQ, /* NCQ */ - ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ - ATA_PROT_ATAPI_NODATA, /* packet command, no data */ - ATA_PROT_ATAPI_DMA, /* packet command with special DMA sauce */ + ATAPI_PROT_NODATA, /* packet command, no data */ + ATAPI_PROT_PIO, /* packet command, PIO data xfer*/ + ATAPI_PROT_DMA, /* packet command with special DMA sauce */ }; enum ata_ioctls { @@ -395,11 +395,11 @@ static inline unsigned int ata_prot_flags(u8 prot) return ATA_PROT_FLAG_DMA; case ATA_PROT_NCQ: return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; - case ATA_PROT_ATAPI_NODATA: + case ATAPI_PROT_NODATA: return ATA_PROT_FLAG_ATAPI; - case ATA_PROT_ATAPI: + case ATAPI_PROT_PIO: return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; - case ATA_PROT_ATAPI_DMA: + case ATAPI_PROT_DMA: return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; } return 0; -- cgit v1.2.3-70-g09d2 From 75f9cafc2d24a1cf44d7c3f3e5b4f7a393afcf71 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 3 Jan 2008 01:21:14 +0900 Subject: libata: fix off-by-one in error categorization ATA_ECAT_DUBIOUS_BASE was too high by one and thus all DUBIOUS error categorizations were wrong. This passed test because only ATA_BUS and UNK_DEV were used during testing and the ones after them - ATA_BUS and an overflowed entry - behaved similarly. This patch fixes the problem by adding DUBIOUS_NONE category and use it as base. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/ata/libata-eh.c') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 419552603a1..4e31071acc0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -61,12 +61,11 @@ enum { ATA_ECAT_ATA_BUS = 1, ATA_ECAT_TOUT_HSM = 2, ATA_ECAT_UNK_DEV = 3, - ATA_ECAT_DUBIOUS_ATA_BUS = 4, - ATA_ECAT_DUBIOUS_TOUT_HSM = 5, - ATA_ECAT_DUBIOUS_UNK_DEV = 6, - ATA_ECAT_NR = 7, - - ATA_ECAT_DUBIOUS_BASE = ATA_ECAT_DUBIOUS_ATA_BUS, + ATA_ECAT_DUBIOUS_NONE = 4, + ATA_ECAT_DUBIOUS_ATA_BUS = 5, + ATA_ECAT_DUBIOUS_TOUT_HSM = 6, + ATA_ECAT_DUBIOUS_UNK_DEV = 7, + ATA_ECAT_NR = 8, }; /* Waiting in ->prereset can never be reliable. It's sometimes nice @@ -1499,7 +1498,7 @@ static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask, *xfer_ok = 1; if (!*xfer_ok) - base = ATA_ECAT_DUBIOUS_BASE; + base = ATA_ECAT_DUBIOUS_NONE; if (err_mask & AC_ERR_ATA_BUS) return base + ATA_ECAT_ATA_BUS; -- cgit v1.2.3-70-g09d2