From: Jens Axboe <axboe@suse.de>
To: "Axel H. Siebenwirth" <axel@hh59.org>
Cc: Anton Altaparmakov <aia21@cam.ac.uk>, linux-kernel@vger.kernel.org
Subject: Re: 2.5.3 - (IDE) hda: drive not ready for command errors
Date: Sat, 2 Feb 2002 10:26:59 +0100 [thread overview]
Message-ID: <20020202102659.L12156@suse.de> (raw)
In-Reply-To: <20020201153303.A1508@prester.hh59.org> <5.1.0.14.2.20020201160018.026603b0@pop.cus.cam.ac.uk> <20020201164813.GA14296@neon>
In-Reply-To: <20020201164813.GA14296@neon>
On Fri, Feb 01 2002, Axel H. Siebenwirth wrote:
> Hi Anton!
>
> On Fri, 01 Feb 2002, Anton Altaparmakov wrote:
>
> > I was about to send the drive (IBM 7200rpm 41GiB) back for replacement when
> > I as last resort tried to upgrade the firmware of the drive.
> >
> > After the upgrade the drive started working again, fully passed the Drive
> > Fitness Test (IBM utility) and it has been working for a few weeks non-stop
> > in my file server RAID-1 array since then.
>
> The thing is that they come up now, just since I installed 2.5.3. Might
> there be a hope that it is a kernel-related issue (new IDE driver...). Drive
> has been working fine ever since till now.
Please try with this patch -- it's against 2.5.3-pre3, but I think it
should apply to 2.5.3 final as well.
diff -ur /ata/linux-2.5.3-pre3/drivers/ide/ide-disk.c drivers/ide/ide-disk.c
--- /ata/linux-2.5.3-pre3/drivers/ide/ide-disk.c Fri Jan 25 05:05:06 2002
+++ drivers/ide/ide-disk.c Fri Jan 25 02:53:03 2002
@@ -192,11 +192,6 @@
sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
- if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
- sectors = drive->mult_count;
- if (sectors > rq->current_nr_sectors)
- sectors = rq->current_nr_sectors;
- }
taskfile.sector_count = sectors;
taskfile.sector_number = sect;
@@ -241,11 +236,6 @@
sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
- if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
- sectors = drive->mult_count;
- if (sectors > rq->current_nr_sectors)
- sectors = rq->current_nr_sectors;
- }
memset(&taskfile, 0, sizeof(task_struct_t));
memset(&hobfile, 0, sizeof(hob_struct_t));
@@ -300,13 +290,8 @@
memset(&hobfile, 0, sizeof(hob_struct_t));
sectors = rq->nr_sectors;
- if (sectors == 256)
+ if (sectors == 65536)
sectors = 0;
- if (command == WIN_MULTWRITE_EXT || command == WIN_MULTWRITE) {
- sectors = drive->mult_count;
- if (sectors > rq->current_nr_sectors)
- sectors = rq->current_nr_sectors;
- }
taskfile.sector_count = sectors;
hobfile.sector_count = sectors >> 8;
diff -ur /ata/linux-2.5.3-pre3/drivers/ide/ide-probe.c drivers/ide/ide-probe.c
--- /ata/linux-2.5.3-pre3/drivers/ide/ide-probe.c Fri Jan 25 05:05:06 2002
+++ drivers/ide/ide-probe.c Fri Jan 25 04:46:26 2002
@@ -625,7 +625,7 @@
blk_queue_segment_boundary(q, 0xffff);
/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
- max_sectors = (is_pdc4030_chipset ? 127 : 255);
+ max_sectors = (is_pdc4030_chipset ? 127 : 256);
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
diff -ur /ata/linux-2.5.3-pre3/drivers/ide/ide-taskfile.c drivers/ide/ide-taskfile.c
--- /ata/linux-2.5.3-pre3/drivers/ide/ide-taskfile.c Fri Jan 25 05:05:06 2002
+++ drivers/ide/ide-taskfile.c Fri Jan 25 04:45:48 2002
@@ -255,6 +255,7 @@
return 1; /* drive ready: *might* be interrupting */
}
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive);
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
@@ -263,7 +264,7 @@
byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
/* (ks/hs): Moved to start, do not use for multiple out commands */
- if (task->handler != task_mulout_intr) {
+ if (task->handler != task_mulout_intr && task->handler != bio_mulout_intr) {
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(HWIF(drive), drive, 0);
@@ -313,7 +314,7 @@
byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
/* (ks/hs): Moved to start, do not use for multiple out commands */
- if (*handler != task_mulout_intr) {
+ if (*handler != task_mulout_intr && handler != bio_mulout_intr) {
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(HWIF(drive), drive, 0);
@@ -936,15 +937,12 @@
char *pBuf = NULL;
unsigned long flags;
- if (!rq->current_nr_sectors) {
- printk("task_out_intr: should not trigger\n");
- ide_end_request(1, HWGROUP(drive));
- return ide_stopped;
- }
-
- if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
+ if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat))
return ide_error(drive, "task_out_intr", stat);
- }
+
+ if (!rq->current_nr_sectors)
+ if (!ide_end_request(1, HWGROUP(drive)))
+ return ide_stopped;
if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
rq = HWGROUP(drive)->rq;
@@ -958,16 +956,8 @@
rq->current_nr_sectors--;
}
- if (rq->current_nr_sectors <= 0) {
- if (ide_end_request(1, HWGROUP(drive))) {
- ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- } else {
- ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL);
- return ide_started;
- }
- return ide_stopped;
+ ide_set_handler(drive, task_out_intr, WAIT_CMD, NULL);
+ return ide_started;
}
/*
@@ -1061,14 +1051,132 @@
return ide_started;
}
+ide_startstop_t pre_bio_out_intr (ide_drive_t *drive, struct request *rq)
+{
+ ide_task_t *args = rq->special;
+ ide_startstop_t startstop;
+
+ /*
+ * assign private copy for multi-write
+ */
+ memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
+
+ if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
+ return startstop;
+
+ /*
+ * (ks/hs): Stuff the first sector(s)
+ * by implicitly calling the handler
+ */
+ if (!(drive_is_ready(drive))) {
+ int i;
+ /*
+ * (ks/hs): FIXME: Replace hard-coded
+ * 100, error handling?
+ */
+ for (i=0; i<100; i++) {
+ if (drive_is_ready(drive))
+ break;
+ }
+ }
+
+ return args->handler(drive);
+}
+
+
+ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
+{
+#ifdef ALTSTAT_SCREW_UP
+ byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write");
+#else
+ byte stat = GET_STAT();
+#endif /* ALTSTAT_SCREW_UP */
+
+ byte io_32bit = drive->io_32bit;
+ struct request *rq = &HWGROUP(drive)->wrq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ int mcount = drive->mult_count;
+ ide_startstop_t startstop;
+
+ /*
+ * (ks/hs): Handle last IRQ on multi-sector transfer,
+ * occurs after all data was sent in this chunk
+ */
+ if (!rq->nr_sectors) {
+ if (stat & (ERR_STAT|DRQ_STAT)) {
+ startstop = ide_error(drive, "bio_mulout_intr", stat);
+ memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+ return startstop;
+ }
+
+ __ide_end_request(HWGROUP(drive), 1, rq->hard_nr_sectors);
+ HWGROUP(drive)->wrq.bio = NULL;
+ return ide_stopped;
+ }
+
+ if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+ if (stat & (ERR_STAT | DRQ_STAT)) {
+ startstop = ide_error(drive, "bio_mulout_intr", stat);
+ memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+ return startstop;
+ }
+
+ /* no data yet, so wait for another interrupt */
+ if (hwgroup->handler == NULL)
+ ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+ return ide_started;
+ }
+
+ do {
+ char *buffer;
+ int nsect = rq->current_nr_sectors;
+ unsigned long flags;
+
+ if (nsect > mcount)
+ nsect = mcount;
+ mcount -= nsect;
+
+ buffer = ide_map_buffer(rq, &flags);
+ rq->sector += nsect;
+ rq->nr_sectors -= nsect;
+ rq->current_nr_sectors -= nsect;
+
+ /* Do we move to the next bio after this? */
+ if (!rq->current_nr_sectors) {
+ /* remember to fix this up /jens */
+ struct bio *bio = rq->bio->bi_next;
+
+ /* end early early we ran out of requests */
+ if (!bio) {
+ mcount = 0;
+ } else {
+ rq->bio = bio;
+ rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+ }
+ }
+
+ /*
+ * Ok, we're all setup for the interrupt
+ * re-entering us on the last transfer.
+ */
+ taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
+ ide_unmap_buffer(buffer, &flags);
+ } while (mcount);
+
+ drive->io_32bit = io_32bit;
+ rq->errors = 0;
+ if (hwgroup->handler == NULL)
+ ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
+
+ return ide_started;
+}
+
/* Called by internal to feature out type of command being called */
ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile)
{
switch(taskfile->command) {
/* IDE_DRIVE_TASK_RAW_WRITE */
- case CFA_WRITE_MULTI_WO_ERASE:
- case WIN_MULTWRITE:
- case WIN_MULTWRITE_EXT:
/* IDE_DRIVE_TASK_OUT */
case WIN_WRITE:
case WIN_WRITE_EXT:
@@ -1077,7 +1185,10 @@
case CFA_WRITE_SECT_WO_ERASE:
case WIN_DOWNLOAD_MICROCODE:
return &pre_task_out_intr;
- /* IDE_DRIVE_TASK_OUT */
+ case CFA_WRITE_MULTI_WO_ERASE:
+ case WIN_MULTWRITE:
+ case WIN_MULTWRITE_EXT:
+ return &pre_bio_out_intr;
case WIN_SMART:
if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
return &pre_task_out_intr;
@@ -1120,7 +1231,7 @@
case CFA_WRITE_MULTI_WO_ERASE:
case WIN_MULTWRITE:
case WIN_MULTWRITE_EXT:
- return &task_mulout_intr;
+ return &bio_mulout_intr;
case WIN_SMART:
switch(taskfile->feature) {
case SMART_READ_VALUES:
--
Jens Axboe
next prev parent reply other threads:[~2002-02-02 9:27 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-02-01 14:33 2.5.3 - (IDE) hda: drive not ready for command errors axel
2002-02-01 16:06 ` Anton Altaparmakov
2002-02-01 16:48 ` Axel H. Siebenwirth
2002-02-01 17:52 ` Andreas Dilger
2002-02-02 2:44 ` Anton Altaparmakov
2002-02-02 9:26 ` Jens Axboe [this message]
2002-02-02 19:10 ` Axel H. Siebenwirth
2002-02-02 21:48 ` Andre Hedrick
2002-02-02 23:28 ` Jens Axboe
2002-02-02 23:58 ` Jens Axboe
2002-02-05 15:32 ` Holger Lubitz
2002-02-05 16:09 ` Anton Altaparmakov
2002-02-05 16:57 ` Holger Lubitz
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=20020202102659.L12156@suse.de \
--to=axboe@suse.de \
--cc=aia21@cam.ac.uk \
--cc=axel@hh59.org \
--cc=linux-kernel@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox