Fix a performance problem with the ciss(4) driver. NetBSD does common
queueing at the scsipi midlayer, and if the midlayer is not requested to enable tagged queueing, the midlayer will only queue one command to the adapter driver for each device. The SmartArray adapter is capable of handling multiple commands, and in the rather common case where there is no battery backup and no write cache, doing single write commands is very slow. The SmartArray adapter runs much better when several commands can be issued to a device. This has been observed and discussed in several list threads, notably: http://mail-index.NetBSD.org/netbsd-users/2008/10/01/msg002083.html http://mail-index.NetBSD.org/tech-kern/2008/11/30/msg003704.html This also addresses PR kern/39686. To enable tagged queueing, the adapter driver responds to the midlayer request to set the transfer mode. However, the SmartArray does not respond to the SCSI INQUIRY command with an ANSII field of 2 or more, so the scsipi midlayer will ignore the CmdQue bit in the flags3 field of the inquiry data. This fix will patch the inquiry data so set the ANSII field to 2, and responds to the midlayer request to set the transfer mode by requesting tagged queueing. In addition, the original port of the driver did not set up the adapter parameters correctly as mentioned in the second list thread mentioned above. The adapt_openings is the total number of commands that the adapter will accept rather than the number of commands divided by the number of logical drives. Also, the adapt_max_periph is the maximum number of commands which can be queued per peripheral device, not the number of logical drives [which in the case of a single logical drive limited the number of commands queued to 1]. I'm also suppressing an error message for invalid commands if the error was due to the SCSI_SYNCHRONIZE_CACHE_10 command, since that command is not supported by the SmartArray adapter, but used with wapbl(4) meta-data journaling. Setting the ANSII version to 2 to allow enabling tagged queueing also enables the use of the SCSI_SYNCHRONIZE_CACHE_10 command.
This commit is contained in:
parent
d00164124d
commit
9c443068a6
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ciss.c,v 1.22 2010/07/27 18:50:32 jakllsch Exp $ */
|
||||
/* $NetBSD: ciss.c,v 1.23 2010/09/07 18:19:16 mhitch Exp $ */
|
||||
/* $OpenBSD: ciss.c,v 1.14 2006/03/13 16:02:23 mickey Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.22 2010/07/27 18:50:32 jakllsch Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.23 2010/09/07 18:19:16 mhitch Exp $");
|
||||
|
||||
#include "bio.h"
|
||||
|
||||
|
@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.22 2010/07/27 18:50:32 jakllsch Exp $");
|
|||
#include <dev/scsipi/scsi_all.h>
|
||||
#include <dev/scsipi/scsi_disk.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
|
||||
#include <dev/ic/cissreg.h>
|
||||
#include <dev/ic/cissvar.h>
|
||||
|
@ -363,7 +364,7 @@ ciss_attach(struct ciss_softc *sc)
|
|||
sc->sc_channel.chan_channel = 0;
|
||||
sc->sc_channel.chan_ntargets = sc->maxunits;
|
||||
sc->sc_channel.chan_nluns = 1; /* ciss doesn't really have SCSI luns */
|
||||
sc->sc_channel.chan_openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
|
||||
sc->sc_channel.chan_openings = sc->maxcmd;
|
||||
#if NBIO > 0
|
||||
/* XXX Reserve some ccb's for sensor and bioctl. */
|
||||
if (sc->sc_channel.chan_openings > 2)
|
||||
|
@ -374,7 +375,7 @@ ciss_attach(struct ciss_softc *sc)
|
|||
|
||||
sc->sc_adapter.adapt_dev = (device_t) sc;
|
||||
sc->sc_adapter.adapt_openings = sc->sc_channel.chan_openings;
|
||||
sc->sc_adapter.adapt_max_periph = sc->maxunits;
|
||||
sc->sc_adapter.adapt_max_periph = sc->sc_channel.chan_openings;
|
||||
sc->sc_adapter.adapt_request = ciss_scsi_cmd;
|
||||
sc->sc_adapter.adapt_minphys = cissminphys;
|
||||
sc->sc_adapter.adapt_ioctl = ciss_scsi_ioctl;
|
||||
|
@ -617,6 +618,14 @@ ciss_done(struct ciss_ccb *ccb)
|
|||
if (xs) {
|
||||
xs->resid = 0;
|
||||
CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs));
|
||||
if (xs->cmd->opcode == INQUIRY) {
|
||||
struct scsipi_inquiry_data *inq;
|
||||
inq = (struct scsipi_inquiry_data *)xs->data;
|
||||
if ((inq->version & SID_ANSII) == 0 &&
|
||||
(inq->flags3 & SID_CmdQue) != 0) {
|
||||
inq->version |= 2;
|
||||
}
|
||||
}
|
||||
scsipi_done(xs);
|
||||
}
|
||||
|
||||
|
@ -636,9 +645,11 @@ ciss_error(struct ciss_ccb *ccb)
|
|||
break;
|
||||
|
||||
case CISS_ERR_INVCMD:
|
||||
printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
|
||||
device_xname(&sc->sc_dev), ccb->ccb_cmd.id,
|
||||
err->err_info, err->err_type[3], err->err_type[2]);
|
||||
if (xs == NULL ||
|
||||
xs->cmd->opcode != SCSI_SYNCHRONIZE_CACHE_10)
|
||||
printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
|
||||
device_xname(&sc->sc_dev), ccb->ccb_cmd.id,
|
||||
err->err_info, err->err_type[3], err->err_type[2]);
|
||||
if (xs) {
|
||||
memset(&xs->sense, 0, sizeof(xs->sense));
|
||||
xs->sense.scsi_sense.response_code =
|
||||
|
@ -1002,7 +1013,8 @@ static void
|
|||
ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
|
||||
void *arg)
|
||||
{
|
||||
struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
|
||||
struct scsipi_xfer *xs;
|
||||
struct scsipi_xfer_mode *xm;
|
||||
struct ciss_softc *sc =
|
||||
(struct ciss_softc *) chan->chan_adapter->adapt_dev;
|
||||
u_int8_t target;
|
||||
|
@ -1015,6 +1027,7 @@ ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
|
|||
switch (req)
|
||||
{
|
||||
case ADAPTER_REQ_RUN_XFER:
|
||||
xs = (struct scsipi_xfer *) arg;
|
||||
target = xs->xs_periph->periph_target;
|
||||
CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target));
|
||||
if (xs->cmdlen > CISS_MAX_CDB) {
|
||||
|
@ -1072,7 +1085,9 @@ ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
|
|||
* We can't change the transfer mode, but at least let
|
||||
* scsipi know what the adapter has negociated.
|
||||
*/
|
||||
/* FIXME: get xfer mode and write it into arg */
|
||||
xm = (struct scsipi_xfer_mode *)arg;
|
||||
xm->xm_mode |= PERIPH_CAP_TQING;
|
||||
scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue