From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
To: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Suleiman Souhlal <ssouhlal@freebsd.org>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
Alan Cox <alan@redhat.com>
Subject: Re: [PATCH 3/3] Use correct IDE error recovery
Date: Sat, 24 Mar 2007 17:07:13 +0300 [thread overview]
Message-ID: <46053091.9090307@ru.mvista.com> (raw)
In-Reply-To: <200703240053.42845.bzolnier@gmail.com>
Hello.
Bartlomiej Zolnierkiewicz wrote:
> Since I think that it's worth to have it in 2.6.21-final and respin didn't
> happen I did the required changes myself (it also turned out that I missed
> few things during initial review), then applied the patch...
> Please let my know whether you are fine with my changes, thanks.
> [PATCH] ide: use correct IDE error recovery
> From: Suleiman Souhlal <suleiman@google.com>
> IDE error recovery is using IDLE IMMEDIATE if the drive is busy or has DRQ set.
> This violates the ATA spec (can only send IDLE IMMEDIATE when drive is not
> busy) and really hoses up some drives (modern drives will not be able to
I wonder if that really ever worked...
> recover using this error handling). The correct thing to do is issue a SRST
> followed by a SET FEATURES command. This is what Western Digital recommends
> for error recovery and what Western Digital says Windows does. It also does
> not violate the ATA spec as far as I can tell.
The patch even does things *not* required by the spec. :-)
> Index: b/drivers/ide/ide-io.c
> ===================================================================
> --- a/drivers/ide/ide-io.c
> +++ b/drivers/ide/ide-io.c
> @@ -519,21 +519,24 @@ static ide_startstop_t ide_ata_error(ide
> if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && hwif->err_stops_fifo == 0)
> try_to_flush_leftover_data(drive);
>
> + if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
> + ide_kill_rq(drive, rq);
> + return ide_stopped;
> + }
> +
> if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
> - /* force an abort */
> - hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
> + rq->errors |= ERROR_RESET;
>
> - if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
> - ide_kill_rq(drive, rq);
> - else {
> - if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
> - ++rq->errors;
> - return ide_do_reset(drive);
> - }
> - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
> - drive->special.b.recalibrate = 1;
> + if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
> ++rq->errors;
> + return ide_do_reset(drive);
> }
> +
> + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
Hm, is there any need for ==?
> + drive->special.b.recalibrate = 1;
> +
> + ++rq->errors;
> +
> return ide_stopped;
> }
>
> @@ -1025,6 +1028,13 @@ static ide_startstop_t start_request (id
> if (!drive->special.all) {
> ide_driver_t *drv;
>
> + /*
> + * We reset the drive so we need to issue a SETFEATURES.
> + * Do it _after_ do_special() restored device parameters.
> + */
> + if (drive->current_speed == 0xff)
> + ide_config_drive_speed(drive, drive->desired_speed);
> +
Hmm, IIRC, drive's UltraDMA mode shall *not* be cleared by reset,
therefore there's no need to restore it.
> if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
> rq->cmd_type == REQ_TYPE_ATA_TASK ||
> rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
> Index: b/drivers/ide/ide-iops.c
> ===================================================================
> --- a/drivers/ide/ide-iops.c
> +++ b/drivers/ide/ide-iops.c
> @@ -1094,6 +1094,9 @@ static void pre_reset(ide_drive_t *drive
> if (HWIF(drive)->pre_reset != NULL)
> HWIF(drive)->pre_reset(drive);
>
> + if (drive->current_speed != 0xff)
> + drive->desired_speed = drive->current_speed;
> + drive->current_speed = 0xff;
> }
> /*
> Index: b/include/linux/ide.h
> ===================================================================
> --- a/include/linux/ide.h
> +++ b/include/linux/ide.h
> @@ -615,6 +615,7 @@ typedef struct ide_drive_s {
> u8 init_speed; /* transfer rate set at boot */
> u8 pio_speed; /* unused by core, used by some drivers for fallback from DMA */
> u8 current_speed; /* current transfer rate set */
> + u8 desired_speed; /* desired transfer rate set */
Oh, more of that *_speed crap. :-)
> u8 dn; /* now wide spread use */
> u8 wcache; /* status of write cache */
> u8 acoustic; /* acoustic management */
MBR, Sergei
prev parent reply other threads:[~2007-03-24 14:06 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-21 1:23 [PATCH 3/3] Use correct IDE error recovery Suleiman Souhlal
2007-03-07 21:16 ` Bartlomiej Zolnierkiewicz
2007-03-08 1:05 ` Alan Cox
2007-03-08 20:16 ` Suleiman Souhlal
2007-03-08 20:34 ` Bartlomiej Zolnierkiewicz
2007-03-08 20:53 ` Suleiman Souhlal
2007-03-23 23:53 ` Bartlomiej Zolnierkiewicz
2007-03-24 14:07 ` Sergei Shtylyov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46053091.9090307@ru.mvista.com \
--to=sshtylyov@ru.mvista.com \
--cc=alan@redhat.com \
--cc=bzolnier@gmail.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ssouhlal@freebsd.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.