- When allocating a scsipi_xfer, add it to the specified device's

pending_xfers queue.
- When freeing a scsipi_xfer, remove it from the device's pending_xfers
  queue.  If the queue is empty, and SDEV_WAITDRAIN is set, wakeup
  those waiting for the queue to drain.
- Implement scsipi_wait_drain(), which waits for a device's pending_xfers
  queue to drain.
This commit is contained in:
thorpej 1998-12-08 00:17:21 +00:00
parent 98194169ea
commit 1ddd2ffec0

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipi_base.c,v 1.14 1998/11/19 20:08:52 thorpej Exp $ */
/* $NetBSD: scsipi_base.c,v 1.15 1998/12/08 00:17:21 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -126,6 +126,7 @@ scsipi_get_xs(sc_link, flags)
*/
if (xs != NULL) {
xs->flags = INUSE | flags;
TAILQ_INSERT_TAIL(&sc_link->pending_xfers, xs, device_q);
bzero(&xs->cmdstore, sizeof(xs->cmdstore));
}
return (xs);
@ -145,6 +146,10 @@ scsipi_free_xs(xs, flags)
{
struct scsipi_link *sc_link = xs->sc_link;
TAILQ_REMOVE(&sc_link->pending_xfers, xs, device_q);
if (TAILQ_FIRST(&sc_link->pending_xfers) == NULL &&
(sc_link->flags & SDEV_WAITDRAIN) != 0)
wakeup(&sc_link->pending_xfers);
xs->flags &= ~INUSE;
pool_put(&scsipi_xfer_pool, xs);
@ -163,6 +168,31 @@ scsipi_free_xs(xs, flags)
}
}
/*
* Wait for a scsipi_link's pending xfers to drain.
*/
void
scsipi_wait_drain(sc_link)
struct scsipi_link *sc_link;
{
int s;
s = splbio();
if (TAILQ_FIRST(&sc_link->pending_xfers) != NULL) {
sc_link->flags |= SDEV_WAITDRAIN;
(void) tsleep(&sc_link->pending_xfers, PRIBIO, "sxdrn", 0);
sc_link->flags &= ~SDEV_WAITDRAIN;
}
#ifdef DIAGNOSTIC
if (TAILQ_FIRST(&sc_link->pending_xfers) != NULL) {
(*sc_link->sc_print_addr)(sc_link);
printf("still pending xfers after wait\n");
panic("scsipi_wait_drain");
}
#endif
splx(s);
}
/*
* Look at the returned sense and act on the error, determining
* the unix error number to pass back. (0 = report no error)