Subject: Re: more new scsi midlayer questions
To: Matthew Jacob <mjacob@feral.com>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 05/22/2001 19:50:19
On Mon, May 21, 2001 at 08:39:20AM -0700, Matthew Jacob wrote:
> On Mon, 21 May 2001, Manuel Bouyer wrote:
> > > I think you're missing the point. The only mechanism with which
> > > scsipi_run_queue can be called now after a thaw is via the indirect softcall
> > > mechanism in scsipi_channel_thaw (which is exposed). I don't care whether
> > > scsipi_run_queue itself is private. I *do* care that you can't restart except
> > > via a softcall. That's just plain wrong when you've already got a per-HBA
> > > thread.
> >
> > This is why I propose to make scsipi_channel_thaw public, this once can be
> > called from your thread. But I don't think we should allow HBA drivers to
> > bypass the freeze/thaw mechanism; this will break if we want to change the
> > internals of scsipi.
>
> Oops- sorry! It's scspi_channel_timed_thaw that does the softcall...
>
> But scsipi_channel_thaw (which is public- I'm assuming that if it's in
> scsipiconf.h it's public) doesn't call scsipi_run_queue- all it does is
> decrement the qfreeze count.
>
> The freeze/thaw mechanism may not be entirely complete yet anyway-
>
> This is all coming up because I'm finally implementing a kthread to manage
> loop events. What I'm forced to do now because I do not know how many channel
> 'freeze' events I get but I do know when they should all thaw, is to do the
> following:
>
> case ISPASYNC_LIP:
> if (isp->isp_osinfo.blocked == 0) {
> isp->isp_osinfo.blocked = 1;
> scsipi_channel_freeze(&isp->isp_chanA, 1);
> }
> isp_prt(isp, ISP_LOGINFO, "LIP Received");
> break;
> case ISPASYNC_LOOP_RESET:
> if (isp->isp_osinfo.blocked == 0) {
> isp->isp_osinfo.blocked = 1;
> scsipi_channel_freeze(&isp->isp_chanA, 1);
> }
> isp_prt(isp, ISP_LOGINFO, "Loop Reset Received");
> break;
> case ISPASYNC_LOOP_DOWN:
> if (isp->isp_osinfo.blocked == 0) {
> isp->isp_osinfo.blocked = 1;
> scsipi_channel_freeze(&isp->isp_chanA, 1);
> }
> isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
> break;
> ...
> case ISPASYNC_CHANGE_NOTIFY:
> if (isp->isp_osinfo.blocked == 0) {
> isp->isp_osinfo.blocked = 1;
> scsipi_channel_freeze(&isp->isp_chanA, 1);
> }
> if (arg == ISPASYNC_CHANGE_PDB) {
> isp_prt(isp, ISP_LOGINFO, "Port Database Changed");
> } else if (arg == ISPASYNC_CHANGE_SNS) {
> isp_prt(isp, ISP_LOGINFO,
> "Name Server Database Changed");
> }
> /*
> * Note that we have work for the thread to do, and
> * if the thread is here already, wake it up.
> */
> isp->isp_osinfo.threadwork++;
> if (isp->isp_osinfo.thread) {
> wakeup(&isp->isp_osinfo.thread);
> }
> break;
>
> and then the last event is the one which allows me to fire up the loop cleanup
> thread, which when it gets done rebuilding loop state and (re)finding all
> devices, wants to thaw everything and call scsipi_run_queue directly so that
> things run now, darn it, not off of a softcall later:
>
> if (isp->isp_osinfo.blocked) {
> isp->isp_osinfo.blocked = 0;
> isp_prt(isp, ISP_LOGINFO, "restarting queues");
> isp->isp_chanA.chan_qfreeze = 0;
> scsipi_run_queue(&isp->isp_chanA);
> }
>
> The two latter line there are both layering violations. What I'd *really* like
> to see is:
>
> scsipi_channel_thaw(&isp->isp_chanA, -1);
>
> to be taken as:
>
> zero freeze count (-1 count argument)
I don't think this is good. The channel may have been frozen by something
else inside scsipi too; we don't want to drop it.
You should keep track on how many times you call scsipi_channel_freeze()
in the driver, and use the count for scsipi_channel_thaw().
I'll look at calling scsipi_run_queue() from scsipi_channel_thaw() when the
count drops to 0.
--
Manuel Bouyer <bouyer@antioche.eu.org>
--