Date: Tue, 29 Apr 1997 10:37:15 -0600 From: "Justin T. Gibbs" <gibbs@plutotech.com> To: "David O'Brien" <obrien@NUXI.com> Cc: gibbs@freebsd.org, stable@freebsd.org Subject: Re: AHA-2940U problem in -STABLE Message-ID: <199704291538.JAA27224@pluto.plutotech.com> In-Reply-To: Your message of "Tue, 29 Apr 1997 01:49:44 PDT." <19970429014944.36331@dragon.nuxi.com>
next in thread | previous in thread | raw e-mail | index | archive | help
>Hi Justin,
>
>I'm having a little problem with my AHA-2940. I can no longer use my
>Exbyte 8505 8mm drive to back up my SCSI hard drive. Using a 2.2-STABLE
>kernel in single user mode from 4/24 I got:
>
>
>DUMP: 91.33% done, finished in 0:03
>st0(ahc0:4:0): SCB 0x2 - timeed out while idle, LASTPHASE == 0x1, SCSISIGI ==
>0x0
>SEQADDR == 0x8
My guess is that you are using the rewindind device and that the rewind is
taking longer than the st driver allows (5 minutes I think) causing the
initial timeout. This is the first problem.
>st0(ahc0:4:0): Queueing an Abort SCB
>st0(ahc0:4:0): Abort Mesasge sent
>st0(ahc0:4:0): SCB 2 - Abort Completed
>st0(ahc0:4:0): no longer in timeout
>DUMP: End of tape detected
>sd0(ahc0:0:0): SCB 0x1 - timed out in message out phase, SCSISIGI == 0x0
>SEQADDR == 0x0
>sd0(ahc0:0:0): SCB 1: Yucky Immediate reset. Flags = 0x1
>sd0(ahc0:0:0): no longer in timeout
>sd0(ahc0:0:0): Issued Channel A Bus Reset. 3 SCBs aborted.
>
>
>And then the machine froze (not even a panic).
This is bug #2. For some reason, the recovery code is botching it. Can
you try the attached patch and see if the recovery code behaves correctly?
Once I get the recovery code to work for you, you should be able to bump
up the timeout in scsi/st.c:st_rewind and make the problem completly go
away.
>Note, that Dump shouldn't
>have detected EOT as I was dumping a 2gig partition on a tape that should
>hold 5gig minium. I've used this tape to backup the SCSI drive before,
>even while multiuser. So I think it has something to do with an aic7xxx
>change. Maybe?
My guess is that you have more data to dump now, making the rewind take
longer, which is why you are just now running into this problem.
>--
>-- David (obrien@NUXI.com -or- obrien@FreeBSD.org)
--
Justin T. Gibbs
===========================================
FreeBSD: Turning PCs into workstations
===========================================
Index: i386/scsi/aic7xxx.c
===================================================================
RCS file: /usr/cvs/src/sys/i386/scsi/aic7xxx.c,v
retrieving revision 1.118
diff -c -r1.118 aic7xxx.c
*** aic7xxx.c 1997/04/26 05:03:18 1.118
--- aic7xxx.c 1997/04/29 16:31:33
***************
*** 178,191 ****
int unpause_always));
static inline void restart_sequencer __P((struct ahc_softc *ahc));
- static int timeouts_work; /*
- * Boolean that lets the driver know
- * that it can safely use timeouts
- * for event scheduling. Timeouts
- * don't work early in the boot
- * process.
- */
-
#define AHC_BUSRESET_DELAY 1000 /* Reset delay in us */
#define AHC_BUSSETTLE_DELAY (100 * 1000)/* Delay before taking commands
* after a reset in us
--- 178,183 ----
***************
*** 308,314 ****
static void ahc_clear_intstat __P((struct ahc_softc *ahc));
static void ahc_reset_current_bus __P((struct ahc_softc *ahc));
static void ahc_run_done_queue __P((struct ahc_softc *ahc));
- static void ahc_untimeout_done_queue __P((struct ahc_softc *ahc));
static void ahc_scsirate __P((struct ahc_softc* ahc, u_int8_t *scsirate,
u_int8_t *period, u_int8_t *offset,
char channel, int target));
--- 300,305 ----
***************
*** 319,333 ****
static void ahc_timeout __P((void *));
#endif
- static timeout_t
- ahc_first_timeout;
-
- static timeout_t
- ahc_busreset_complete;
-
- static timeout_t
- ahc_busreset_settle_complete;
-
static u_int8_t ahc_index_busy_target __P((struct ahc_softc *ahc, int target,
char channel, int unbusy));
--- 310,315 ----
***************
*** 489,500 ****
ahc->flags = flags;
ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
ahc->pause = ahc->unpause | PAUSE;
-
- ahc->busreset_args.ahc = ahc;
- ahc->busreset_args.bus = 'A';
- ahc->busreset_args_b.ahc = ahc;
- ahc->busreset_args_b.bus = 'B';
-
#if defined(__FreeBSD__)
return (ahc);
#endif
--- 471,476 ----
***************
*** 2326,2334 ****
unpause_sequencer(ahc, /*unpause_always*/TRUE);
- /* Notify us when the system can handle timeouts */
- timeout(ahc_first_timeout, NULL, 0);
-
/*
* Note that we are going and return (to probe)
*/
--- 2302,2307 ----
***************
*** 2377,2399 ****
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
flags = xs->flags;
- if (ahc->in_reset != 0) {
- /*
- * If we are still in a reset, send the transaction
- * back indicating that it was aborted due to a
- * reset.
- */
- if ((IS_SCSIBUS_B(ahc, xs->sc_link)
- && (ahc->in_reset & CHANNEL_B_RESET) != 0)
- || (!IS_SCSIBUS_B(ahc, xs->sc_link)
- && (ahc->in_reset & CHANNEL_A_RESET) != 0)) {
- /* Ick, but I don't want it to abort this */
- xs->retries++;
- xs->error = XS_BUSY;
- return(COMPLETE);
- }
- }
-
/*
* get an scb to use. If the transfer
* is from a buf (possibly from interrupt time)
--- 2350,2355 ----
***************
*** 2893,2911 ****
return (0);
}
- /*
- * Handler to register that the system is capable of
- * delivering timeouts. We register this timeout in
- * ahc_init and it should go off as soon as we're through
- * the boot process.
- */
- static void
- ahc_first_timeout(arg)
- void *arg;
- {
- timeouts_work = 1;
- }
-
static void
ahc_timeout(arg)
void *arg;
--- 2849,2854 ----
***************
*** 3654,3714 ****
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
scsiseq = ahc_inb(ahc, SCSISEQ);
ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
! if (timeouts_work != 0) {
! struct ahc_busreset_args *args;
!
! sblkctl = ahc_inb(ahc, SBLKCTL);
! args = (sblkctl & SELBUSB) ? &ahc->busreset_args_b
! : &ahc->busreset_args;
! ahc->in_reset |= (args->bus == 'A' ? CHANNEL_A_RESET
! : CHANNEL_B_RESET);
! timeout(ahc_busreset_complete, args,
! MAX((AHC_BUSRESET_DELAY * hz) / 1000000, 1));
! } else {
! DELAY(AHC_BUSRESET_DELAY);
! /* Turn off the bus reset */
! ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
!
! ahc_clear_intstat(ahc);
!
! /* Re-enable reset interrupts */
! ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
!
! /* Wait a minimal bus settle delay */
! DELAY(AHC_BUSSETTLE_DELAY);
!
! ahc_run_done_queue(ahc);
! }
! }
!
! static void
! ahc_busreset_complete(arg)
! void *arg;
! {
! struct ahc_busreset_args *args;
! struct ahc_softc *ahc;
! int s;
! u_int8_t scsiseq;
! u_int8_t sblkctl;
!
! args = (struct ahc_busreset_args *)arg;
! ahc = (struct ahc_softc *)args->ahc;
!
! s = splbio();
! pause_sequencer(ahc);
!
! /* Save the current block control state */
! sblkctl = ahc_inb(ahc, SBLKCTL);
!
! /* Switch to the right bus */
! if (args->bus == 'A')
! ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
! else
! ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
!
/* Turn off the bus reset */
- printf("Clearing bus reset\n");
- scsiseq = ahc_inb(ahc, SCSISEQ);
ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
ahc_clear_intstat(ahc);
--- 3597,3604 ----
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
scsiseq = ahc_inb(ahc, SCSISEQ);
ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
! DELAY(AHC_BUSRESET_DELAY);
/* Turn off the bus reset */
ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
ahc_clear_intstat(ahc);
***************
*** 3716,3752 ****
/* Re-enable reset interrupts */
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
! /*
! * Set a 100ms timeout to clear our in_reset flag.
! * It will be *at-least* that long before any targets
! * respond to real commands on the bus.
! */
! timeout(ahc_busreset_settle_complete, args,
! (AHC_BUSSETTLE_DELAY * hz) / 1000000);
!
! /* Restore the original channel */
! ahc_outb(ahc, SBLKCTL, sblkctl);
! unpause_sequencer(ahc, /*unpause_always*/FALSE);
! splx(s);
! }
!
! static void
! ahc_busreset_settle_complete(arg)
! void *arg;
! {
! struct ahc_busreset_args *args;
! struct ahc_softc *ahc;
! int s;
!
! args = (struct ahc_busreset_args *)arg;
! ahc = (struct ahc_softc *)args->ahc;
! /* Clear the reset flag */
! s = splbio();
! printf("Clearing 'in-reset' flag\n");
! ahc->in_reset &= (args->bus == 'A' ? ~CHANNEL_A_RESET
! : ~CHANNEL_B_RESET);
! ahc_run_done_queue(ahc);
! splx(s);
}
static int
--- 3606,3613 ----
/* Re-enable reset interrupts */
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
! /* Wait a minimal bus settle delay */
! DELAY(AHC_BUSSETTLE_DELAY);
}
static int
***************
*** 3831,3848 ****
ahc_clear_intstat(ahc);
restart_sequencer(ahc);
}
! /*
! * Untimeout our scbs now in case we have to delay our done
! * processing.
! */
! ahc_untimeout_done_queue(ahc);
! if (initiate_reset == 0) {
! /*
! * If we initiated the reset, we'll run the queue
! * once our bus-settle delay has expired.
! */
! ahc_run_done_queue(ahc);
! }
return found;
}
--- 3692,3698 ----
ahc_clear_intstat(ahc);
restart_sequencer(ahc);
}
! ahc_run_done_queue(ahc);
return found;
}
***************
*** 3860,3879 ****
}
}
- static void
- ahc_untimeout_done_queue(ahc)
- struct ahc_softc *ahc;
- {
- int i;
- struct scb *scbp;
-
- for (i = 0; i < ahc->scb_data->numscbs; i++) {
- scbp = ahc->scb_data->scbarray[i];
- if (scbp->flags & SCB_QUEUED_FOR_DONE)
- untimeout(ahc_timeout, (caddr_t)scbp);
- }
- }
-
static int
ahc_match_scb (scb, target, channel, lun, tag)
struct scb *scb;
--- 3710,3715 ----
Index: i386/scsi/aic7xxx.h
===================================================================
RCS file: /usr/cvs/src/sys/i386/scsi/aic7xxx.h,v
retrieving revision 1.40
diff -c -r1.40 aic7xxx.h
*** aic7xxx.h 1997/02/25 03:05:35 1.40
--- aic7xxx.h 1997/04/29 16:28:40
***************
*** 228,238 ****
*/
};
- struct ahc_busreset_args {
- struct ahc_softc *ahc;
- char bus;
- };
-
struct ahc_softc {
#if defined(__FreeBSD__)
int unit;
--- 228,233 ----
***************
*** 249,256 ****
#endif
volatile u_int8_t *maddr;
struct scb_data *scb_data;
- struct ahc_busreset_args busreset_args;
- struct ahc_busreset_args busreset_args_b;
struct scsi_link sc_link;
struct scsi_link sc_link_b; /* Second bus for Twin channel cards */
STAILQ_HEAD(, scb) waiting_scbs;/*
--- 244,249 ----
***************
*** 289,297 ****
u_int8_t unpause;
u_int8_t pause;
u_int8_t in_timeout;
- u_int8_t in_reset;
- #define CHANNEL_A_RESET 0x01
- #define CHANNEL_B_RESET 0x02
};
struct full_ahc_softc {
--- 282,287 ----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199704291538.JAA27224>
