Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/scsipi Make the xxstart() functions reentrant again, ...



details:   https://anonhg.NetBSD.org/src/rev/1dd839711adc
branches:  trunk
changeset: 569848:1dd839711adc
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Thu Sep 09 19:35:30 2004 +0000

description:
Make the xxstart() functions reentrant again, as some drivers HBA can call
scsipi_done() from their scsipi_request().
For this, add a struct scsipi_xfer * argument to scsipi_command().
If not NULL scsipi_command() will use this to enqueue this xfer, otherwise
it'll try to allocate a new one. This scsipi_xfer has to be allocated
and initialised by scsipi_make_xs() or equivalent.
In xxstart(), allocate a scsipi_xfer using scsipi_make_xs(), and if not NULL,
dequeue the buffer before calling scsipi_command(). This makes sure that
scsipi_command() will not fail, and also makes sure that xxstart() won't
be called again between the BUFQ_PEEK() and BUFQ_GET().

Fix "dequeued wrong buf" panics reported by Juergen Hannken-Illjes in
private mail and Andreas Wrede on current-users@.
Thanks to Jason Thorpe and Chuck Silver for review, and Andreas Wrede for
testing the patch.

diffstat:

 sys/dev/scsipi/atapi_base.c   |  18 +++++-----
 sys/dev/scsipi/atapiconf.h    |   7 ++-
 sys/dev/scsipi/cd.c           |  71 +++++++++++++++++++++++-------------------
 sys/dev/scsipi/ch.c           |  16 ++++----
 sys/dev/scsipi/if_se.c        |   6 +-
 sys/dev/scsipi/scsi_base.c    |  23 +++++++------
 sys/dev/scsipi/scsiconf.h     |   7 ++-
 sys/dev/scsipi/scsipi_base.c  |  38 ++++++++++++----------
 sys/dev/scsipi/scsipi_ioctl.c |   6 +-
 sys/dev/scsipi/scsipiconf.c   |  12 +++---
 sys/dev/scsipi/scsipiconf.h   |   6 +-
 sys/dev/scsipi/sd.c           |  33 ++++++++++++-------
 sys/dev/scsipi/ses.c          |   6 +-
 sys/dev/scsipi/ss_mustek.c    |  61 +++++++++++++++++++-----------------
 sys/dev/scsipi/ss_scanjet.c   |  49 +++++++++++++++-------------
 sys/dev/scsipi/st.c           |  41 +++++++++++++++---------
 sys/dev/scsipi/st_scsi.c      |   6 +-
 17 files changed, 221 insertions(+), 185 deletions(-)

diffs (truncated from 1296 to 300 lines):

diff -r c5316cf03ae8 -r 1dd839711adc sys/dev/scsipi/atapi_base.c
--- a/sys/dev/scsipi/atapi_base.c       Thu Sep 09 14:56:00 2004 +0000
+++ b/sys/dev/scsipi/atapi_base.c       Thu Sep 09 19:35:30 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atapi_base.c,v 1.21 2004/08/27 20:37:28 bouyer Exp $   */
+/*     $NetBSD: atapi_base.c,v 1.22 2004/09/09 19:35:30 bouyer Exp $   */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atapi_base.c,v 1.21 2004/08/27 20:37:28 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atapi_base.c,v 1.22 2004/09/09 19:35:30 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -213,11 +213,10 @@
  * 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;
        int error;
 
        SC_DEBUG(periph, SCSIPI_DB2, ("atapi_cmd\n"));
@@ -226,11 +225,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;
diff -r c5316cf03ae8 -r 1dd839711adc sys/dev/scsipi/atapiconf.h
--- a/sys/dev/scsipi/atapiconf.h        Thu Sep 09 14:56:00 2004 +0000
+++ b/sys/dev/scsipi/atapiconf.h        Thu Sep 09 19:35:30 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atapiconf.h,v 1.17 2004/08/21 17:41:18 thorpej Exp $   */
+/*     $NetBSD: atapiconf.h,v 1.18 2004/09/09 19:35:30 bouyer Exp $    */
 
 /*
  * Copyright (c) 1996, 2001 Manuel Bouyer.  All rights reserved.
@@ -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 *,
+           struct scsipi_generic *, int, void *, size_t,
+           int, int, struct buf *, int);
 
 #endif /* _DEV_SCSIPI_ATAPICONF_H */
diff -r c5316cf03ae8 -r 1dd839711adc sys/dev/scsipi/cd.c
--- a/sys/dev/scsipi/cd.c       Thu Sep 09 14:56:00 2004 +0000
+++ b/sys/dev/scsipi/cd.c       Thu Sep 09 19:35:30 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cd.c,v 1.204 2004/09/06 20:38:14 bouyer Exp $  */
+/*     $NetBSD: cd.c,v 1.205 2004/09/09 19:35:30 bouyer Exp $  */
 
 /*-
  * Copyright (c) 1998, 2001, 2003 The NetBSD Foundation, Inc.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.204 2004/09/06 20:38:14 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd.c,v 1.205 2004/09/09 19:35:30 bouyer Exp $");
 
 #include "rnd.h"
 
@@ -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,22 @@
                            periph);
                        return;
                }
+               /*
+                * need to dequeue the 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);
+               /* with a scsipi_xfer preallocated, scsipi_command can't fail */
+               KASSERT(error == 0);
        }
 }
 
@@ -1619,7 +1626,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 +1664,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 +1720,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 +1736,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 +1748,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 +1769,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 +1799,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 +1874,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 +1886,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 +1898,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 +1911,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 +1926,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 +1940,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 +1954,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 +1967,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 +1977,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 +1995,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 +2023,7 @@
        _lto2b(sizeof(buf), &cmd.bytes[7]);
 



Home | Main Index | Thread Index | Old Index