Subject: Re: panic: dequeued wrong buf in -current
To: Andreas Wrede <andreas@planix.com>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-kern
Date: 09/07/2004 23:12:00
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Tue, Sep 07, 2004 at 12:12:42AM +0200, Manuel Bouyer wrote:
> Juergen Hannken-Illjes has reported in private mail a similar problem,
> on sparc64 without raidframe or ccd involved.
> He started looking at this, and it appears that sdstart() is called twice,
> once of the calls being interrupted. I followed the call graph and I don't
> know where it could happen.
>
> Both you and Juergen use the esiop driver, and this driver can call
> scsipi_done() from esiop_scsipi_request(). This can likely cause sdstart() to
> call itself. Other HBA drivers may do this as well.
>
> A workaround would be to add a lock in sdstart() to avoid such recursion,
> but this will have an impact on performances, as we loose opportunities to
> keep the disk busy.
> A better way would be to allow sdstart() to be reentrant.
> Basically we need to deqeue the buf before calling the HBA's adapter request.
> 1) add a struct scsipi_xfer * argument to scsipi_command(): if this pointer is
> not null it would use this xfer, otherwise it would try to allocate one
> as it does now.
> 2) make scsipi_command() dequeue the buf itself. We can't do this for every
> command with a buf, so this needs a new flag, or something
> 3) always dequeue the buf, and use a local FIFO queue when we're out of
> ressources.
>
> I prefer 1) myself, as it can allow a more flexible error recovery procedure
> on resources shortage in other cases too. However, it's quite intrusive as
> all scsipi_command() calls needs to be touched (which means almost all
> files in sys/dev/scsipi) As we want to get this pulled up to 2.0, 2) may be
> better.
2) isn't doable without adding an extra argument to scsipi_command() either
(we need a pointer to the buf queue), so I've gone with 1).
I'm now running the attached patch on i386 with atapi devices, and sparc
with scsi drives (controller is a esp@sbus).
I noone object I'll commit this in a couple of days, and request a pullup to
2.0 of all commits related to dealing with scsipi_xfer shortage.
Andreas, can you please give this patch a try ?
--
Manuel Bouyer <bouyer@antioche.eu.org>
NetBSD: 26 ans d'experience feront toujours la difference
--
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Index: atapi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapi_base.c,v
retrieving revision 1.21
diff -u -r1.21 atapi_base.c
--- atapi_base.c 27 Aug 2004 20:37:28 -0000 1.21
+++ atapi_base.c 7 Sep 2004 20:28:28 -0000
@@ -213,11 +213,11 @@
* to associate with the transfer, we need that too.
*/
int
-atapi_scsipi_cmd(struct scsipi_periph *periph,
+atapi_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_xfer *_xs,
struct scsipi_generic *scsipi_cmd, int cmdlen, void *data, size_t datalen,
int retries, int timeout, struct buf *bp, int flags)
{
- struct scsipi_xfer *xs;
+ struct scsipi_xfer *xs = _xs;
int error;
SC_DEBUG(periph, SCSIPI_DB2, ("atapi_cmd\n"));
@@ -226,11 +226,12 @@
if (bp != NULL && (flags & XS_CTL_ASYNC) == 0)
panic("atapi_scsipi_cmd: buffer without async");
#endif
-
- if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
- datalen, retries, timeout, bp, flags)) == NULL) {
- /* let the caller deal with this */
- return (ENOMEM);
+ if (xs == NULL) {
+ if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
+ datalen, retries, timeout, bp, flags)) == NULL) {
+ /* let the caller deal with this */
+ return (ENOMEM);
+ }
}
xs->cmdlen = (periph->periph_cap & PERIPH_CAP_CMD16) ? 16 : 12;
Index: atapiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/atapiconf.h,v
retrieving revision 1.17
diff -u -r1.17 atapiconf.h
--- atapiconf.h 21 Aug 2004 17:41:18 -0000 1.17
+++ atapiconf.h 7 Sep 2004 20:28:30 -0000
@@ -57,7 +57,8 @@
int atapiprint(void *, const char *);
void atapi_print_addr(struct scsipi_periph *);
int atapi_interpret_sense(struct scsipi_xfer *);
-int atapi_scsipi_cmd(struct scsipi_periph *, struct scsipi_generic *,
- int, void *, size_t, int, int, struct buf *, int);
+int atapi_scsipi_cmd(struct scsipi_periph *, struct scsipi_xfer *xs,
+ struct scsipi_generic *, int, void *, size_t,
+ int, int, struct buf *, int);
#endif /* _DEV_SCSIPI_ATAPICONF_H */
Index: cd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/cd.c,v
retrieving revision 1.204
diff -u -r1.204 cd.c
--- cd.c 6 Sep 2004 20:38:14 -0000 1.204
+++ cd.c 7 Sep 2004 20:28:34 -0000
@@ -88,6 +88,7 @@
/* from there */
#include <dev/scsipi/scsi_disk.h> /* rw comes from there */
#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
#include <dev/scsipi/cdvar.h>
#define CDUNIT(z) DISKUNIT(z)
@@ -772,6 +773,7 @@
struct scsipi_rw_big cmd_big;
struct scsi_rw cmd_small;
struct scsipi_generic *cmdp;
+ struct scsipi_xfer *xs;
int flags, nblks, cmdlen, error;
SC_DEBUG(periph, SCSIPI_DB2, ("cdstart "));
@@ -866,15 +868,10 @@
* Call the routine that chats with the adapter.
* Note: we cannot sleep as we may be an interrupt
*/
- error = scsipi_command(periph, cmdp, cmdlen,
+ xs = scsipi_make_xs(periph, cmdp, cmdlen,
(u_char *)bp->b_data, bp->b_bcount,
CDRETRIES, 30000, bp, flags);
- if (__predict_false(error)) {
- disk_unbusy(&cd->sc_dk, 0, 0);
- printf("%s: not queued, error %d\n",
- cd->sc_dev.dv_xname, error);
- }
- if (__predict_false(error == ENOMEM)) {
+ if (__predict_false(xs == NULL)) {
/*
* out of memory. Keep this buffer in the queue, and
* retry later.
@@ -883,12 +880,28 @@
periph);
return;
}
+ /*
+ * need to dequeue de buffer before queuing the command,
+ * because cdstart may be called recursively from the
+ * HBA driver
+ */
#ifdef DIAGNOSTIC
if (BUFQ_GET(&cd->buf_queue) != bp)
panic("cdstart(): dequeued wrong buf");
#else
BUFQ_GET(&cd->buf_queue);
#endif
+ error = scsipi_command(periph, xs, cmdp, cmdlen,
+ (u_char *)bp->b_data, bp->b_bcount,
+ CDRETRIES, 30000, bp, flags);
+ if (__predict_false(error)) {
+ disk_unbusy(&cd->sc_dk, 0, 0);
+ printf("%s: not queued, error %d\n",
+ cd->sc_dev.dv_xname, error);
+ bp->b_flags |= B_ERROR;
+ bp->b_error = ENOMEM;
+ biodone(bp);
+ }
}
}
@@ -1619,7 +1632,7 @@
* If the command works, interpret the result as a 4 byte
* number of blocks and a blocksize
*/
- if (scsipi_command(cd->sc_periph,
+ if (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
(u_char *)&rdcap, sizeof(rdcap), CDRETRIES, 30000, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK) != 0)
@@ -1657,7 +1670,7 @@
scsipi_cmd.opcode = PLAY;
_lto4b(blkno, scsipi_cmd.blk_addr);
_lto2b(nblks, scsipi_cmd.xfer_len);
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
0, 0, CDRETRIES, 30000, NULL, 0));
}
@@ -1713,7 +1726,7 @@
scsipi_cmd.end_m = endm;
scsipi_cmd.end_s = ends;
scsipi_cmd.end_f = endf;
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
0, 0, CDRETRIES, 30000, NULL, 0));
}
@@ -1729,7 +1742,7 @@
memset(&scsipi_cmd, 0, sizeof(scsipi_cmd));
scsipi_cmd.opcode = PAUSE;
scsipi_cmd.resume = go & 0xff;
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
0, 0, CDRETRIES, 30000, NULL, 0));
}
@@ -1741,7 +1754,7 @@
cd_reset(struct cd_softc *cd)
{
- return (scsipi_command(cd->sc_periph, 0, 0, 0, 0,
+ return (scsipi_command(cd->sc_periph, NULL, 0, 0, 0, 0,
CDRETRIES, 30000, NULL, XS_CTL_RESET));
}
@@ -1762,7 +1775,7 @@
scsipi_cmd.subchan_format = format;
scsipi_cmd.track = track;
_lto2b(len, scsipi_cmd.data_len);
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd,
sizeof(struct scsipi_read_subchannel), (u_char *)data, len,
CDRETRIES, 30000, NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT));
@@ -1792,7 +1805,7 @@
scsipi_cmd.from_track = start;
_lto2b(ntoc, scsipi_cmd.data_len);
scsipi_cmd.control = control;
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd,
sizeof(struct scsipi_read_toc), (u_char *)data, len, CDRETRIES,
30000, NULL, flags | XS_CTL_DATA_IN));
@@ -1867,7 +1880,7 @@
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[8] = 8;
cmd.bytes[9] = 0 | (0 << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 8,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1879,7 +1892,7 @@
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[8] = 16;
cmd.bytes[9] = 1 | (a->lsc.agid << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 16,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1891,7 +1904,7 @@
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[8] = 12;
cmd.bytes[9] = 2 | (a->lsk.agid << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 12,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1904,7 +1917,7 @@
_lto4b(a->lstk.lba, &cmd.bytes[1]);
cmd.bytes[8] = 12;
cmd.bytes[9] = 4 | (a->lstk.agid << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 12,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1919,7 +1932,7 @@
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[8] = 8;
cmd.bytes[9] = 5 | (a->lsasf.agid << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 8,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1933,7 +1946,7 @@
cmd.bytes[9] = 1 | (a->hsc.agid << 6);
buf[1] = 14;
dvd_copy_challenge(&buf[4], a->hsc.chal);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 16,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1947,7 +1960,7 @@
cmd.bytes[9] = 3 | (a->hsk.agid << 6);
buf[1] = 10;
dvd_copy_key(&buf[4], a->hsk.key);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 12,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 12,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
if (error) {
@@ -1960,7 +1973,7 @@
case DVD_INVALIDATE_AGID:
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[9] = 0x3f | (a->lsa.agid << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 16,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 16,
CDRETRIES, 30000, NULL, 0);
if (error)
return (error);
@@ -1970,7 +1983,7 @@
cmd.opcode = GPCMD_REPORT_KEY;
cmd.bytes[8] = 8;
cmd.bytes[9] = 8 | (0 << 6);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 8,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
@@ -1988,7 +2001,7 @@
cmd.bytes[9] = 6 | (0 << 6);
buf[1] = 6;
buf[4] = a->hrpcs.pdrc;
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 8,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 8,
CDRETRIES, 30000, NULL,
XS_CTL_DATA_OUT|XS_CTL_DATA_ONSTACK);
if (error)
@@ -2016,7 +2029,7 @@
_lto2b(sizeof(buf), &cmd.bytes[7]);
cmd.bytes[5] = s->physical.layer_num;
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, sizeof(buf),
CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
return (error);
@@ -2054,7 +2067,7 @@
_lto2b(sizeof(buf), &cmd.bytes[7]);
cmd.bytes[5] = s->copyright.layer_num;
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, sizeof(buf),
CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
return (error);
@@ -2079,7 +2092,7 @@
_lto2b(4 + 2048, &cmd.bytes[7]);
cmd.bytes[9] = s->disckey.agid << 6;
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 4 + 2048,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 4 + 2048,
CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error == 0)
memcpy(s->disckey.value, &buf[4], 2048);
@@ -2100,7 +2113,7 @@
cmd.bytes[6] = s->type;
_lto2b(sizeof(buf), &cmd.bytes[7]);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, sizeof(buf),
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, sizeof(buf),
CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error)
return (error);
@@ -2126,7 +2139,7 @@
cmd.bytes[6] = s->type;
_lto2b(4 + 2048, &cmd.bytes[7]);
- error = scsipi_command(cd->sc_periph, &cmd, 12, buf, 4 + 2048,
+ error = scsipi_command(cd->sc_periph, NULL, &cmd, 12, buf, 4 + 2048,
CDRETRIES, 30000, NULL, XS_CTL_DATA_IN|XS_CTL_DATA_ONSTACK);
if (error == 0) {
s->manufact.len = _2btol(&buf[0]);
@@ -2402,7 +2415,7 @@
scsipi_cmd.options = args->options; /* ioctl uses MMC values */
scsipi_cmd.slot = args->slot;
- return (scsipi_command(cd->sc_periph,
+ return (scsipi_command(cd->sc_periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
0, 0, CDRETRIES, 200000, NULL, 0));
}
Index: ch.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ch.c,v
retrieving revision 1.61
diff -u -r1.61 ch.c
--- ch.c 21 Aug 2004 17:40:25 -0000 1.61
+++ ch.c 7 Sep 2004 20:28:36 -0000
@@ -615,7 +615,7 @@
/*
* Send command to changer.
*/
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd), NULL, 0, CHRETRIES,
100000, NULL, 0));
}
@@ -670,7 +670,7 @@
/*
* Send command to changer.
*/
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd), NULL, 0, CHRETRIES,
100000, NULL, 0));
}
@@ -707,7 +707,7 @@
/*
* Send command to changer.
*/
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd), NULL, 0, CHRETRIES,
100000, NULL, 0));
}
@@ -1047,7 +1047,7 @@
/*
* Send command to changer.
*/
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
(u_char *)data, datalen, CHRETRIES, 100000, NULL,
scsiflags | XS_CTL_DATA_IN));
@@ -1113,7 +1113,7 @@
/*
* Send command to changer.
*/
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
(u_char *)data, datalen, CHRETRIES, 100000, NULL,
datalen ? XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK : 0));
@@ -1150,7 +1150,7 @@
tmo *= 5 * 60 * 1000;
tmo += (10 * 60 * 1000);
- return (scsipi_command(sc->sc_periph,
+ return (scsipi_command(sc->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
NULL, 0, CHRETRIES, tmo, NULL, XS_CTL_IGNORE_ILLEGAL_REQUEST));
}
Index: if_se.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/if_se.c,v
retrieving revision 1.46
diff -u -r1.46 if_se.c
--- if_se.c 23 Apr 2004 21:52:17 -0000 1.46
+++ if_se.c 7 Sep 2004 20:28:38 -0000
@@ -387,7 +387,7 @@
int error;
int s = splbio();
- error = scsipi_command(periph, scsipi_cmd, cmdlen, data_addr,
+ error = scsipi_command(periph, NULL, scsipi_cmd, cmdlen, data_addr,
datalen, retries, timeout, bp, flags);
splx(s);
return (error);
Index: scsi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsi_base.c,v
retrieving revision 1.80
diff -u -r1.80 scsi_base.c
--- scsi_base.c 27 Aug 2004 20:37:28 -0000 1.80
+++ scsi_base.c 7 Sep 2004 20:28:38 -0000
@@ -67,7 +67,7 @@
scsipi_cmd.opcode = SCSI_CHANGE_DEFINITION;
scsipi_cmd.how = SC_SCSI_2;
- return (scsipi_command(periph,
+ return (scsipi_command(periph, NULL,
(struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
0, 0, SCSIPIRETRIES, 100000, NULL, flags));
}
@@ -79,11 +79,11 @@
* to associate with the transfer, we need that too.
*/
int
-scsi_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_generic *scsipi_cmd,
- int cmdlen, void *data, size_t datalen, int retries, int timeout,
- struct buf *bp, int flags)
+scsi_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_xfer *_xs,
+ struct scsipi_generic *scsipi_cmd, int cmdlen, void *data, size_t datalen,
+ int retries, int timeout, struct buf *bp, int flags)
{
- struct scsipi_xfer *xs;
+ struct scsipi_xfer *xs = _xs;
int error;
SC_DEBUG(periph, SCSIPI_DB2, ("scsi_scsipi_cmd\n"));
@@ -93,10 +93,12 @@
panic("scsi_scsipi_cmd: buffer without async");
#endif
- if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
- datalen, retries, timeout, bp, flags)) == NULL) {
- /* let the caller deal with this */
- return (ENOMEM);
+ if (xs == NULL) {
+ if ((xs = scsipi_make_xs(periph, scsipi_cmd, cmdlen, data,
+ datalen, retries, timeout, bp, flags)) == NULL) {
+ /* let the caller deal with this */
+ return (ENOMEM);
+ }
}
/*
Index: scsiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsiconf.h,v
retrieving revision 1.51
diff -u -r1.51 scsiconf.h
--- scsiconf.h 21 Aug 2004 20:40:36 -0000 1.51
+++ scsiconf.h 7 Sep 2004 20:28:38 -0000
@@ -76,7 +76,8 @@
void scsi_kill_pending(struct scsipi_periph *);
void scsi_print_addr(struct scsipi_periph *);
int scsi_probe_bus(struct scsibus_softc *, int, int);
-int scsi_scsipi_cmd(struct scsipi_periph *, struct scsipi_generic *,
- int, void *, size_t, int, int, struct buf *, int);
+int scsi_scsipi_cmd(struct scsipi_periph *, struct scsipi_xfer *,
+ struct scsipi_generic *, int, void *, size_t,
+ int, int, struct buf *, int);
#endif /* _DEV_SCSIPI_SCSICONF_H_ */
Index: scsipi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_base.c,v
retrieving revision 1.111
diff -u -r1.111 scsipi_base.c
--- scsipi_base.c 2 Sep 2004 12:39:56 -0000 1.111
+++ scsipi_base.c 7 Sep 2004 20:28:42 -0000
@@ -1040,7 +1040,7 @@
* If the command works, interpret the result as a 4 byte
* number of blocks
*/
- if (scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
+ if (scsipi_command(periph, NULL, (struct scsipi_generic *)&scsipi_cmd,
sizeof(scsipi_cmd), (u_char *)&rdcap, sizeof(rdcap),
SCSIPIRETRIES, 20000, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
@@ -1072,7 +1072,7 @@
else
retries = SCSIPIRETRIES;
- return (scsipi_command(periph,
+ return (scsipi_command(periph, NULL,
(struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
0, 0, retries, 10000, NULL, flags));
}
@@ -1110,13 +1110,13 @@
* - mycroft, 2003/10/16
*/
scsipi_cmd.length = SCSIPI_INQUIRY_LENGTH_SCSI2;
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
(u_char *) inqbuf, SCSIPI_INQUIRY_LENGTH_SCSI2,
retries, 10000, NULL, XS_CTL_DATA_IN | flags);
if (!error && inqbuf->additional_length > SCSIPI_INQUIRY_LENGTH_SCSI2 - 4) {
scsipi_cmd.length = SCSIPI_INQUIRY_LENGTH_SCSI3;
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
(u_char *) inqbuf, SCSIPI_INQUIRY_LENGTH_SCSI3,
retries, 10000, NULL, XS_CTL_DATA_IN | flags);
@@ -1180,7 +1180,7 @@
scsipi_cmd.opcode = PREVENT_ALLOW;
scsipi_cmd.how = type;
- return (scsipi_command(periph,
+ return (scsipi_command(periph, NULL,
(struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
0, 0, SCSIPIRETRIES, 5000, NULL, flags));
}
@@ -1200,7 +1200,7 @@
scsipi_cmd.byte2 = 0x00;
scsipi_cmd.how = type;
- return (scsipi_command(periph,
+ return (scsipi_command(periph, NULL,
(struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
0, 0, SCSIPIRETRIES, (type & SSS_START) ? 60000 : 10000,
NULL, flags));
@@ -1224,8 +1224,9 @@
scsipi_cmd.byte2 = byte2;
scsipi_cmd.page = page;
scsipi_cmd.length = len & 0xff;
- error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
- sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
+ error = scsipi_command(periph, NULL,
+ (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
+ (void *)data, len, retries, timeout, NULL,
flags | XS_CTL_DATA_IN);
SC_DEBUG(periph, SCSIPI_DB2,
("scsipi_mode_sense: error=%d\n", error));
@@ -1245,8 +1246,9 @@
scsipi_cmd.byte2 = byte2;
scsipi_cmd.page = page;
_lto2b(len, scsipi_cmd.length);
- error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
- sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
+ error = scsipi_command(periph, NULL,
+ (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
+ (void *)data, len, retries, timeout, NULL,
flags | XS_CTL_DATA_IN);
SC_DEBUG(periph, SCSIPI_DB2,
("scsipi_mode_sense_big: error=%d\n", error));
@@ -1265,8 +1267,9 @@
scsipi_cmd.opcode = MODE_SELECT;
scsipi_cmd.byte2 = byte2;
scsipi_cmd.length = len & 0xff;
- error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
- sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
+ error = scsipi_command(periph, NULL,
+ (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
+ (void *)data, len, retries, timeout, NULL,
flags | XS_CTL_DATA_OUT);
SC_DEBUG(periph, SCSIPI_DB2,
("scsipi_mode_select: error=%d\n", error));
@@ -1285,8 +1288,9 @@
scsipi_cmd.opcode = MODE_SELECT_BIG;
scsipi_cmd.byte2 = byte2;
_lto2b(len, scsipi_cmd.length);
- error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
- sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
+ error = scsipi_command(periph, NULL,
+ (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
+ (void *)data, len, retries, timeout, NULL,
flags | XS_CTL_DATA_OUT);
SC_DEBUG(periph, SCSIPI_DB2,
("scsipi_mode_select: error=%d\n", error));
@@ -1690,7 +1694,7 @@
cmd.opcode = REQUEST_SENSE;
cmd.length = sizeof(struct scsipi_sense_data);
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &cmd, sizeof(cmd),
(u_char*)&xs->sense.scsi_sense, sizeof(struct scsipi_sense_data),
0, 1000, NULL, flags);
Index: scsipi_ioctl.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_ioctl.c,v
retrieving revision 1.47
diff -u -r1.47 scsipi_ioctl.c
--- scsipi_ioctl.c 21 Aug 2004 21:29:39 -0000 1.47
+++ scsipi_ioctl.c 7 Sep 2004 20:28:43 -0000
@@ -278,7 +278,7 @@
if (screq->flags & SCCMD_ESCAPE)
flags |= XS_CTL_ESCAPE;
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *)screq->cmd, screq->cmdlen,
(u_char *)bp->b_data, screq->datalen,
0, /* user must do the retries *//* ignored */
Index: scsipiconf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipiconf.c,v
retrieving revision 1.23
diff -u -r1.23 scsipiconf.c
--- scsipiconf.c 21 Aug 2004 21:30:58 -0000 1.23
+++ scsipiconf.c 7 Sep 2004 20:28:44 -0000
@@ -71,9 +71,9 @@
#define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
int
-scsipi_command(struct scsipi_periph *periph, struct scsipi_generic *cmd,
- int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
- struct buf *bp, int flags)
+scsipi_command(struct scsipi_periph *periph, struct scsipi_xfer *xs,
+ struct scsipi_generic *cmd, int cmdlen, u_char *data_addr, int datalen,
+ int retries, int timeout, struct buf *bp, int flags)
{
int error;
@@ -86,7 +86,7 @@
PHOLD(curlwp);
}
error = (*periph->periph_channel->chan_bustype->bustype_cmd)(periph,
- cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags);
+ xs, cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags);
if ((flags & XS_CTL_DATA_ONSTACK) != 0)
PRELE(curlwp);
return (error);
Index: scsipiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipiconf.h,v
retrieving revision 1.86
diff -u -r1.86 scsipiconf.h
--- scsipiconf.h 21 Aug 2004 21:30:29 -0000 1.86
+++ scsipiconf.h 7 Sep 2004 20:28:46 -0000
@@ -237,7 +237,7 @@
struct scsipi_bustype {
int bustype_type; /* symbolic name of type */
- int (*bustype_cmd)(struct scsipi_periph *,
+ int (*bustype_cmd)(struct scsipi_periph *, struct scsipi_xfer *,
struct scsipi_generic *, int, void *, size_t, int,
int, struct buf *, int);
int (*bustype_interpret_sense)(struct scsipi_xfer *);
@@ -626,7 +626,7 @@
#ifdef _KERNEL
void scsipi_init(void);
-int scsipi_command(struct scsipi_periph *,
+int scsipi_command(struct scsipi_periph *, struct scsipi_xfer *xs,
struct scsipi_generic *, int, u_char *, int,
int, int, struct buf *, int);
void scsipi_create_completion_thread(void *);
Index: sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.222
diff -u -r1.222 sd.c
--- sd.c 6 Sep 2004 20:38:14 -0000 1.222
+++ sd.c 7 Sep 2004 20:28:49 -0000
@@ -85,6 +85,7 @@
#include <dev/scsipi/scsipi_disk.h>
#include <dev/scsipi/scsi_disk.h>
#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipi_base.h>
#include <dev/scsipi/sdvar.h>
#define SDUNIT(dev) DISKUNIT(dev)
@@ -795,6 +796,7 @@
struct scsipi_rw_big cmd_big;
struct scsi_rw cmd_small;
struct scsipi_generic *cmdp;
+ struct scsipi_xfer *xs;
int nblks, cmdlen, error, flags;
SC_DEBUG(periph, SCSIPI_DB2, ("sdstart "));
@@ -899,15 +901,10 @@
* Call the routine that chats with the adapter.
* Note: we cannot sleep as we may be an interrupt
*/
- error = scsipi_command(periph, cmdp, cmdlen,
+ xs = scsipi_make_xs(periph, cmdp, cmdlen,
(u_char *)bp->b_data, bp->b_bcount,
SDRETRIES, SD_IO_TIMEOUT, bp, flags);
- if (__predict_false(error)) {
- disk_unbusy(&sd->sc_dk, 0, 0);
- printf("%s: not queued, error %d\n",
- sd->sc_dev.dv_xname, error);
- }
- if (__predict_false(error == ENOMEM)) {
+ if (__predict_false(xs == NULL)) {
/*
* out of memory. Keep this buffer in the queue, and
* retry later.
@@ -916,13 +913,28 @@
periph);
return;
}
+ /*
+ * need to dequeue de buffer before queuing the command,
+ * because cdstart may be called recursively from the
+ * HBA driver
+ */
#ifdef DIAGNOSTIC
if (BUFQ_GET(&sd->buf_queue) != bp)
panic("sdstart(): dequeued wrong buf");
#else
BUFQ_GET(&sd->buf_queue);
#endif
-
+ error = scsipi_command(periph, xs, cmdp, cmdlen,
+ (u_char *)bp->b_data, bp->b_bcount,
+ SDRETRIES, SD_IO_TIMEOUT, bp, flags);
+ if (__predict_false(error)) {
+ disk_unbusy(&sd->sc_dk, 0, 0);
+ printf("%s: not queued, error %d\n",
+ sd->sc_dev.dv_xname, error);
+ bp->b_flags |= B_ERROR;
+ bp->b_error = ENOMEM;
+ biodone(bp);
+ }
}
}
@@ -1665,8 +1677,9 @@
cmd.opcode = READ_FORMAT_CAPACITIES;
_lto2b(sizeof(data), cmd.length);
- error = scsipi_command(sd->sc_periph, (void *)&cmd, sizeof(cmd),
- (void *)&data, sizeof(data), SDRETRIES, 20000, NULL,
+ error = scsipi_command(sd->sc_periph, NULL,
+ (void *)&cmd, sizeof(cmd), (void *)&data, sizeof(data),
+ SDRETRIES, 20000, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
if (error == EFTYPE) {
/* Medium Format Corrupted, handle as not formatted */
@@ -1953,7 +1966,7 @@
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_SYNCHRONIZE_CACHE;
- return (scsipi_command(periph, (void *)&cmd, sizeof(cmd), 0, 0,
+ return (scsipi_command(periph, NULL, (void *)&cmd, sizeof(cmd), 0, 0,
SDRETRIES, 100000, NULL, flags | XS_CTL_IGNORE_ILLEGAL_REQUEST));
}
Index: ses.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ses.c,v
retrieving revision 1.23
diff -u -r1.23 ses.c
--- ses.c 21 Aug 2004 22:02:31 -0000 1.23
+++ ses.c 7 Sep 2004 20:28:52 -0000
@@ -500,7 +500,7 @@
#ifndef SCSIDEBUG
flg |= XS_CTL_SILENT;
#endif
- error = scsipi_command(ssc->sc_periph, &sgen, cdbl,
+ error = scsipi_command(ssc->sc_periph, NULL, &sgen, cdbl,
(u_char *) dptr, dl, SCSIPIRETRIES, 30000, NULL, flg);
if (error == 0 && dptr)
Index: ss_mustek.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ss_mustek.c,v
retrieving revision 1.20
diff -u -r1.20 ss_mustek.c
--- ss_mustek.c 27 Aug 2004 20:37:29 -0000 1.20
+++ ss_mustek.c 7 Sep 2004 20:28:54 -0000
@@ -66,6 +66,7 @@
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsi_scanner.h>
#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipi_base.h>
#include <dev/scsipi/ssvar.h>
#include <dev/scsipi/ss_mustek.h>
@@ -320,7 +321,7 @@
/* send the set window command to the scanner */
SC_DEBUG(periph, SCSIPI_DB1, ("mustek_set_parms: set_window\n"));
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &window_cmd,
sizeof(window_cmd), (u_char *) &window_data, sizeof(window_data),
MUSTEK_RETRIES, 5000, NULL, XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK);
@@ -360,7 +361,7 @@
SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner: mode_select\n"));
/* send the command to the scanner */
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &mode_cmd,
sizeof(mode_cmd), (u_char *) &mode_data, sizeof(mode_data),
MUSTEK_RETRIES, 5000, NULL, XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK);
@@ -398,7 +399,7 @@
/* send the command to the scanner */
SC_DEBUG(periph, SCSIPI_DB1, ("mustek_trigger_scanner: start_scan\n"));
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &start_scan_cmd,
sizeof(start_scan_cmd), NULL, 0,
MUSTEK_RETRIES, 5000, NULL, 0);
@@ -441,7 +442,7 @@
/* send the command to the scanner */
SC_DEBUG(periph, SCSIPI_DB1,
("mustek_rewind_scanner: stop_scan\n"));
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &cmd,
sizeof(cmd), NULL, 0, MUSTEK_RETRIES, 5000, NULL, 0);
if (error)
@@ -460,6 +461,7 @@
mustek_read(struct ss_softc *ss, struct buf *bp)
{
struct mustek_read_cmd cmd;
+ struct scsipi_xfer *xs;
struct scsipi_periph *periph = ss->sc_periph;
u_long lines_to_read;
int error;
@@ -479,22 +481,33 @@
/*
* go ask the adapter to do all this for us
*/
- error = scsipi_command(periph,
+ xs = scsipi_make_xs(periph,
+ (struct scsipi_generic *) &cmd, sizeof(cmd),
+ (u_char *) bp->b_data, bp->b_bcount,
+ MUSTEK_RETRIES, 10000, bp,
+ XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
+ if (xs == NULL) {
+ /*
+ * out of memory. Keep this buffer in the queue, and
+ * retry later.
+ */
+ callout_reset(&ss->sc_callout, hz / 2, ssrestart,
+ periph);
+ return(0);
+ }
+#ifdef DIAGNOSTIC
+ if (BUFQ_GET(&ss->buf_queue) != bp)
+ panic("ssstart(): dequeued wrong buf");
+#else
+ BUFQ_GET(&ss->buf_queue);
+#endif
+ error = scsipi_command(periph, xs,
(struct scsipi_generic *) &cmd, sizeof(cmd),
(u_char *) bp->b_data, bp->b_bcount, MUSTEK_RETRIES, 10000, bp,
XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
if (error) {
printf("%s: not queued, error %d\n", ss->sc_dev.dv_xname,
error);
- if (error == ENOMEM) {
- /*
- * out of memory. Keep this buffer in the queue, and
- * retry later.
- */
- callout_reset(&ss->sc_callout, hz / 2, ssrestart,
- periph);
- return(0);
- }
} else {
ss->sio.scan_lines -= lines_to_read;
if (ss->sio.scan_lines < 0)
@@ -503,13 +516,6 @@
if (ss->sio.scan_window_size < 0)
ss->sio.scan_window_size = 0;
}
-#ifdef DIAGNOSTIC
- if (BUFQ_GET(&ss->buf_queue) != bp)
- panic("ssstart(): dequeued wrong buf");
-#else
- BUFQ_GET(&ss->buf_queue);
-#endif
-
return (0);
}
@@ -534,7 +540,7 @@
while (1) {
SC_DEBUG(periph, SCSIPI_DB1, ("mustek_get_status: stat_cmd\n"));
- error = scsipi_command(periph,
+ error = scsipi_command(periph, NULL,
(struct scsipi_generic *) &cmd, sizeof(cmd),
(u_char *) &data, sizeof(data), MUSTEK_RETRIES,
5000, NULL, XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
Index: ss_scanjet.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/ss_scanjet.c,v
retrieving revision 1.31
diff -u -r1.31 ss_scanjet.c
--- ss_scanjet.c 27 Aug 2004 20:37:29 -0000 1.31
+++ ss_scanjet.c 7 Sep 2004 20:28:55 -0000
@@ -54,6 +54,7 @@
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsi_scanner.h>
#include <dev/scsipi/scsiconf.h>
+#include <dev/scsipi/scsipi_base.h>
#include <dev/scsipi/ssvar.h>
#define SCANJET_RETRIES 4
@@ -260,6 +261,7 @@
scanjet_read(struct ss_softc *ss, struct buf *bp)
{
struct scsi_rw_scanner cmd;
+ struct scsipi_xfer *xs;
struct scsipi_periph *periph = ss->sc_periph;
int error;
@@ -278,34 +280,38 @@
/*
* go ask the adapter to do all this for us
*/
- error = scsipi_command(periph,
+ xs = scsipi_make_xs(periph,
+ (struct scsipi_generic *) &cmd, sizeof(cmd),
+ (u_char *) bp->b_data, bp->b_bcount,
+ SCANJET_RETRIES, 100000, bp,
+ XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
+ if (xs == NULL) {
+ /*
+ * out of memory. Keep this buffer in the queue, and
+ * retry later.
+ */
+ callout_reset(&ss->sc_callout, hz / 2, ssrestart,
+ periph);
+ return(0);
+ }
+#ifdef DIAGNOSTIC
+ if (BUFQ_GET(&ss->buf_queue) != bp)
+ panic("ssstart(): dequeued wrong buf");
+#else
+ BUFQ_GET(&ss->buf_queue);
+#endif
+ error = scsipi_command(periph, xs,
(struct scsipi_generic *) &cmd, sizeof(cmd),
(u_char *) bp->b_data, bp->b_bcount, SCANJET_RETRIES, 100000, bp,
XS_CTL_NOSLEEP | XS_CTL_ASYNC | XS_CTL_DATA_IN);
if (error) {
printf("%s: not queued, error %d\n", ss->sc_dev.dv_xname,
error);
- if (error == ENOMEM) {
- /*
- * out of memory. Keep this buffer in the queue, and
- * retry later.
- */
- callout_reset(&ss->sc_callout, hz / 2, ssrestart,
- periph);
- return(0);
- }
} else {
ss->sio.scan_window_size -= bp->b_bcount;
if (ss->sio.scan_window_size < 0)
ss->sio.scan_window_size = 0;
}
-#ifdef DIAGNOSTIC
- if (BUFQ_GET(&ss->buf_queue) != bp)
- panic("ssstart(): dequeued wrong buf");
-#else
- BUFQ_GET(&ss->buf_queue);
-#endif
-
return (0);
}
@@ -326,7 +332,7 @@
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = WRITE;
_lto3b(size, cmd.len);
- return (scsipi_command(ss->sc_periph,
+ return (scsipi_command(ss->sc_periph, NULL,
(struct scsipi_generic *) &cmd,
sizeof(cmd), (u_char *) buf, size, 0, 100000, NULL,
flags | XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK));
@@ -349,7 +355,7 @@
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = READ;
_lto3b(size, cmd.len);
- return (scsipi_command(ss->sc_periph,
+ return (scsipi_command(ss->sc_periph, NULL,
(struct scsipi_generic *) &cmd,
sizeof(cmd), (u_char *) buf, size, 0, 100000, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK));
Index: st.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st.c,v
retrieving revision 1.165
diff -u -r1.165 st.c
--- st.c 27 Aug 2004 20:37:29 -0000 1.165
+++ st.c 7 Sep 2004 20:28:58 -0000
@@ -79,6 +79,7 @@
#include <dev/scsipi/scsi_all.h>
#include <dev/scsipi/scsi_tape.h>
#include <dev/scsipi/stvar.h>
+#include <dev/scsipi/scsipi_base.h>
/* Defines for device specific stuff */
#define DEF_FIXED_BSIZE 512
@@ -1162,6 +1163,7 @@
struct st_softc *st = (void *)periph->periph_dev;
struct buf *bp;
struct scsi_rw_tape cmd;
+ struct scsipi_xfer *xs;
int flags, error;
SC_DEBUG(periph, SCSIPI_DB2, ("ststart "));
@@ -1281,15 +1283,11 @@
/*
* go ask the adapter to do all this for us
*/
- error = scsipi_command(periph,
+ xs = scsipi_make_xs(periph,
(struct scsipi_generic *)&cmd, sizeof(cmd),
(u_char *)bp->b_data, bp->b_bcount,
0, ST_IO_TIME, bp, flags);
- if (__predict_false(error)) {
- printf("%s: not queued, error %d\n",
- st->sc_dev.dv_xname, error);
- }
- if (__predict_false(error == ENOMEM)) {
+ if (__predict_false(xs == NULL)) {
/*
* out of memory. Keep this buffer in the queue, and
* retry later.
@@ -1298,12 +1296,28 @@
periph);
return;
}
+ /*
+ * need to dequeue de buffer before queuing the command,
+ * because cdstart may be called recursively from the
+ * HBA driver
+ */
#ifdef DIAGNOSTIC
if (BUFQ_GET(&st->buf_queue) != bp)
panic("ststart(): dequeued wrong buf");
#else
BUFQ_GET(&st->buf_queue);
#endif
+ error = scsipi_command(periph, xs,
+ (struct scsipi_generic *)&cmd, sizeof(cmd),
+ (u_char *)bp->b_data, bp->b_bcount,
+ 0, ST_IO_TIME, bp, flags);
+ if (__predict_false(error)) {
+ printf("%s: not queued, error %d\n",
+ st->sc_dev.dv_xname, error);
+ bp->b_flags |= B_ERROR;
+ bp->b_error = ENOMEM;
+ biodone(bp);
+ }
} /* go back and see if we can cram more work in.. */
}
@@ -1636,7 +1650,7 @@
cmd.len);
} else
_lto3b(size, cmd.len);
- return (scsipi_command(st->sc_periph,
+ return (scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
(u_char *)buf, size, 0, ST_IO_TIME, NULL, flags | XS_CTL_DATA_IN));
}
@@ -1672,7 +1686,7 @@
if ((st->quirks & ST_Q_ERASE_NOIMM) == 0)
cmd.byte2 |= SE_IMMED;
- return (scsipi_command(st->sc_periph,
+ return (scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, ST_RETRIES, tmo, NULL, flags));
}
@@ -1758,7 +1772,7 @@
st->flags &= ~ST_POSUPDATED;
st->last_ctl_resid = 0;
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, 0, ST_SPC_TIME, NULL, flags);
@@ -1828,7 +1842,7 @@
_lto3b(number, cmd.number);
/* XXX WE NEED TO BE ABLE TO GET A RESIDIUAL XXX */
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, 0, ST_IO_TIME * 4, NULL, flags);
if (error == 0 && st->fileno != -1) {
@@ -1902,7 +1916,7 @@
cmd.byte2 = SR_IMMED;
cmd.how = type;
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
0, 0, ST_RETRIES, ST_SPC_TIME, NULL, flags);
if (error) {
@@ -1940,7 +1954,7 @@
cmd.opcode = REWIND;
cmd.byte2 = immediate;
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd), 0, 0, ST_RETRIES,
immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
if (error) {
@@ -1991,7 +2005,7 @@
if (hard)
cmd.byte1 = 1;
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd), (u_char *)&posdata,
sizeof(posdata), ST_RETRIES, ST_CTL_TIME, NULL,
XS_CTL_SILENT | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
@@ -2032,7 +2046,7 @@
if (hard)
cmd.byte2 = 1 << 2;
_lto4b(*blkptr, cmd.blkaddr);
- error = scsipi_command(st->sc_periph,
+ error = scsipi_command(st->sc_periph, NULL,
(struct scsipi_generic *)&cmd, sizeof(cmd),
NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0);
/*
Index: st_scsi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/st_scsi.c,v
retrieving revision 1.11
diff -u -r1.11 st_scsi.c
--- st_scsi.c 21 Aug 2004 22:16:07 -0000 1.11
+++ st_scsi.c 7 Sep 2004 20:28:58 -0000
@@ -155,7 +155,7 @@
/*
* do the command, update the global values
*/
- error = scsipi_command(periph, (struct scsipi_generic *)&cmd,
+ error = scsipi_command(periph, NULL, (struct scsipi_generic *)&cmd,
sizeof(cmd), (u_char *)&block_limits, sizeof(block_limits),
ST_RETRIES, ST_CTL_TIME, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
--M9NhX3UHpAaciwkO--