Subject: Re: kern/35071: panic: mpt_get_request: corrupted request free list (xfer)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: netbsd-bugs
Date: 12/02/2006 19:00:05
The following reply was made to PR kern/35071; it has been noted by GNATS.

From: Manuel Bouyer <bouyer@antioche.eu.org>
To: gnats-bugs@NetBSD.org
Cc: kern-bug-people@NetBSD.org, gnats-admin@NetBSD.org,
	netbsd-bugs@NetBSD.org, tjd-nb-pr@menelos.com
Subject: Re: kern/35071: panic: mpt_get_request: corrupted request free list (xfer)
Date: Sat, 2 Dec 2006 19:55:01 +0100

 --7AUc2qLy4jB3hD7Z
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 On Fri, Dec 01, 2006 at 03:20:02PM +0000, Tracy Di Marco White wrote:
 > The following reply was made to PR kern/35071; it has been noted by GNATS.
 > 
 > From: Tracy Di Marco White <tjd-nb-pr@menelos.com>
 > To: gnats-bugs@NetBSD.org
 > Cc: 
 > Subject: Re: kern/35071: panic: mpt_get_request: corrupted request free list (xfer) 
 > Date: Fri, 01 Dec 2006 09:15:43 -0600
 > 
 >  I seem to be getting this every day, or every other day.  So, more messages.
 >  
 >  st2: already open
 >  st0(mpt3:0:1:0): command timeout
 >  mpt3: timeout on request index = 0xfe, seq = 0x0133d791
 >  mpt3: Status 0x00000000, Mask 0x00000001, Doorbell 0x24000000
 >  mpt3: request state: On Chip
 >  mpt3: mpt_done: no scsipi_xfer, index = 0xfe, seq = 0x00000000
 >  mpt3: request state: Free
 
 OK, the command resets, and later the chip says it's complete while
 we've already freed it. I think we should just issue a bus reset
 (or bus_device_reset but it's harder to do) in case of timeout, and
 let the controller complete the commands.
 
 Attached is a patch that attemps to implement a bus_reset function for
 mpt(4). You can easily test by starting some I/O (e.g dd if=/dev/rsdxd
 of=/dev/null bs=1m) and while it's running issue several scsictl scsibusx reset
 
 I expect to see "IOC Bus Reset Port %d" or "External Bus Reset" on console
 
 -- 
 Manuel Bouyer <bouyer@antioche.eu.org>
      NetBSD: 26 ans d'experience feront toujours la difference
 --
 
 --7AUc2qLy4jB3hD7Z
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=diff
 
 Index: mpt_netbsd.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ic/mpt_netbsd.c,v
 retrieving revision 1.10
 diff -u -r1.10 mpt_netbsd.c
 --- mpt_netbsd.c	11 Dec 2005 12:21:28 -0000	1.10
 +++ mpt_netbsd.c	2 Dec 2006 18:50:50 -0000
 @@ -78,6 +78,7 @@
  __KERNEL_RCSID(0, "$NetBSD: mpt_netbsd.c,v 1.10 2005/12/11 12:21:28 christos Exp $");
  
  #include <dev/ic/mpt.h>			/* pulls in all headers */
 +#include <sys/scsiio.h>
  
  #include <machine/stdarg.h>		/* for mpt_prt() */
  
 @@ -89,10 +90,13 @@
  static void	mpt_get_xfer_mode(mpt_softc_t *, struct scsipi_periph *);
  static void	mpt_ctlop(mpt_softc_t *, void *vmsg, uint32_t);
  static void	mpt_event_notify_reply(mpt_softc_t *, MSG_EVENT_NOTIFY_REPLY *);
 +static void	mpt_bus_reset(mpt_softc_t *);
  
  static void	mpt_scsipi_request(struct scsipi_channel *,
  		    scsipi_adapter_req_t, void *);
  static void	mpt_minphys(struct buf *);
 +static int 	mpt_ioctl(struct scsipi_channel *, u_long, caddr_t, int,
 +			struct proc *);
  
  void
  mpt_scsipi_attach(mpt_softc_t *mpt)
 @@ -110,10 +114,11 @@
  	memset(adapt, 0, sizeof(*adapt));
  	adapt->adapt_dev = &mpt->sc_dev;
  	adapt->adapt_nchannels = 1;
 -	adapt->adapt_openings = maxq;
 -	adapt->adapt_max_periph = maxq;
 +	adapt->adapt_openings = maxq - 1; /* keep one for mngt reqs */
 +	adapt->adapt_max_periph = maxq - 1;
  	adapt->adapt_request = mpt_scsipi_request;
  	adapt->adapt_minphys = mpt_minphys;
 +	adapt->adapt_ioctl = mpt_ioctl;
  
  	/* Fill in the scsipi_channel. */
  	memset(chan, 0, sizeof(*chan));
 @@ -382,14 +387,15 @@
  	mpt_prt(mpt, "request state: %s", mpt_req_state(req->debug));
  	if (mpt->verbose > 1)
  		mpt_print_scsi_io_request((MSG_SCSI_IO_REQUEST *)req->req_vbuf);
 -
 +#if 0
  	/* XXX WHAT IF THE IOC IS STILL USING IT?? */
  	req->xfer = NULL;
  	mpt_free_request(mpt, req);
  
  	xs->error = XS_TIMEOUT;
  	scsipi_done(xs);
 -
 +#endif
 +	mpt_bus_reset(mpt);
  	splx(s);
  }
  
 @@ -461,6 +467,8 @@
  	if (__predict_false(mpt_req->Function == MPI_FUNCTION_SCSI_TASK_MGMT)) {
  		if (mpt->verbose > 1)
  			mpt_prt(mpt, "mpt_done: TASK MGMT");
 +		KASSERT(req == mpt->mngt_req);
 +		mpt->mngt_req = NULL;
  		goto done;
  	}
  
 @@ -1280,7 +1288,43 @@
  	}
  }
  
 -/* XXXJRT mpt_bus_reset() */
 +static void
 +mpt_bus_reset(mpt_softc_t *mpt)
 +{
 +	request_t *req;
 +	MSG_SCSI_TASK_MGMT *mngt_req;
 +	int s;
 +
 +	s = splbio();
 +	if (mpt->mngt_req) {
 +		/* request already queued; can't do more */
 +		splx(s);
 +		return;
 +	}
 +	req = mpt_get_request(mpt);
 +	if (__predict_false(req == NULL)) {
 +		printf("%s: no mngt request\n", mpt->sc_dev.dv_xname);
 +		splx(s);
 +		return;
 +	}
 +	mpt->mngt_req = req;
 +	splx(s);
 +	mngt_req = req->req_vbuf;
 +	memset(mngt_req, 0, sizeof(*mngt_req));
 +	mngt_req->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
 +	mngt_req->Bus = mpt->bus;
 +	mngt_req->TargetID = 0;
 +	mngt_req->ChainOffset = 0;
 +	mngt_req->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
 +	mngt_req->Reserved1 = 0;
 +	mngt_req->MsgFlags =
 +	    mpt->is_fc ? MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION : 0;
 +	mngt_req->MsgContext = req->index;
 +	mngt_req->TaskMsgContext = 0;
 +	s = splbio();
 +	mpt_send_cmd(mpt, req);
 +	splx(s);
 +}
  
  /*****************************************************************************
   * SCSI interface routines
 @@ -1322,3 +1366,19 @@
  		bp->b_bcount = MPT_MAX_XFER;
  	minphys(bp);
  }
 +
 +static int
 +mpt_ioctl(struct scsipi_channel *chan, u_long cmd, caddr_t arg,
 +    int flag, struct proc *p)
 +{
 +	struct scsipi_adapter *adapt = chan->chan_adapter;
 +	mpt_softc_t *mpt = (void *) adapt->adapt_dev;
 +
 +	switch (cmd) {
 +	case SCBUSIORESET:
 +		mpt_bus_reset(mpt);
 +		return(0);
 +	default:
 +		return (ENOTTY);
 +	}
 +}
 Index: mpt_netbsd.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/ic/mpt_netbsd.h,v
 retrieving revision 1.4
 diff -u -r1.4 mpt_netbsd.h
 --- mpt_netbsd.h	11 Dec 2005 12:21:28 -0000	1.4
 +++ mpt_netbsd.h	2 Dec 2006 18:50:50 -0000
 @@ -227,6 +227,7 @@
  	/* SCSIPI and software management */
  	request_t		*request_pool;
  	SLIST_HEAD(req_queue, req_entry) request_free_list;
 +	request_t		*mngt_req;
  
  	struct scsipi_adapter	sc_adapter;
  	struct scsipi_channel	sc_channel;
 
 --7AUc2qLy4jB3hD7Z--