Subject: Re: sdX: not queued, error 5
To: Michael L. VanLoon -- HeadCandy.com <michaelv@mindbender.serv.net>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-kern
Date: 03/11/1997 14:05:40
On Tue, 11 Mar 1997 07:26:33 -0800
"Michael L. VanLoon -- HeadCandy.com" <michaelv@MindBender.serv.net> wrote:
> Is there any way to get rid of these with the ahc driver?
I fixed this in -current quite some time ago. Attached below are
the changes I commited to -current. They should be easy to back-port
to the 1.2 driver.
(In the Very Soon To Be Released, No Really, NetBSD 1.2 patch 1, the
-current driver has been pulled up into the branch. But this should
do until that's released.)
Jason R. Thorpe thorpej@nas.nasa.gov
NASA Ames Research Center Home: 408.866.1912
NAS: M/S 258-6 Work: 415.604.0935
Moffett Field, CA 94035 Pager: 415.428.6939
Index: aic7xxx.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/aic7xxx.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -c -r1.17 -r1.18
*** aic7xxx.c 1996/10/21 22:34:04 1.17
--- aic7xxx.c 1996/12/02 19:06:41 1.18
***************
*** 1,4 ****
! /* $NetBSD: aic7xxx.c,v 1.17 1996/10/21 22:34:04 thorpej Exp $ */
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
--- 1,4 ----
! /* $NetBSD: aic7xxx.c,v 1.18 1996/12/02 19:06:41 thorpej Exp $ */
/*
* Generic driver for the aic7xxx based adaptec SCSI controllers
***************
*** 325,330 ****
--- 325,336 ----
static void ahc_construct_wdtr __P((struct ahc_data *ahc, int start_byte,
u_int8_t bus_width));
+ #if defined(__NetBSD__) /* XXX */
+ static void ahc_xxx_enqueue __P((struct ahc_data *ahc,
+ struct scsi_xfer *xs, int infront));
+ static struct scsi_xfer *ahc_xxx_dequeue __P((struct ahc_data *ahc));
+ #endif
+
#if defined(__FreeBSD__)
char *ahc_name(ahc)
***************
*** 619,624 ****
--- 625,637 ----
struct scsibus_data *scbus;
#endif
+ #if defined(__NetBSD__) /* XXX */
+ /*
+ * Initialize the software queue.
+ */
+ LIST_INIT(&ahc->sc_xxxq);
+ #endif
+
#ifdef AHC_BROKEN_CACHE
if (cpu_class == CPUCLASS_386) /* doesn't have "wbinvd" instruction */
ahc_broken_cache = 0;
***************
*** 1986,1991 ****
--- 1999,2017 ----
#endif
ahc_free_scb(ahc, scb, xs->flags);
scsi_done(xs);
+
+ #if defined(__NetBSD__) /* XXX */
+ /*
+ * If there are entries in the software queue, try to
+ * run the first one. We should be more or less guaranteed
+ * to succeed, since we just freed an SCB.
+ *
+ * NOTE: ahc_scsi_cmd() relies on our calling it with
+ * the first entry in the queue.
+ */
+ if (ahc->sc_xxxq.lh_first != NULL)
+ (void) ahc_scsi_cmd(ahc->sc_xxxq.lh_first);
+ #endif /* __NetBSD__ */
}
/*
***************
*** 2329,2334 ****
--- 2355,2405 ----
#endif
}
+ #if defined(__NetBSD__) /* XXX */
+ /*
+ * Insert a scsi_xfer into the software queue. We overload xs->free_list
+ * to to ensure we don't run into a queue resource shortage, and keep
+ * a pointer to the last entry around to make insertion O(C).
+ */
+ static void
+ ahc_xxx_enqueue(ahc, xs, infront)
+ struct ahc_data *ahc;
+ struct scsi_xfer *xs;
+ int infront;
+ {
+
+ if (infront || ahc->sc_xxxq.lh_first == NULL) {
+ if (ahc->sc_xxxq.lh_first == NULL)
+ ahc->sc_xxxqlast = xs;
+ LIST_INSERT_HEAD(&ahc->sc_xxxq, xs, free_list);
+ return;
+ }
+
+ LIST_INSERT_AFTER(ahc->sc_xxxqlast, xs, free_list);
+ ahc->sc_xxxqlast = xs;
+ }
+
+ /*
+ * Pull a scsi_xfer off the front of the software queue. When we
+ * pull the last one off, we need to clear the pointer to the last
+ * entry.
+ */
+ static struct scsi_xfer *
+ ahc_xxx_dequeue(ahc)
+ struct ahc_data *ahc;
+ {
+ struct scsi_xfer *xs;
+
+ xs = ahc->sc_xxxq.lh_first;
+ LIST_REMOVE(xs, free_list);
+
+ if (ahc->sc_xxxq.lh_first == NULL)
+ ahc->sc_xxxqlast = NULL;
+
+ return (xs);
+ }
+ #endif
+
/*
* start a scsi operation given the command and
* the data address, target, and lun all of which
***************
*** 2347,2352 ****
--- 2418,2426 ----
struct ahc_data *ahc;
u_short mask;
int s;
+ #if defined(__NetBSD__) /* XXX */
+ int dontqueue = 0, fromqueue = 0;
+ #endif
ahc = (struct ahc_data *)xs->sc_link->adapter_softc;
mask = (0x01 << (xs->sc_link->target
***************
*** 2355,2361 ****
--- 2429,2481 ----
#elif defined(__NetBSD__)
| (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0) ));
#endif
+
SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
+
+ #if defined(__NetBSD__) /* XXX */
+ /* must protect the queue */
+ s = splbio();
+
+ /*
+ * If we're running the queue from ahc_done(), we're called
+ * with the first entry in the queue as our argument.
+ * Pull it off; if we can't run the job, it will get placed
+ * back at the front.
+ */
+ if (xs == ahc->sc_xxxq.lh_first) {
+ xs = ahc_xxx_dequeue(ahc);
+ fromqueue = 1;
+ goto get_scb;
+ }
+
+ /* determine safey of software queueing */
+ dontqueue = xs->flags & SCSI_POLL;
+
+ /*
+ * Handle situations where there's already entries in the
+ * queue.
+ */
+ if (ahc->sc_xxxq.lh_first != NULL) {
+ /*
+ * If we can't queue, we have to abort, since
+ * we have to preserve order.
+ */
+ if (dontqueue) {
+ splx(s);
+ xs->error = XS_DRIVER_STUFFUP;
+ return (TRY_AGAIN_LATER);
+ }
+
+ /*
+ * Swap with the first queue entry.
+ */
+ ahc_xxx_enqueue(ahc, xs, 0);
+ xs = ahc_xxx_dequeue(ahc);
+ fromqueue = 1;
+ }
+
+ get_scb:
+ #endif /* __NetBSD__ */
/*
* get an scb to use. If the transfer
* is from a buf (possibly from interrupt time)
***************
*** 2371,2379 ****
--- 2491,2526 ----
xs->flags |= INUSE;
}
if (!(scb = ahc_get_scb(ahc, flags))) {
+ #if defined(__NetBSD__) /* XXX */
+ /*
+ * If we can't queue, we lose.
+ */
+ if (dontqueue) {
+ splx(s);
+ xs->error = XS_DRIVER_STUFFUP;
+ return (TRY_AGAIN_LATER);
+ }
+
+ /*
+ * If we were pulled off the queue, put ourselves
+ * back in the front, otherwise tack ourselves onto
+ * the end.
+ */
+ ahc_xxx_enqueue(ahc, xs, fromqueue);
+
+ splx(s);
+ return (SUCCESSFULLY_QUEUED);
+ #else
xs->error = XS_DRIVER_STUFFUP;
return (TRY_AGAIN_LATER);
+ #endif /* __NetBSD__ */
}
+
+ #if defined(__NetBSD__)
+ /* we're done playing with the queue */
+ splx(s);
+ #endif
+
SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
scb->xs = xs;
if (flags & SCSI_RESET) {
Index: aic7xxxvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/aic7xxxvar.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -c -r1.10 -r1.11
*** aic7xxxvar.h 1996/10/21 22:34:09 1.10
--- aic7xxxvar.h 1996/12/02 19:06:44 1.11
***************
*** 1,4 ****
! /* $NetBSD: aic7xxxvar.h,v 1.10 1996/10/21 22:34:09 thorpej Exp $ */
/*
* Interface to the generic driver for the aic7xxx based adaptec
--- 1,4 ----
! /* $NetBSD: aic7xxxvar.h,v 1.11 1996/12/02 19:06:44 thorpej Exp $ */
/*
* Interface to the generic driver for the aic7xxx based adaptec
***************
*** 213,218 ****
--- 213,220 ----
void *sc_ih;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
+ LIST_HEAD(, scsi_xfer) sc_xxxq; /* XXX software request queue */
+ struct scsi_xfer *sc_xxxqlast; /* last entry in queue */
#endif
ahc_type type;
ahc_flag flags;