Subject: Draining after adjusting max openings -- not necessary?
To: None <tech-kern@netbsd.org>
From: Jason Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 06/07/2003 20:36:59
--Apple-Mail-2--573191644
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Folks...

Right now, the ld(4) driver (and some associated drivers, namely 
iopsp(4)) wait for commands beyond the new command window to complete 
if adjusting the new # of command openings below the number of current 
commands running.

I don't think this is necessary... certainly, the scsipi code can 
handle the openings count going negative, and a simple change to the ld 
driver allows the same thing to happen there (moving the 
"wait-for-drain" to the place where it's really needed, during detach).

There is also a problem with adjusting the openings in the iopsp(4) 
case.  Since adapt_openings actually changes, you can't simply assign a 
new value to it in iopsp_adjqparam().  Instead, you must adjust 
adapt_openings by the difference between the new and old openings value.

Attached is a patch that addresses both issues.  Anyone see any 
problems with these changes?

         -- Jason R. Thorpe <thorpej@wasabisystems.com>


--Apple-Mail-2--573191644
Content-Disposition: attachment;
	filename=lddrain-patch
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="lddrain-patch"

Index: ld.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ld.c,v
retrieving revision 1.23
diff -c -r1.23 ld.c
*** ld.c	2003/06/07 23:37:24	1.23
--- ld.c	2003/06/08 03:34:47
***************
*** 157,175 ****
  int
  ldadjqparam(struct ld_softc *sc, int max)
  {
! 	int s, rv;
  
  	s = splbio();
  	sc->sc_maxqueuecnt = max;
- 	if (sc->sc_queuecnt > max) {
- 		sc->sc_flags |= LDF_DRAIN;
- 		rv = tsleep(&sc->sc_queuecnt, PRIBIO, "lddrn", 30 * hz);
- 		sc->sc_flags &= ~LDF_DRAIN;
- 	} else
- 		rv = 0;
  	splx(s);
  
! 	return (rv);
  }
  
  int
--- 157,169 ----
  int
  ldadjqparam(struct ld_softc *sc, int max)
  {
! 	int s;
  
  	s = splbio();
  	sc->sc_maxqueuecnt = max;
  	splx(s);
  
! 	return (0);
  }
  
  int
***************
*** 184,191 ****
  		return (EBUSY);
  
  	s = splbio();
  	sc->sc_flags |= LDF_DETACH;
! 	rv = ldadjqparam(sc, 0);
  	splx(s);
  
  	return (rv);
--- 178,189 ----
  		return (EBUSY);
  
  	s = splbio();
+ 	sc->sc_maxqueuecnt = 0;
  	sc->sc_flags |= LDF_DETACH;
! 	while (sc->sc_queuecnt > 0) {
! 		sc->sc_flags |= LDF_DRAIN;
! 		(void) tsleep(&sc->sc_queuecnt, PRIBIO, "lddrn", 0);
! 	}
  	splx(s);
  
  	return (rv);
***************
*** 597,604 ****
  	biodone(bp);
  
  	if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) {
! 		if ((sc->sc_flags & LDF_DRAIN) != 0)
  			wakeup(&sc->sc_queuecnt);
  		ldstart(sc);
  	}
  }
--- 595,604 ----
  	biodone(bp);
  
  	if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) {
! 		if ((sc->sc_flags & LDF_DRAIN) != 0) {
! 			sc->sc_flags &= ~LDF_DRAIN;
  			wakeup(&sc->sc_queuecnt);
+ 		}
  		ldstart(sc);
  	}
  }
Index: i2o/iopsp.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2o/iopsp.c,v
retrieving revision 1.17
diff -c -r1.17 iopsp.c
*** i2o/iopsp.c	2002/12/06 11:22:25	1.17
--- i2o/iopsp.c	2003/06/08 03:34:48
***************
*** 410,416 ****
  	struct iop_msg *im;
  	struct iop_softc *iop;
  	struct i2o_scsi_scb_exec *mf;
! 	int error, flags, tid, s;
  	u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
  
  	sc = (void *)chan->chan_adapter->adapt_dev;
--- 410,416 ----
  	struct iop_msg *im;
  	struct iop_softc *iop;
  	struct i2o_scsi_scb_exec *mf;
! 	int error, flags, tid;
  	u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
  
  	sc = (void *)chan->chan_adapter->adapt_dev;
***************
*** 496,509 ****
  				mf->flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE;
  		}
  
- 		s = splbio();
- 		sc->sc_curqd++;
- 		splx(s);
- 
  		if (iop_msg_post(iop, im, mb, xs->timeout)) {
- 			s = splbio();
- 			sc->sc_curqd--;
- 			splx(s);
  			if (xs->datalen != 0)
  				iop_msg_unmap(iop, im);
  			iop_msg_free(iop, im);
--- 496,502 ----
***************
*** 631,639 ****
  		iop_msg_unmap(iop, im);
  	iop_msg_free(iop, im);
  
- 	if (--sc->sc_curqd == sc->sc_adapter.adapt_openings)
- 		wakeup(&sc->sc_curqd);
- 
  	scsipi_done(xs);
  }
  
--- 624,629 ----
***************
*** 680,687 ****
  	sc = (struct iopsp_softc *)dv;
  
  	s = splbio();
! 	sc->sc_adapter.adapt_openings = mpi;
! 	if (mpi < sc->sc_curqd)
! 		tsleep(&sc->sc_curqd, PWAIT, "iopspdrn", 0);
  	splx(s);
  }
--- 670,676 ----
  	sc = (struct iopsp_softc *)dv;
  
  	s = splbio();
! 	sc->sc_adapter.adapt_openings += mpi - sc->sc_openings;
! 	sc->sc_openings = mpi;
  	splx(s);
  }
Index: i2o/iopspvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2o/iopspvar.h,v
retrieving revision 1.5
diff -c -r1.5 iopspvar.h
*** i2o/iopspvar.h	2001/08/04 16:54:18	1.5
--- i2o/iopspvar.h	2003/06/08 03:34:48
***************
*** 64,70 ****
  	struct	iop_initiator sc_ii;		/* I2O initiator state */
  	u_short	*sc_tidmap;			/* Target/LUN -> TID map */
  	u_int	sc_chgind;			/* Last LCT change # */
! 	u_int	sc_curqd;			/* Current queue depth */
  #ifdef I2OVERBOSE
  	struct	iopsp_target *sc_targetmap;	/* Target information */
  #endif
--- 64,70 ----
  	struct	iop_initiator sc_ii;		/* I2O initiator state */
  	u_short	*sc_tidmap;			/* Target/LUN -> TID map */
  	u_int	sc_chgind;			/* Last LCT change # */
! 	int	sc_openings;			/* # command openings */
  #ifdef I2OVERBOSE
  	struct	iopsp_target *sc_targetmap;	/* Target information */
  #endif

--Apple-Mail-2--573191644--