Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/scsipi Adn scsipi_target_detach() and scsipi_thread_...



details:   https://anonhg.NetBSD.org/src/rev/2b854a342cef
branches:  trunk
changeset: 512887:2b854a342cef
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Wed Jul 18 20:19:24 2001 +0000

description:
Adn scsipi_target_detach() and scsipi_thread_call_callback() as discussed
on tech-kern. scsipi_target_detach() accept wildcard target/lun as requested.

diffstat:

 sys/dev/scsipi/scsiconf.c    |   31 ++++------
 sys/dev/scsipi/scsipi_base.c |  123 ++++++++++++++++++++++++++++++++++++++----
 sys/dev/scsipi/scsipiconf.h  |   11 +++-
 3 files changed, 132 insertions(+), 33 deletions(-)

diffs (273 lines):

diff -r 56a062f015b8 -r 2b854a342cef sys/dev/scsipi/scsiconf.c
--- a/sys/dev/scsipi/scsiconf.c Wed Jul 18 19:29:40 2001 +0000
+++ b/sys/dev/scsipi/scsiconf.c Wed Jul 18 20:19:24 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: scsiconf.c,v 1.158 2001/06/11 13:58:18 pk Exp $        */
+/*     $NetBSD: scsiconf.c,v 1.159 2001/07/18 20:19:24 bouyer Exp $    */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -257,8 +257,6 @@
 {
        struct scsibus_softc *sc = (void *) self;
        struct scsipi_channel *chan = sc->sc_channel;
-       struct scsipi_periph *periph;
-       int target, lun, error;
 
        /*
         * Shut down the channel.
@@ -268,21 +266,7 @@
        /*
         * Now detach all of the periphs.
         */
-       for (target = 0; target < chan->chan_ntargets; target++) {
-               if (target == chan->chan_id)
-                       continue;
-               for (lun = 0; lun < chan->chan_nluns; lun++) {
-                       periph = scsipi_lookup_periph(chan, target, lun);
-                       if (periph == NULL)
-                               continue;
-                       error = config_detach(periph->periph_dev, flags);
-                       if (error)
-                               return (error);
-                       scsipi_remove_periph(chan, periph);
-                       free(periph, M_DEVBUF);
-               }
-       }
-       return (0);
+       return scsipi_target_detach(chan, -1, -1, flags);
 }
 
 /*
@@ -938,6 +922,7 @@
         */
        switch (cmd) {
        case SCBUSIOSCAN:
+       case SCBUSIODETACH:
        case SCBUSIORESET:
                if ((flag & FWRITE) == 0)
                        return (EBADF);
@@ -953,6 +938,16 @@
                break;
            }
 
+       case SCBUSIODETACH:
+           {
+               struct scbusiodetach_args *a =
+                   (struct scbusiodetach_args *)addr;
+
+               error = scsipi_target_detach(chan, a->sa_target, a->sa_lun, 0);
+               break;
+           }
+
+
        case SCBUSIORESET:
                /* FALLTHROUGH */
        default:
diff -r 56a062f015b8 -r 2b854a342cef sys/dev/scsipi/scsipi_base.c
--- a/sys/dev/scsipi/scsipi_base.c      Wed Jul 18 19:29:40 2001 +0000
+++ b/sys/dev/scsipi/scsipi_base.c      Wed Jul 18 20:19:24 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: scsipi_base.c,v 1.50 2001/07/18 18:21:05 thorpej Exp $ */
+/*     $NetBSD: scsipi_base.c,v 1.51 2001/07/18 20:19:24 bouyer Exp $  */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -1947,29 +1947,41 @@
                s = splbio();
                xs = TAILQ_FIRST(&chan->chan_complete);
                if (xs == NULL &&
-                   (chan->chan_flags & SCSIPI_CHAN_SHUTDOWN) == 0) {
+                   (chan->chan_flags &
+                    (SCSIPI_CHAN_SHUTDOWN | SCSIPI_CHAN_CALLBACK)) == 0) {
                        (void) tsleep(&chan->chan_complete, PRIBIO,
                            "sccomp", 0);
                        splx(s);
                        continue;
                }
+               if (chan->chan_flags & SCSIPI_CHAN_CALLBACK) {
+                       /* call chan_callback from thread context */
+                       chan->chan_flags &= ~SCSIPI_CHAN_CALLBACK;
+                       chan->chan_callback(chan, chan->chan_callback_arg);
+                       splx(s);
+                       continue;
+               }
                if (chan->chan_flags & SCSIPI_CHAN_SHUTDOWN) {
                        splx(s);
                        break;
                }
-               TAILQ_REMOVE(&chan->chan_complete, xs, channel_q);
-               splx(s);
+               if (xs) {
+                       TAILQ_REMOVE(&chan->chan_complete, xs, channel_q);
+                       splx(s);
+
+                       /*
+                        * Have an xfer with an error; process it.
+                        */
+                       (void) scsipi_complete(xs);
 
-               /*
-                * Have an xfer with an error; process it.
-                */
-               (void) scsipi_complete(xs);
-
-               /*
-                * Kick the queue; keep it running if it was stopped
-                * for some reason.
-                */
-               scsipi_run_queue(chan);
+                       /*
+                        * Kick the queue; keep it running if it was stopped
+                        * for some reason.
+                        */
+                       scsipi_run_queue(chan);
+               } else {
+                       splx(s);
+               }
        }
 
        chan->chan_thread = NULL;
@@ -2003,6 +2015,33 @@
 }
 
 /*
+ * scsipi_thread_call_callback:
+ *
+ *     request to call a callback from the completion thread
+ */
+int
+scsipi_thread_call_callback(chan, callback, arg)
+       struct scsipi_channel *chan;
+       void (*callback) __P((struct scsipi_channel *, void *));
+       void *arg;
+{
+       int s;
+
+       s = splbio();
+       if (chan->chan_flags & SCSIPI_CHAN_CALLBACK) {
+               splx(s);
+               return EBUSY;
+       }
+       scsipi_channel_freeze(chan, 1);
+       chan->chan_callback = callback;
+       chan->chan_callback_arg = arg;
+       chan->chan_flags |= SCSIPI_CHAN_CALLBACK;
+       wakeup(&chan->chan_complete);
+       splx(s);
+       return(0);
+}
+
+/*
  * scsipi_async_event:
  *
  *     Handle an asynchronous event from an adapter.
@@ -2271,6 +2310,62 @@
        }
 }
 
+/*
+ * scsipi_target_detach:
+ *
+ *     detach all periph associated with a I_T
+ *     must be called from valid thread context
+ */
+int
+scsipi_target_detach(chan, target, lun, flags)
+       struct scsipi_channel *chan;
+       int target, lun;
+       int flags;
+{
+       struct scsipi_periph *periph;
+       int ctarget, mintarget, maxtarget;
+       int clun, minlun, maxlun;
+       int error;
+
+       if (target == -1) {
+               mintarget = 0;
+               maxtarget = chan->chan_ntargets;
+       } else {
+               if (target == chan->chan_id)
+                       return EINVAL;
+               if (target < 0 || target >= chan->chan_ntargets)
+                       return EINVAL;
+               mintarget = target;
+               maxtarget = target + 1;
+       }
+
+       if (lun == -1) {
+               minlun = 0;
+               maxlun = chan->chan_nluns;
+       } else {
+               if (lun < 0 || lun >= chan->chan_nluns)
+                       return EINVAL;
+               minlun = lun;
+               maxlun = lun + 1;
+       }
+
+       for (ctarget = 0; ctarget < chan->chan_ntargets; ctarget++) {
+               if (ctarget == chan->chan_id)
+                       continue;
+
+               for (clun = minlun; clun < maxlun; clun++) {
+                       periph = scsipi_lookup_periph(chan, target, clun);
+                       if (periph == NULL)
+                               continue;
+                       error = config_detach(periph->periph_dev, flags);
+                       if (error)
+                               return (error);
+                       scsipi_remove_periph(chan, periph);
+                       free(periph, M_DEVBUF);
+               }
+       }
+       return(0);
+}
 
 /*
  * scsipi_adapter_addref:
diff -r 56a062f015b8 -r 2b854a342cef sys/dev/scsipi/scsipiconf.h
--- a/sys/dev/scsipi/scsipiconf.h       Wed Jul 18 19:29:40 2001 +0000
+++ b/sys/dev/scsipi/scsipiconf.h       Wed Jul 18 20:19:24 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: scsipiconf.h,v 1.54 2001/06/26 15:32:02 bouyer Exp $   */
+/*     $NetBSD: scsipiconf.h,v 1.55 2001/07/18 20:19:24 bouyer Exp $   */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -293,6 +293,10 @@
 
        /* Completed (async) jobs. */
        struct scsipi_xfer_queue chan_complete;
+
+       /* callback we may have to call from completion thread */
+       void (*chan_callback) __P((struct scsipi_channel *, void *));
+       void *chan_callback_arg;
 };
 
 /* chan_flags */
@@ -300,6 +304,7 @@
 #define        SCSIPI_CHAN_OPENINGS    0x02    /* use chan_openings */
 #define        SCSIPI_CHAN_CANGROW     0x04    /* channel can grow resources */
 #define        SCSIPI_CHAN_NOSETTLE    0x08    /* don't wait for devices to settle */
+#define        SCSIPI_CHAN_CALLBACK    0x10    /* has to call chan_callback() */
 
 #define        SCSIPI_CHAN_MAX_PERIPH(chan)                                    \
        (((chan)->chan_flags & SCSIPI_CHAN_OPENINGS) ?                  \
@@ -641,6 +646,9 @@
 void   scsipi_print_sense_data __P((struct scsipi_sense_data *, int));
 char   *scsipi_decode_sense __P((void *, int));
 #endif
+int    scsipi_thread_call_callback __P((struct scsipi_channel *,
+           void (*callback) __P((struct scsipi_channel *, void *)),
+           void *));
 void   scsipi_async_event __P((struct scsipi_channel *,
            scsipi_async_event_t, void *));
 int    scsipi_do_ioctl __P((struct scsipi_periph *, dev_t, u_long, caddr_t,
@@ -658,6 +666,7 @@
            struct scsipi_periph *));
 struct scsipi_periph *scsipi_lookup_periph __P((struct scsipi_channel *,
            int, int));
+int    scsipi_target_detach __P((struct scsipi_channel *, int, int, int));
 
 int    scsipi_adapter_addref __P((struct scsipi_adapter *));
 void   scsipi_adapter_delref __P((struct scsipi_adapter *));



Home | Main Index | Thread Index | Old Index