this diff starts to address several problems i have with the scsi
midlayer.
the most important at the moment is that the entrypoint into the
current midlayer is through a function called scsi_scsi_cmd. the
problem with this function is that it is impossible to start an
async scsi operation and then tell if the command has failed,
completed, or been queued without shoving a buf down with it.
this sucks for mpath because it simply wants to take commands from
sd/cd/etc and push them down a real physical path. the buf handling
will be done by the sd to mpath leg of the journey, trying to do
it again on the mpath to mpi/isp/etc leg of the journey will cause
a use after free.
this lets drivers like sd/cd/mpath allocate an xs, fill it in, and
supply a completion routine for it. in the mpath case this completion
routine goes on and completes the io it was asked to do on cd/sd/etc's
behalf.
i have tweaked sd to use this new interface too to verify it is
usable. i have also reimplimented scsi_scsi_cmd to retain backward
compat for old users (currently everything except sd).
these changes clear the way to make a hbas scsi_cmd routine not
need to return an error code, in the future the ability of the hba
to complete an xs will be reported by changing the state of the xs
and completing it. there is a huge amount of confusion in hba drivers
at the moment about the right way to report errors up to the midlayer
and then in turn up to the device drivers. forcing all reporting
to be done via the xs will simplify code hugely and make it more
robust.
the last benefit is this makes it easier to allow the hba to provide
the xs to cd/sd/mpath/etc.
i encourage everyone to test this diff and tell me what blows up.
Index: mpath.c
===================================================================
RCS file: /cvs/src/sys/scsi/mpath.c,v
retrieving revision 1.3
diff -u -p -r1.3 mpath.c
--- mpath.c 9 Aug 2009 16:55:02 -0000 1.3
+++ mpath.c 11 Aug 2009 14:24:59 -0000
@@ -78,6 +78,8 @@ int mpath_cmd(struct scsi_xfer *);
void mpath_minphys(struct buf *, struct scsi_link *);
int mpath_probe(struct scsi_link *);
+void mpath_done(struct scsi_xfer *);
+
struct scsi_adapter mpath_switch = {
mpath_cmd,
scsi_minphys,
@@ -148,36 +150,53 @@ mpath_cmd(struct scsi_xfer *xs)
struct scsi_link *link = xs->sc_link;
struct mpath_node *n = mpath_nodes[link->target];
struct mpath_path *p = TAILQ_FIRST(&n->node_paths);
- int rv;
- int s;
+ struct scsi_xfer *mxs;
if (n == NULL || p == NULL) {
mpath_xs_stuffup(xs);
return (COMPLETE);
}
- rv = scsi_scsi_cmd(p->path_link, xs->cmd, xs->cmdlen,
- xs->data, xs->datalen,
- 2, xs->timeout, NULL, SCSI_POLL |
- (xs->flags & (SCSI_DATA_IN|SCSI_DATA_OUT)));
+ mxs = scsi_xs_get(p->path_link, xs->flags);
+ if (mxs == NULL) {
+ mpath_xs_stuffup(xs);
+ return (COMPLETE);
+ }
+ memcpy(mxs->cmd, xs->cmd, xs->cmdlen);
+ mxs->cmdlen = xs->cmdlen;
+ mxs->data = xs->data;
+ mxs->datalen = xs->datalen;
+ mxs->retries = xs->retries;
+ mxs->timeout = xs->timeout;
+ mxs->req_sense_length = xs->req_sense_length;
- xs->flags |= ITSDONE;
- if (rv == 0) {
- xs->error = XS_NOERROR;
- xs->status = SCSI_OK;
- xs->resid = 0;
- } else {
- printf("%s: t%dl%d rv %d cmd %x\n", DEVNAME(mpath),
- link->target, link->lun, rv, xs->cmd->opcode);
- xs->error = XS_DRIVER_STUFFUP;
- }
+ mxs->cookie = xs;
+ mxs->done = mpath_done;
+
+ scsi_xs_exec(mxs);
+
+ return (COMPLETE); /* doesnt matter anymore */
+}
+
+void
+mpath_done(struct scsi_xfer *mxs)
+{
+ struct scsi_xfer *xs = mxs->cookie;
+ int s;
+
+ xs->error = mxs->error;
+ xs->status = mxs->status;
+ xs->flags = mxs->flags;
+ xs->resid = mxs->resid;
+
+ memcpy(&xs->sense, &mxs->sense, sizeof(xs->sense));
+
+ scsi_xs_put(mxs);
s = splbio();
scsi_done(xs);
splx(s);
-
- return (COMPLETE);
}
void
Index: scsi_base.c
===================================================================
RCS file: /cvs/src/sys/scsi/scsi_base.c,v
retrieving revision 1.132
diff -u -p -r1.132 scsi_base.c
--- scsi_base.c 2 Jun 2009 06:33:04 -0000 1.132
+++ scsi_base.c 11 Aug 2009 14:24:59 -0000
@@ -50,15 +50,14 @@
#include <scsi/scsi_disk.h>
#include <scsi/scsiconf.h>
-static __inline struct scsi_xfer *scsi_make_xs(struct scsi_link *,
- struct scsi_generic *, int cmdlen, u_char *data_addr,
- int datalen, int retries, int timeout, struct buf *, int flags);
static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result,
size_t len);
int sc_err1(struct scsi_xfer *);
int scsi_interpret_sense(struct scsi_xfer *);
char *scsi_decode_sense(struct scsi_sense_data *, int);
+void scsi_xs_done(struct scsi_xfer *);
+
/* Values for flag parameter to scsi_decode_sense. */
#define DECODE_SENSE_KEY 1
#define DECODE_ASC_ASCQ 2
@@ -84,6 +83,7 @@ scsi_init()
/* Initialize the scsi_xfer pool. */
pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0,
0, 0, "scxspl", NULL);
+ pool_setipl(&scsi_xfer_pool, IPL_BIO);
}
void
@@ -105,42 +105,43 @@ scsi_deinit()
*/
struct scsi_xfer *
-scsi_get_xs(struct scsi_link *sc_link, int flags)
+scsi_xs_get(struct scsi_link *link, int flags)
{
- struct scsi_xfer *xs;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("scsi_get_xs\n"));
+ struct scsi_xfer *xs;
- s = splbio();
- while (sc_link->openings == 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
- if ((flags & SCSI_NOSLEEP) != 0) {
- splx(s);
- return (NULL);
- }
- sc_link->flags |= SDEV_WAITING;
- if (tsleep(sc_link, PRIBIO|PCATCH, "getxs", 0)) {
- /* Bail out on getting a signal. */
- sc_link->flags &= ~SDEV_WAITING;
- splx(s);
+ mtx_enter(&link->mtx);
+ while (link->openings == 0) {
+ if (!ISSET(flags, SCSI_NOSLEEP)) {
+ mtx_leave(&link->mtx);
return (NULL);
}
+
+ SET(link->flags, SDEV_WAITING);
+ msleep(link, &link->mtx, PRIBIO, "getxs", 0);
}
- SC_DEBUG(sc_link, SDEV_DB3, ("calling pool_get\n"));
+ link->openings--;
+ mtx_leave(&link->mtx);
+
+ /* pool is shared, link mtx is not */
xs = pool_get(&scsi_xfer_pool,
- ((flags & SCSI_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK));
- if (xs != NULL) {
- bzero(xs, sizeof(*xs));
- sc_link->openings--;
- xs->flags = flags;
+ ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK);
+ if (xs == NULL) {
+ mtx_enter(&link->mtx);
+ link->openings++;
+ mtx_leave(&link->mtx);
} else {
- sc_print_addr(sc_link);
- printf("cannot allocate scsi xs\n");
+ xs->flags = flags;
+ xs->sc_link = link;
+ xs->retries = SCSI_RETRIES;
+ xs->timeout = 0;
+ bzero(&xs->cmdstore, sizeof(xs->cmdstore));
+ xs->cmd = &xs->cmdstore;
+ xs->cmdlen = 0;
+ xs->data = NULL;
+ xs->datalen = 0;
+ xs->resid = 0;
+ xs->bp = NULL;
}
- splx(s);
-
- SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
return (xs);
}
@@ -151,75 +152,21 @@ scsi_get_xs(struct scsi_link *sc_link, i
* If another process is waiting for an xs, do a wakeup, let it proceed
*/
void
-scsi_free_xs(struct scsi_xfer *xs, int start)
+scsi_xs_put(struct scsi_xfer *xs)
{
- struct scsi_link *sc_link = xs->sc_link;
-
- splassert(IPL_BIO);
-
- SC_DEBUG(sc_link, SDEV_DB3, ("scsi_free_xs\n"));
+ struct scsi_link *link = xs->sc_link;
pool_put(&scsi_xfer_pool, xs);
- sc_link->openings++;
+
+ mtx_enter(&link->mtx);
+ link->openings++;
/* If someone is waiting for scsi_xfer, wake them up. */
- if ((sc_link->flags & SDEV_WAITING) != 0) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup(sc_link);
- } else if (start && sc_link->device->start) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("calling private start()\n"));
- (*(sc_link->device->start)) (sc_link->device_softc);
+ if (ISSET(link->flags, SDEV_WAITING)) {
+ CLR(link->flags, SDEV_WAITING);
+ wakeup(link);
}
-}
-
-/*
- * Make a scsi_xfer, and return a pointer to it.
- */
-static __inline struct scsi_xfer *
-scsi_make_xs(struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
- int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
- struct buf *bp, int flags)
-{
- struct scsi_xfer *xs;
-
- if ((xs = scsi_get_xs(sc_link, flags)) == NULL)
- return (NULL);
-
- /*
- * Fill out the scsi_xfer structure. We don't know whose context
- * the cmd is in, so copy it.
- */
- xs->sc_link = sc_link;
- bcopy(scsi_cmd, &xs->cmdstore, cmdlen);
- xs->cmd = &xs->cmdstore;
- xs->cmdlen = cmdlen;
- xs->data = data_addr;
- xs->datalen = datalen;
- xs->retries = retries;
- xs->timeout = timeout;
- xs->bp = bp;
-
- /*
- * Set the LUN in the CDB if it fits in the three bits available. This
- * may only be needed if we have an older device. However, we also set
- * it for more modern SCSI devices "just in case". The old code
- * assumed everything newer than SCSI-2 would not need it, but why risk
- * it? This was the old conditional:
- *
- * if ((SCSISPC(sc_link->inqdata.version) <= 2))
- */
- xs->cmd->bytes[0] &= ~SCSI_CMD_LUN_MASK;
- if (sc_link->lun < 8)
- xs->cmd->bytes[0] |= ((sc_link->lun << SCSI_CMD_LUN_SHIFT) &
- SCSI_CMD_LUN_MASK);
-
-#ifdef SCSIDEBUG
- if ((sc_link->flags & SDEV_DB1) != 0)
- show_scsi_xs(xs);
-#endif /* SCSIDEBUG */
-
- return (xs);
+ mtx_leave(&link->mtx);
}
/*
@@ -681,179 +628,58 @@ scsi_report_luns(struct scsi_link *sc_li
return (error);
}
+void
+scsi_xs_exec(struct scsi_xfer *xs)
+{
+ int rv;
+ int s;
+
+ xs->flags &= ~ITSDONE;
+ xs->error = XS_NOERROR;
+ xs->resid = xs->datalen;
+ xs->status = 0;
+
+ rv = xs->sc_link->adapter->scsi_cmd(xs);
+ switch (rv) {
+ case NO_CCB:
+ if (!ISSET(xs->flags, SCSI_POLL) && xs->retries-- > 0) {
+ timeout_set(&xs->stimeout,
+ (void (*)(void *))scsi_xs_exec, xs);
+ timeout_add(&xs->stimeout, 1);
+ break;
+ }
+ /* FALLTHROUGH */
+ case TRY_AGAIN_LATER:
+ /* hahaha, sif... */
+
+ xs->error = XS_DRIVER_STUFFUP;
+ xs->flags |= ITSDONE;
+ s = splbio();
+ scsi_done(xs);
+ splx(s);
+ break;
+ }
+}
+
/*
- * This routine is called by the scsi interrupt when the transfer is complete.
+ * This routine is called by the adapter when its xs handling is done.
*/
void
scsi_done(struct scsi_xfer *xs)
{
- struct scsi_link *sc_link = xs->sc_link;
- struct buf *bp;
- int error;
-
splassert(IPL_BIO);
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
-
/*
* If it's a user level request, bypass all usual completion processing,
* let the user work it out.. We take reponsibility for freeing the
* xs when the user returns (and restarting the device's queue).
*/
if ((xs->flags & SCSI_USER) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
scsi_user_done(xs); /* to take a copy of the sense etc. */
- SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n"));
-
- scsi_free_xs(xs, 1); /* restarts queue too */
- SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
return;
}
- if (!((xs->flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)) {
- /*
- * if it's a normal upper level request, then ask
- * the upper level code to handle error checking
- * rather than doing it here at interrupt time
- */
- wakeup(xs);
- return;
- }
-
- /*
- * Go and handle errors now.
- * If it returns ERESTART then we should RETRY
- */
-retry:
- error = sc_err1(xs);
- if (error == ERESTART) {
- switch ((*(sc_link->adapter->scsi_cmd)) (xs)) {
- case SUCCESSFULLY_QUEUED:
- return;
-
- case TRY_AGAIN_LATER:
- xs->error = XS_BUSY;
- /* FALLTHROUGH */
- case COMPLETE:
- goto retry;
- }
- }
-
- bp = xs->bp;
- if (bp != NULL) {
- if (error) {
- bp->b_error = error;
- bp->b_flags |= B_ERROR;
- bp->b_resid = bp->b_bcount;
- } else {
- bp->b_error = 0;
- bp->b_resid = xs->resid;
- }
- }
-
- if (sc_link->device->done) {
- /*
- * Tell the device the operation is actually complete.
- * No more will happen with this xfer. This for
- * notification of the upper-level driver only; they
- * won't be returning any meaningful information to us.
- */
- (*sc_link->device->done)(xs);
- }
- scsi_free_xs(xs, 1);
- if (bp != NULL)
- biodone(bp);
-}
-
-int
-scsi_execute_xs(struct scsi_xfer *xs)
-{
- int error, flags, rslt, s;
-
- xs->flags &= ~ITSDONE;
- xs->error = XS_NOERROR;
- xs->resid = xs->datalen;
- xs->status = 0;
-
- /*
- * Do the transfer. If we are polling we will return:
- * COMPLETE, Was poll, and scsi_done has been called
- * TRY_AGAIN_LATER, Adapter short resources, try again
- *
- * if under full steam (interrupts) it will return:
- * SUCCESSFULLY_QUEUED, will do a wakeup when complete
- * TRY_AGAIN_LATER, (as for polling)
- * After the wakeup, we must still check if it succeeded
- *
- * If we have a SCSI_NOSLEEP (typically because we have a buf)
- * we just return. All the error processing and the buffer
- * code both expect us to return straight to them, so as soon
- * as the command is queued, return.
- */
-
- /*
- * We save the flags here because the xs structure may already
- * be freed by scsi_done by the time adapter->scsi_cmd returns.
- *
- * scsi_done is responsible for freeing the xs if either
- * (flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP
- * -or-
- * (flags & SCSI_USER) != 0
- *
- * Note: SCSI_USER must always be called with SCSI_NOSLEEP
- * and never with SCSI_POLL, so the second expression should be
- * is equivalent to the first.
- */
-
- flags = xs->flags;
-#ifdef DIAGNOSTIC
- if ((flags & (SCSI_USER | SCSI_NOSLEEP)) == SCSI_USER)
- panic("scsi_execute_xs: USER without NOSLEEP");
- if ((flags & (SCSI_USER | SCSI_POLL)) == (SCSI_USER | SCSI_POLL))
- panic("scsi_execute_xs: USER with POLL");
-#endif
-retry:
- rslt = (*(xs->sc_link->adapter->scsi_cmd))(xs);
- switch (rslt) {
- case SUCCESSFULLY_QUEUED:
- if ((flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)
- return (EJUSTRETURN);
-#ifdef DIAGNOSTIC
- if (flags & SCSI_NOSLEEP)
- panic("scsi_execute_xs: NOSLEEP and POLL");
-#endif
- s = splbio();
- /* Since the xs is active we can't bail out on a signal. */
- while ((xs->flags & ITSDONE) == 0)
- tsleep(xs, PRIBIO + 1, "scsicmd", 0);
- splx(s);
- /* FALLTHROUGH */
- case COMPLETE: /* Polling command completed ok */
- if ((flags & (SCSI_NOSLEEP | SCSI_POLL)) == SCSI_NOSLEEP)
- return (EJUSTRETURN);
- if (xs->bp)
- return (EJUSTRETURN);
- doit:
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("back in cmd()\n"));
- if ((error = sc_err1(xs)) != ERESTART)
- return (error);
- goto retry;
-
- case TRY_AGAIN_LATER: /* adapter resource shortage */
- xs->error = XS_BUSY;
- goto doit;
-
- case NO_CCB:
- return (EAGAIN);
-
- default:
- panic("scsi_execute_xs: invalid return code (%#x)", rslt);
- }
-
-#ifdef DIAGNOSTIC
- panic("scsi_execute_xs: impossible");
-#endif
- return (EINVAL);
+ xs->done(xs);
}
/*
@@ -863,54 +689,79 @@ retry:
* to associate with the transfer, we need that too.
*/
int
-scsi_scsi_cmd(struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
+scsi_scsi_cmd(struct scsi_link *link, struct scsi_generic *scsi_cmd,
int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
struct buf *bp, int flags)
{
- struct scsi_xfer *xs;
- int error;
- int s;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
+ struct scsi_xfer *xs;
+ int error;
+ int s;
#ifdef DIAGNOSTIC
if (bp != NULL && (flags & SCSI_NOSLEEP) == 0)
panic("scsi_scsi_cmd: buffer without nosleep");
#endif
- if ((xs = scsi_make_xs(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
- retries, timeout, bp, flags)) == NULL)
+ xs = scsi_xs_get(link, flags);
+ if (xs == NULL)
return (ENOMEM);
-#ifdef SCSIDEBUG
- if ((sc_link->flags & SDEV_DB1) != 0)
- if (xs->datalen && (xs->flags & SCSI_DATA_OUT))
- show_mem(xs->data, min(64, xs->datalen));
-#endif /* SCSIDEBUG */
-
- error = scsi_execute_xs(xs);
-
-#ifdef SCSIDEBUG
- if ((sc_link->flags & SDEV_DB1) != 0)
- if (xs->datalen && (xs->flags & SCSI_DATA_IN))
- show_mem(xs->data, min(64, xs->datalen));
-#endif /* SCSIDEBUG */
+ memcpy(xs->cmd, scsi_cmd, cmdlen);
+ xs->cmdlen = cmdlen;
+ xs->data = data_addr;
+ xs->datalen = datalen;
+ xs->retries = retries;
+ xs->timeout = timeout;
- if (error == EJUSTRETURN)
- return (0);
+ xs->done = scsi_xs_done;
- s = splbio();
+ do {
+ scsi_xs_exec(xs);
+ if (!ISSET(xs->flags, SCSI_POLL)) {
+ while (!ISSET(xs->flags, ITSDONE))
+ tsleep(xs, PRIBIO, "scsicmd", 0);
+ }
- if (error == EAGAIN)
- scsi_free_xs(xs, 0); /* Don't restart queue. */
- else
- scsi_free_xs(xs, 1);
+ error = sc_err1(xs);
+ } while (error == ERESTART);
- splx(s);
+ if (bp != NULL) {
+ if (error) {
+ bp->b_error = error;
+ bp->b_flags |= B_ERROR;
+ bp->b_resid = bp->b_bcount;
+ } else {
+ bp->b_error = 0;
+ bp->b_resid = xs->resid;
+ }
+
+ s = splbio();
+ biodone(bp);
+ splx(s);
+ }
+
+ if (link->device->done) {
+ /*
+ * Tell the device the operation is actually complete.
+ * No more will happen with this xfer. This for
+ * notification of the upper-level driver only; they
+ * won't be returning any meaningful information to us.
+ */
+ link->device->done(xs);
+ }
+
+ scsi_xs_put(xs);
return (error);
}
+void
+scsi_xs_done(struct scsi_xfer *xs)
+{
+ if (!ISSET(xs->flags, SCSI_POLL))
+ wakeup_one(xs);
+}
+
int
sc_err1(struct scsi_xfer *xs)
{
@@ -1030,10 +881,6 @@ scsi_interpret_sense(struct scsi_xfer *x
sense->flags & SSD_EOM ? 1 : 0,
sense->flags & SSD_FILEMARK ? 1 : 0,
sense->extra_len));
-#ifdef SCSIDEBUG
- if ((sc_link->flags & SDEV_DB1) != 0)
- show_mem((u_char *)&xs->sense, sizeof xs->sense);
-#endif /* SCSIDEBUG */
/*
* If the device has its own error handler, call it first.
@@ -1926,57 +1773,3 @@ scsi_decode_sense(struct scsi_sense_data
return (rqsbuf);
}
-
-#ifdef SCSIDEBUG
-/*
- * Given a scsi_xfer, dump the request, in all its glory
- */
-void
-show_scsi_xs(struct scsi_xfer *xs)
-{
- u_char *b = (u_char *) xs->cmd;
- int i = 0;
-
- sc_print_addr(xs->sc_link);
-
- printf("xs(%p): ", xs);
-
- printf("flg(0x%x)", xs->flags);
- printf("sc_link(%p)", xs->sc_link);
- printf("retr(0x%x)", xs->retries);
- printf("timo(0x%x)", xs->timeout);
- printf("cmd(%p)", xs->cmd);
- printf("len(0x%x)", xs->cmdlen);
- printf("data(%p)", xs->data);
- printf("len(0x%x)", xs->datalen);
- printf("res(0x%x)", xs->resid);
- printf("err(0x%x)", xs->error);
- printf("bp(%p)\n", xs->bp);
-
- printf("command: ");
-
- if ((xs->flags & SCSI_RESET) == 0) {
- while (i < xs->cmdlen) {
- if (i)
- printf(",");
- printf("%x", b[i++]);
- }
- printf("-[%d bytes]\n", xs->datalen);
- } else
- printf("-RESET-\n");
-}
-
-void
-show_mem(u_char *address, int num)
-{
- int x;
-
- printf("------------------------------");
- for (x = 0; x < num; x++) {
- if ((x % 16) == 0)
- printf("\n%03d: ", x);
- printf("%02x ", *address++);
- }
- printf("\n------------------------------\n");
-}
-#endif /* SCSIDEBUG */
Index: scsiconf.c
===================================================================
RCS file: /cvs/src/sys/scsi/scsiconf.c,v
retrieving revision 1.142
diff -u -p -r1.142 scsiconf.c
--- scsiconf.c 10 Aug 2009 11:02:38 -0000 1.142
+++ scsiconf.c 11 Aug 2009 14:24:59 -0000
@@ -738,6 +738,7 @@ scsi_probedev(struct scsibus_softc *scsi
sc_link->target = target;
sc_link->lun = lun;
sc_link->device = &probe_switch;
+ mtx_init(&sc_link->mtx, IPL_BIO);
inqbuf = &sc_link->inqdata;
SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n"));
Index: scsiconf.h
===================================================================
RCS file: /cvs/src/sys/scsi/scsiconf.h,v
retrieving revision 1.99
diff -u -p -r1.99 scsiconf.h
--- scsiconf.h 9 Aug 2009 12:47:23 -0000 1.99
+++ scsiconf.h 11 Aug 2009 14:24:59 -0000
@@ -53,6 +53,7 @@
#include <sys/queue.h>
#include <sys/timeout.h>
#include <sys/workq.h>
+#include <sys/mutex.h>
#include <machine/cpu.h>
#include <scsi/scsi_debug.h>
@@ -369,6 +370,7 @@ struct scsi_link {
struct scsibus_softc *bus; /* link to the scsibus we're on */
struct scsi_inquiry_data inqdata; /* copy of INQUIRY data from probe */
struct devid id;
+ struct mutex mtx;
};
int scsiprint(void *, const char *);
@@ -444,6 +446,8 @@ struct scsi_xfer {
* timeout structure for hba's to use for a command
*/
struct timeout stimeout;
+ void *cookie;
+ void (*done)(struct scsi_xfer *);
};
/*
@@ -556,6 +560,10 @@ int scsi_detach_lun(struct scsibus_softc
extern const u_int8_t version_to_spc[];
#define SCSISPC(x)(version_to_spc[(x) & SID_ANSII])
+
+struct scsi_xfer * scsi_xs_get(struct scsi_link *, int);
+void scsi_xs_exec(struct scsi_xfer *);
+void scsi_xs_put(struct scsi_xfer *);
/*
* Entrypoints for multipathing
Index: sd.c
===================================================================
RCS file: /cvs/src/sys/scsi/sd.c,v
retrieving revision 1.156
diff -u -p -r1.156 sd.c
--- sd.c 17 Jun 2009 01:30:30 -0000 1.156
+++ sd.c 11 Aug 2009 14:25:00 -0000
@@ -83,10 +83,7 @@ int sddetach(struct device *, int);
void sdminphys(struct buf *);
void sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, int);
void sdstart(void *);
-void sdrestart(void *);
-void sddone(struct scsi_xfer *);
void sd_shutdown(void *);
-int sd_reassign_blocks(struct sd_softc *, u_long);
int sd_interpret_sense(struct scsi_xfer *);
int sd_get_parms(struct sd_softc *, struct disk_parms *, int);
void sd_flush(struct sd_softc *, int);
@@ -111,7 +108,7 @@ struct scsi_device sd_switch = {
sd_interpret_sense, /* check out error handler first */
sdstart, /* have a queue, served by this */
NULL, /* have no async handler */
- sddone, /* deal with stats at interrupt time */
+ NULL, /* have no done handler */
};
const struct scsi_inquiry_pattern sd_patterns[] = {
@@ -163,6 +160,8 @@ sdattach(struct device *parent, struct d
SC_DEBUG(sc_link, SDEV_DB2, ("sdattach:\n"));
+ mtx_init(&sd->sc_buf_mtx, IPL_BIO);
+
/*
* Store information needed to contact our base driver
*/
@@ -197,7 +196,7 @@ sdattach(struct device *parent, struct d
*/
printf("\n");
- timeout_set(&sd->sc_timeout, sdrestart, sd);
+ timeout_set(&sd->sc_timeout, sdstart, sd);
/* Spin up non-UMASS devices ready or not. */
if ((sd->sc_link->flags & SDEV_UMASS) == 0)
@@ -553,7 +552,7 @@ sdstrategy(struct buf *bp)
/*
* Place it in the queue of disk activities for this disk
*/
- disksort(&sd->buf_queue, bp);
+ disksort(&sd->sc_buf_queue, bp);
/*
* Tell the device to get going on the transfer if it's
@@ -580,6 +579,89 @@ done:
device_unref(&sd->sc_dev);
}
+struct buf *sd_buf_dequeue(struct sd_softc *);
+void sd_buf_requeue(struct sd_softc *, struct buf *);
+
+struct buf *
+sd_buf_dequeue(struct sd_softc *sc)
+{
+ struct buf *bp;
+
+ mtx_enter(&sc->sc_buf_mtx);
+ bp = sc->sc_buf_queue.b_actf;
+ if (bp != NULL)
+ sc->sc_buf_queue.b_actf = bp->b_actf;
+ mtx_leave(&sc->sc_buf_mtx);
+
+ return (bp);
+}
+
+void
+sd_buf_requeue(struct sd_softc *sc, struct buf *bp)
+{
+ mtx_enter(&sc->sc_buf_mtx);
+ bp->b_actf = sc->sc_buf_queue.b_actf;
+ sc->sc_buf_queue.b_actf = bp;
+ mtx_leave(&sc->sc_buf_mtx);
+}
+
+void
+sd_cmd_rw6(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks);
+void
+sd_cmd_rw6(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
+{
+ struct scsi_rw *cmd = (struct scsi_rw *)xs->cmd;
+
+ cmd->opcode = read ? READ_COMMAND : WRITE_COMMAND;
+ _lto3b(blkno, cmd->addr);
+ cmd->length = nblks;
+
+ xs->cmdlen = sizeof(*cmd);
+}
+
+void
+sd_cmd_rw10(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks);
+void
+sd_cmd_rw10(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
+{
+ struct scsi_rw_big *cmd = (struct scsi_rw_big *)xs->cmd;
+
+ cmd->opcode = read ? READ_BIG : WRITE_BIG;
+ _lto4b(blkno, cmd->addr);
+ _lto2b(nblks, cmd->length);
+
+ xs->cmdlen = sizeof(*cmd);
+}
+
+void
+sd_cmd_rw12(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks);
+void
+sd_cmd_rw12(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
+{
+ struct scsi_rw_12 *cmd = (struct scsi_rw_12 *)xs->cmd;
+
+ cmd->opcode = read ? READ_12 : WRITE_12;
+ _lto4b(blkno, cmd->addr);
+ _lto4b(nblks, cmd->length);
+
+ xs->cmdlen = sizeof(*cmd);
+}
+
+void
+sd_cmd_rw16(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks);
+void
+sd_cmd_rw16(struct scsi_xfer *xs, int read, daddr64_t blkno, u_int nblks)
+{
+ struct scsi_rw_16 *cmd = (struct scsi_rw_16 *)xs->cmd;
+
+ cmd->opcode = read ? READ_16 : WRITE_16;
+ _lto4b(blkno, cmd->addr);
+ _lto4b(nblks, cmd->length);
+
+ xs->cmdlen = sizeof(*cmd);
+}
+void sd_buf_done(struct scsi_xfer *xs);
+
/*
* sdstart looks to see if there is a buf waiting for the device
* and that the device is not already busy. If both are true,
@@ -592,62 +674,31 @@ done:
* This routine is also called after other non-queued requests
* have been made of the scsi driver, to ensure that the queue
* continues to be drained.
- *
- * must be called at the correct (highish) spl level
- * sdstart() is called at splbio from sdstrategy, sdrestart and scsi_done
*/
void
sdstart(void *v)
{
- struct sd_softc *sd = (struct sd_softc *)v;
- struct scsi_link *sc_link = sd->sc_link;
- struct buf *bp = 0;
- struct buf *dp;
- struct scsi_rw_big cmd_big;
- struct scsi_rw_12 cmd_12;
- struct scsi_rw_16 cmd_16;
- struct scsi_rw cmd_small;
- struct scsi_generic *cmdp;
+ struct sd_softc *sc = (struct sd_softc *)v;
+ struct scsi_link *link = sc->sc_link;
+ struct scsi_xfer *xs;
+ struct buf *bp;
daddr64_t blkno;
- int nblks, cmdlen, error;
+ int nblks;
+ int read;
struct partition *p;
- if (sd->flags & SDF_DYING)
+ if (sc->flags & SDF_DYING)
return;
SC_DEBUG(sc_link, SDEV_DB2, ("sdstart\n"));
- splassert(IPL_BIO);
-
- /*
- * Check if the device has room for another command
- */
- while (sc_link->openings > 0) {
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (sc_link->flags & SDEV_WAITING) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link);
- return;
- }
-
- /*
- * See if there is a buf with work for us to do..
- */
- dp = &sd->buf_queue;
- if ((bp = dp->b_actf) == NULL) /* yes, an assign */
- return;
- dp->b_actf = bp->b_actf;
-
+ while ((bp = sd_buf_dequeue(sc)) != NULL) {
/*
* If the device has become invalid, abort all the
* reads and writes until all files have been closed and
* re-opened
*/
- if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
+ if ((link->flags & SDEV_MEDIA_LOADED) == 0) {
bp->b_error = EIO;
bp->b_flags |= B_ERROR;
bp->b_resid = bp->b_bcount;
@@ -655,129 +706,77 @@ sdstart(void *v)
continue;
}
- /*
- * We have a buf, now we should make a command
- *
- * First, translate the block to absolute and put it in terms
- * of the logical blocksize of the device.
- */
+ xs = scsi_xs_get(link, SCSI_NOSLEEP);
+ if (xs == NULL) {
+ sd_buf_requeue(sc, bp);
+ return;
+ }
+
blkno =
- bp->b_blkno / (sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
- p = &sd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
+ bp->b_blkno / (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
+ p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
blkno += DL_GETPOFFSET(p);
- nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label->d_secsize);
+ nblks = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize);
+ read = bp->b_flags & B_READ;
/*
* Fill out the scsi command. If the transfer will
* fit in a "small" cdb, use it.
*/
- if (!(sc_link->flags & SDEV_ATAPI) &&
- !(sc_link->quirks & SDEV_ONLYBIG) &&
+ if (!(link->flags & SDEV_ATAPI) &&
+ !(link->quirks & SDEV_ONLYBIG) &&
((blkno & 0x1fffff) == blkno) &&
- ((nblks & 0xff) == nblks)) {
- /*
- * We can fit in a 6 byte cdb.
- */
- bzero(&cmd_small, sizeof(cmd_small));
- cmd_small.opcode = (bp->b_flags & B_READ) ?
- READ_COMMAND : WRITE_COMMAND;
- _lto3b(blkno, cmd_small.addr);
- cmd_small.length = nblks;
- cmdlen = sizeof(cmd_small);
- cmdp = (struct scsi_generic *)&cmd_small;
- } else if (((blkno & 0xffffffff) == blkno) &&
- ((nblks & 0xffff) == nblks)) {
- /*
- * We can fit in a 10 byte cdb.
- */
- bzero(&cmd_big, sizeof(cmd_big));
- cmd_big.opcode = (bp->b_flags & B_READ) ?
- READ_BIG : WRITE_BIG;
- _lto4b(blkno, cmd_big.addr);
- _lto2b(nblks, cmd_big.length);
- cmdlen = sizeof(cmd_big);
- cmdp = (struct scsi_generic *)&cmd_big;
- } else if (((blkno & 0xffffffff) == blkno) &&
- ((nblks & 0xffffffff) == nblks)) {
- /*
- * We can fit in a 12 byte cdb.
- */
- bzero(&cmd_12, sizeof(cmd_12));
- cmd_12.opcode = (bp->b_flags & B_READ) ?
- READ_12 : WRITE_12;
- _lto4b(blkno, cmd_12.addr);
- _lto4b(nblks, cmd_12.length);
- cmdlen = sizeof(cmd_12);
- cmdp = (struct scsi_generic *)&cmd_12;
- } else {
- /*
- * Need a 16 byte cdb. There's nothing bigger.
- */
- bzero(&cmd_16, sizeof(cmd_16));
- cmd_16.opcode = (bp->b_flags & B_READ) ?
- READ_16 : WRITE_16;
- _lto8b(blkno, cmd_16.addr);
- _lto4b(nblks, cmd_16.length);
- cmdlen = sizeof(cmd_16);
- cmdp = (struct scsi_generic *)&cmd_16;
- }
+ ((nblks & 0xff) == nblks))
+ sd_cmd_rw6(xs, read, blkno, nblks);
+ else if (((blkno & 0xffffffff) == blkno) &&
+ ((nblks & 0xffff) == nblks))
+ sd_cmd_rw10(xs, read, blkno, nblks);
+ else if (((blkno & 0xffffffff) == blkno) &&
+ ((nblks & 0xffffffff) == nblks))
+ sd_cmd_rw12(xs, read, blkno, nblks);
+ else
+ sd_cmd_rw16(xs, read, blkno, nblks);
- /* Instrumentation. */
- disk_busy(&sd->sc_dk);
+ xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT);
+ xs->timeout = 60000;
+ xs->data = bp->b_data;
+ xs->datalen = bp->b_bcount;
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
- (u_char *)bp->b_data, bp->b_bcount,
- SCSI_RETRIES, 60000, bp, SCSI_NOSLEEP |
- ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT));
- switch (error) {
- case 0:
- /*
- * Mark the disk dirty so that the cache will be
- * flushed on close.
- */
- if ((bp->b_flags & B_READ) == 0)
- sd->flags |= SDF_DIRTY;
- timeout_del(&sd->sc_timeout);
- break;
- case EAGAIN:
- /*
- * The device can't start another i/o. Try again later.
- */
- dp->b_actf = bp;
- disk_unbusy(&sd->sc_dk, 0, 0);
- timeout_add(&sd->sc_timeout, 1);
- return;
- default:
- disk_unbusy(&sd->sc_dk, 0, 0);
- printf("%s: not queued, error %d\n",
- sd->sc_dev.dv_xname, error);
- break;
- }
+ xs->done = sd_buf_done;
+ xs->cookie = bp;
+
+ /* Instrumentation. */
+ disk_busy(&sc->sc_dk);
+ scsi_xs_exec(xs);
}
}
void
-sdrestart(void *v)
+sd_buf_done(struct scsi_xfer *xs)
{
+ struct sd_softc *sc = xs->sc_link->device_softc;
+ struct buf *bp = xs->cookie;
int s;
+ disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid,
+ bp->b_flags & B_READ);
+
+ if (xs->error == XS_NOERROR) {
+ bp->b_error = 0;
+ bp->b_resid = xs->resid;
+ } else {
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ bp->b_resid = bp->b_bcount;
+ }
+
s = splbio();
- sdstart(v);
+ biodone(bp);
splx(s);
-}
-void
-sddone(struct scsi_xfer *xs)
-{
- struct sd_softc *sd = xs->sc_link->device_softc;
+ scsi_xs_put(xs);
- if (xs->bp != NULL)
- disk_unbusy(&sd->sc_dk, (xs->bp->b_bcount - xs->bp->b_resid),
- (xs->bp->b_flags & B_READ));
+ sdstart(sc); /* XXX */
}
void
@@ -1081,27 +1080,6 @@ sd_shutdown(void *arg)
}
/*
- * Tell the device to map out a defective block
- */
-int
-sd_reassign_blocks(struct sd_softc *sd, u_long blkno)
-{
- struct scsi_reassign_blocks scsi_cmd;
- struct scsi_reassign_blocks_data rbdata;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&rbdata, sizeof(rbdata));
- scsi_cmd.opcode = REASSIGN_BLOCKS;
-
- _lto2b(sizeof(rbdata.defect_descriptor[0]), rbdata.length);
- _lto4b(blkno, rbdata.defect_descriptor[0].dlbaddr);
-
- return scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd,
- sizeof(scsi_cmd), (u_char *)&rbdata, sizeof(rbdata), SCSI_RETRIES,
- 5000, NULL, SCSI_DATA_OUT);
-}
-
-/*
* Check Errors
*/
int
@@ -1186,7 +1164,6 @@ sdsize(dev_t dev)
}
/* #define SD_DUMP_NOT_TRUSTED if you just want to watch */
-static struct scsi_xfer sx;
static int sddoingadump;
/*
@@ -1196,7 +1173,7 @@ static int sddoingadump;
int
sddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
{
- struct sd_softc *sd; /* disk unit to do the I/O */
+ struct sd_softc *sc; /* disk unit to do the I/O */
struct disklabel *lp; /* disk's disklabel */
int unit, part;
int sectorsize; /* size of a disk sector */
@@ -1204,9 +1181,7 @@ sddump(dev_t dev, daddr64_t blkno, caddr
daddr64_t sectoff; /* sector offset of partition */
int totwrt; /* total number of sectors left to write */
int nwrt; /* current number of sectors to write */
- struct scsi_rw_big cmd; /* write command */
struct scsi_xfer *xs; /* ... convenience */
- int retval;
/* Check if recursive dump; if so, punt. */
if (sddoingadump)
@@ -1219,7 +1194,7 @@ sddump(dev_t dev, daddr64_t blkno, caddr
part = DISKPART(dev);
/* Check for acceptable drive number. */
- if (unit >= sd_cd.cd_ndevs || (sd = sd_cd.cd_devs[unit]) == NULL)
+ if (unit >= sd_cd.cd_ndevs || (sc = sd_cd.cd_devs[unit]) == NULL)
return ENXIO;
/*
@@ -1229,12 +1204,12 @@ sddump(dev_t dev, daddr64_t blkno, caddr
*/
#if 0
/* Make sure it was initialized. */
- if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
+ if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
return ENXIO;
#endif
/* Convert to disk sectors. Request must be a multiple of size. */
- lp = sd->sc_dk.dk_label;
+ lp = sc->sc_dk.dk_label;
sectorsize = lp->d_secsize;
if ((size % sectorsize) != 0)
return EFAULT;
@@ -1251,43 +1226,25 @@ sddump(dev_t dev, daddr64_t blkno, caddr
/* Offset block number to start of partition. */
blkno += sectoff;
- xs = &sx;
-
while (totwrt > 0) {
nwrt = totwrt; /* XXX */
+
#ifndef SD_DUMP_NOT_TRUSTED
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = WRITE_BIG;
- _lto4b(blkno, cmd.addr);
- _lto2b(nwrt, cmd.length);
- /*
- * Fill out the scsi_xfer structure
- * Note: we cannot sleep as we may be an interrupt
- * don't use scsi_scsi_cmd() as it may want
- * to wait for an xs.
- */
- bzero(xs, sizeof(sx));
- xs->flags |= SCSI_AUTOCONF | SCSI_DATA_OUT;
- xs->sc_link = sd->sc_link;
- xs->retries = SCSI_RETRIES;
- xs->timeout = 10000; /* 10000 millisecs for a disk ! */
- xs->cmd = (struct scsi_generic *)&cmd;
- xs->cmdlen = sizeof(cmd);
- xs->resid = nwrt * sectorsize;
- xs->error = XS_NOERROR;
- xs->bp = NULL;
+ xs = scsi_xs_get(sc->sc_link, SCSI_NOSLEEP);
+ if (xs == NULL)
+ return (ENOMEM);
+
+ xs->timeout = 10000;
+ xs->flags = SCSI_POLL | SCSI_NOSLEEP | SCSI_DATA_OUT;
xs->data = va;
xs->datalen = nwrt * sectorsize;
- /*
- * Pass all this info to the scsi driver.
- */
- retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs);
- if (retval != COMPLETE)
- return ENXIO;
+ sd_cmd_rw10(xs, 0, blkno, nwrt); /* XXX */
+
+ scsi_xs_exec(xs);
+ if (xs->error != XS_NOERROR)
+ return (ENXIO);
+ scsi_xs_put(xs);
#else /* SD_DUMP_NOT_TRUSTED */
/* Let's just talk about this first... */
printf("sd%d: dump addr 0x%x, blk %d\n", unit, va, blkno);
@@ -1299,8 +1256,10 @@ sddump(dev_t dev, daddr64_t blkno, caddr
blkno += nwrt;
va += sectorsize * nwrt;
}
+
sddoingadump = 0;
- return 0;
+
+ return (0);
}
/*
@@ -1469,14 +1428,17 @@ validate:
return (SDGP_RESULT_OK);
}
+void
+sd_flush_done(struct scsi_xfer *xs);
void
-sd_flush(struct sd_softc *sd, int flags)
+sd_flush(struct sd_softc *sc, int flags)
{
- struct scsi_link *sc_link = sd->sc_link;
- struct scsi_synchronize_cache cmd;
+ struct scsi_link *link = sc->sc_link;
+ struct scsi_xfer *xs;
+ struct scsi_synchronize_cache *cmd;
- if (sc_link->quirks & SDEV_NOSYNCCACHE)
+ if (link->quirks & SDEV_NOSYNCCACHE)
return;
/*
@@ -1485,15 +1447,38 @@ sd_flush(struct sd_softc *sd, int flags)
* that the command is not supported by the device.
*/
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = SYNCHRONIZE_CACHE;
-
- if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&cmd, sizeof(cmd),
- NULL, 0, SCSI_RETRIES, 100000, NULL,
- flags | SCSI_IGNORE_ILLEGAL_REQUEST)) {
+ xs = scsi_xs_get(link, flags);
+ if (xs == NULL) {
+ SC_DEBUG(sc_link, SDEV_DB1, ("cache sync failed to get xs\n"));
+ return;
+ }
+
+ cmd = (struct scsi_synchronize_cache *)xs->cmd;
+ cmd->opcode = SYNCHRONIZE_CACHE;
+
+ xs->timeout = 100000;
+
+ xs->done = sd_flush_done;
+
+ scsi_xs_exec(xs);
+ if (!ISSET(xs->flags, SCSI_POLL)) {
+ while (!ISSET(xs->flags, ITSDONE))
+ tsleep(xs, PRIBIO, "sdflush", 0);
+ }
+
+ if (xs->error != XS_NOERROR)
SC_DEBUG(sc_link, SDEV_DB1, ("cache sync failed\n"));
- } else
- sd->flags &= ~SDF_DIRTY;
+ else
+ sc->flags &= ~SDF_DIRTY;
+
+ scsi_xs_put(xs);
+}
+
+void
+sd_flush_done(struct scsi_xfer *xs)
+{
+ if (!ISSET(xs->flags, SCSI_POLL))
+ wakeup_one(xs);
}
/*
@@ -1502,16 +1487,11 @@ sd_flush(struct sd_softc *sd, int flags)
void
sd_kill_buffers(struct sd_softc *sd)
{
- struct buf *dp, *bp;
- int s;
-
- s = splbio();
- for (dp = &sd->buf_queue; (bp = dp->b_actf) != NULL; ) {
- dp->b_actf = bp->b_actf;
+ struct buf *bp;
+ while ((bp = sd_buf_dequeue(sd)) != NULL) {
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
biodone(bp);
}
- splx(s);
}
Index: sdvar.h
===================================================================
RCS file: /cvs/src/sys/scsi/sdvar.h,v
retrieving revision 1.18
diff -u -p -r1.18 sdvar.h
--- sdvar.h 17 Jun 2009 01:30:32 -0000 1.18
+++ sdvar.h 11 Aug 2009 14:25:00 -0000
@@ -49,10 +49,10 @@
#ifdef _KERNEL
struct sd_softc {
- struct device sc_dev;
- struct disk sc_dk;
+ struct device sc_dev;
+ struct disk sc_dk;
- int flags;
+ int flags;
#define SDF_LOCKED 0x01
#define SDF_WANTED 0x02
#define SDF_WLABEL 0x04 /* label is writable */
@@ -60,7 +60,7 @@ struct sd_softc {
#define SDF_ANCIENT 0x10 /* disk is ancient; for minphys
*/
#define SDF_DIRTY 0x20 /* disk is dirty; needs cache
flush */
#define SDF_DYING 0x40 /* dying, when deactivated */
- struct scsi_link *sc_link; /* contains our targ, lun, etc. */
+ struct scsi_link *sc_link; /* contains our targ, lun, etc. */
struct disk_parms {
u_long heads; /* number of heads */
u_long cyls; /* number of cylinders */
@@ -69,9 +69,11 @@ struct sd_softc {
u_long rot_rate; /* rotational rate, in RPM */
daddr64_t disksize; /* total number sectors */
} params;
- struct buf buf_queue;
+ struct mutex sc_buf_mtx;
+ struct buf sc_buf_queue;
void *sc_sdhook; /* our shutdown hook */
struct timeout sc_timeout;
+
};
#define SDGP_RESULT_OK 0 /* parameters obtained */