Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Mar 2003 00:42:27 +0100
From:      Thomas Stratmann <strattbo@fsp1.physik.ruhr-uni-bochum.de>
To:        stable@freebsd.org
Subject:   hard read/write error workaround (and: fallback brand elf works)
Message-ID:  <20030305004227.A6054@fsp1.physik.ruhr-uni-bochum.de>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello everyone,

to start with, I was wrong before today on the kern.fallback_elf_brand
issue. It works for me, I just forgot to kldload linux before. Sorry for
that.

Now to the biggie: my ata symptoms seem as I already mentioned, when waking
up from disk hibernation the very first (and all following) disk access will
fail, so tons of hard ... error messages run down my screen. I already
mentioned my 'leave the atacontrol cmdline on a rootshell' workaround, but
this is really inconvenient.

I am proud to present what is just a bad hack that sort of works for me.
I went into ata-disk.h/c and made count the PIO errors, and as soon as the
fourth is encountered, ad_reinit is called. No spooky messages any more.
For anyone who wants to test for whatever crazy reasons (the only sensible
one would be you have the same symptom), beware that these first four accesses
acually fail hard, with whatever consequences this has. Can't help, but
I thought counting errors would be a good idea instead of resetting
instantly.

Patches are attached, have fun.

Yours
Thomas Stratmann

P.S. The ext2fsprogs issue is still unresolved, people who get it working
send me mail please!

[-- Attachment #2 --]
*** ata-disk.h	Tue Mar  4 23:07:40 2003
--- ata-disk.h.bak	Tue Mar  4 23:06:33 2003
***************
*** 74,82 ****
      struct devstat		stats;		/* devstat entry */
      struct disk			disk;		/* disklabel/slice stuff */
      dev_t			dev;		/* device place holder */
- /********patch********/
-     int				pioerrs;	/* non-dma error count */
- /********patch********/
  };
  
  void ad_attach(struct ata_device *);
--- 74,79 ----

[-- Attachment #3 --]
*** ata-disk.c	Wed Mar  5 00:14:19 2003
--- ata-disk.c.bak	Tue Mar  4 20:50:23 2003
***************
*** 649,686 ****
      if (request->flags & ADR_F_FORCE_PIO && !(request->flags & ADR_F_ERROR))
  	ata_prtdev(adp->device, "DMA problem fallback to PIO mode\n");
  
! /************patch**********/
!     /* was this a PIO operation? */
!     if (!(request->flags & ADR_F_DMA_USED)) {
!     	/* PIO read -> get the data */
! 	if ((request->flags & (ADR_F_READ | ADR_F_ERROR)) == ADR_F_READ) {
! 		/* ready to receive data? */
! 		if ((adp->device->channel->status & (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))
! 		    != (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))
! 		    ata_prtdev(adp->device, "read interrupt arrived early");
  
! 		if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != 0) {
! 		    ata_prtdev(adp->device, "read error detected (too) late");
! 		    request->flags |= ADR_F_ERROR;
! 		}
! 		else {
! 		    /* data ready, read in */
! 		    if (adp->device->channel->flags & ATA_USE_16BIT)
! 			ATA_INSW(adp->device->channel->r_io, ATA_DATA,
! 				 (void*)((uintptr_t)request->data + request->donecount),
! 				 request->currentsize / sizeof(int16_t));
! 		    else
! 			ATA_INSL(adp->device->channel->r_io, ATA_DATA,
! 				 (void*)((uintptr_t)request->data + request->donecount),
! 				 request->currentsize / sizeof(int32_t));
! 		}
!     	} else if (request->flags & ADR_F_ERROR) { /* failure */
! 		if (++adp->pioerrs >= 4) {
! 			adp->pioerrs = 0;
! 			printf("PIO error count >= 4 for this disk, ");
! 			printf("calling reinit...\n");
! 			ad_reinit(adp->device);
! 		}
  	}
      }
  
--- 649,677 ----
      if (request->flags & ADR_F_FORCE_PIO && !(request->flags & ADR_F_ERROR))
  	ata_prtdev(adp->device, "DMA problem fallback to PIO mode\n");
  
!     /* if this was a PIO read operation, get the data */
!     if (!(request->flags & ADR_F_DMA_USED) &&
! 	(request->flags & (ADR_F_READ | ADR_F_ERROR)) == ADR_F_READ) {
  
! 	/* ready to receive data? */
! 	if ((adp->device->channel->status & (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))
! 	    != (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ))
! 	    ata_prtdev(adp->device, "read interrupt arrived early");
! 
! 	if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != 0) {
! 	    ata_prtdev(adp->device, "read error detected (too) late");
! 	    request->flags |= ADR_F_ERROR;
! 	}
! 	else {
! 	    /* data ready, read in */
! 	    if (adp->device->channel->flags & ATA_USE_16BIT)
! 		ATA_INSW(adp->device->channel->r_io, ATA_DATA,
! 			 (void*)((uintptr_t)request->data + request->donecount),
! 			 request->currentsize / sizeof(int16_t));
! 	    else
! 		ATA_INSL(adp->device->channel->r_io, ATA_DATA,
! 			 (void*)((uintptr_t)request->data + request->donecount),
! 			 request->currentsize / sizeof(int32_t));
  	}
      }
  

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030305004227.A6054>