Subject: Re: scsipi changes
To: Matthew Jacob <mjacob@feral.com>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 07/14/2001 13:30:29
--Q68bSM7Ycu6FN28Q
Content-Type: text/plain; charset=us-ascii

On Fri, Jul 13, 2001 at 02:49:17PM -0700, Matthew Jacob wrote:
> 
> A lun argument would be good as long as you can use -1 for a wildcard.
> Heck- a wildcard on target would be okay too.

I can't see why you would want to detach all periph without detatching the
associated bus, but OK. New patch attached.

--
Manuel Bouyer <bouyer@antioche.eu.org>
--

--Q68bSM7Ycu6FN28Q
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: scsiconf.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/scsiconf.c,v
retrieving revision 1.158
diff -u -r1.158 scsiconf.c
--- scsiconf.c	2001/06/11 13:58:18	1.158
+++ scsiconf.c	2001/07/14 11:30:17
@@ -257,8 +257,7 @@
 {
 	struct scsibus_softc *sc = (void *) self;
 	struct scsipi_channel *chan = sc->sc_channel;
-	struct scsipi_periph *periph;
-	int target, lun, error;
+	int target, error;
 
 	/*
 	 * Shut down the channel.
@@ -271,16 +270,9 @@
 	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);
-		}
+		error = scsipi_target_detach(chan, target, -1, flags);
+		if (error)
+			return (error);
 	}
 	return (0);
 }
Index: scsipi_base.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/scsipi_base.c,v
retrieving revision 1.49
diff -u -r1.49 scsipi_base.c
--- scsipi_base.c	2001/07/13 20:00:23	1.49
+++ scsipi_base.c	2001/07/14 11:30:20
@@ -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);
-
-		/*
-		 * Have an xfer with an error; process it.
-		 */
-		(void) scsipi_complete(xs);
+		if (xs) {
+			TAILQ_REMOVE(&chan->chan_complete, xs, channel_q);
+			splx(s);
 
-		/*
-		 * Kick the queue; keep it running if it was stopped
-		 * for some reason.
-		 */
-		scsipi_run_queue(chan);
+			/*
+			 * 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);
+		} 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,46 @@
 	}
 }
 
+/*
+ * 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 clun, minlun, maxlun, error;
+
+	if (target == chan->chan_id)
+		return EINVAL;
+
+	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 (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:
Index: scsipiconf.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/scsipi/scsipiconf.h,v
retrieving revision 1.54
diff -u -r1.54 scsipiconf.h
--- scsipiconf.h	2001/06/26 15:32:02	1.54
+++ scsipiconf.h	2001/07/14 11:30:22
@@ -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 *));

--Q68bSM7Ycu6FN28Q--