summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-10-01 08:07:52 -0600
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:52:38 -0400
commit9ec76fbf7d6da3e98070a7059699d0ca019b0c9b (patch)
tree6370b64b39555c4df92232a3ba9a65b11bebbba1
parent50865c1d38e3fbe17a1843582a8e10f2dbbeb6d3 (diff)
[SCSI] qlogicpti: Add a slave_configure method
By configuring targets in slave_configure, we can eliminate a shadow queuecommand, a shadow scsi_done, a write to the host template, abuse of SCp->Message and SCp->Status, a use of kmap_atomic() and sniffing the results of INQUIRY. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/qlogicpti.c171
-rw-r--r--drivers/scsi/qlogicpti.h3
2 files changed, 27 insertions, 147 deletions
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 594887205b0..e93f80316a1 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
}
qpti->dev_param[i].device_enable = 1;
}
- /* this is very important to set! */
- qpti->sbits = 1 << qpti->scsi_id;
}
static int qlogicpti_reset_hardware(struct Scsi_Host *host)
@@ -951,153 +949,35 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int
host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
}
-static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out)
+static int qlogicpti_slave_configure(struct scsi_device *sdev)
{
- unsigned char *buf;
- unsigned int buflen;
-
- if (cmd->use_sg) {
- struct scatterlist *sg;
+ struct qlogicpti *qpti = shost_priv(sdev->host);
+ int tgt = sdev->id;
+ u_short param[6];
- sg = (struct scatterlist *) cmd->request_buffer;
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
- buflen = sg->length;
+ /* tags handled in midlayer */
+ /* enable sync mode? */
+ if (sdev->sdtr) {
+ qpti->dev_param[tgt].device_flags |= 0x10;
} else {
- buf = cmd->request_buffer;
- buflen = cmd->request_bufflen;
+ qpti->dev_param[tgt].synchronous_offset = 0;
+ qpti->dev_param[tgt].synchronous_period = 0;
}
-
- *buf_out = buf;
- return buflen;
-}
-
-static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf)
-{
- if (cmd->use_sg) {
- struct scatterlist *sg;
-
- sg = (struct scatterlist *) cmd->request_buffer;
- kunmap_atomic(buf - sg->offset, KM_IRQ0);
- }
-}
-
-/*
- * Until we scan the entire bus with inquiries, go throught this fella...
- */
-static void ourdone(struct scsi_cmnd *Cmnd)
-{
- struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
- int tgt = Cmnd->device->id;
- void (*done) (struct scsi_cmnd *);
-
- /* This grot added by DaveM, blame him for ugliness.
- * The issue is that in the 2.3.x driver we use the
- * host_scribble portion of the scsi command as a
- * completion linked list at interrupt service time,
- * so we have to store the done function pointer elsewhere.
- */
- done = (void (*)(struct scsi_cmnd *))
- (((unsigned long) Cmnd->SCp.Message)
-#ifdef __sparc_v9__
- | ((unsigned long) Cmnd->SCp.Status << 32UL)
-#endif
- );
-
- if ((qpti->sbits & (1 << tgt)) == 0) {
- int ok = host_byte(Cmnd->result) == DID_OK;
- if (Cmnd->cmnd[0] == 0x12 && ok) {
- unsigned char *iqd;
- unsigned int iqd_len;
-
- iqd_len = scsi_rbuf_get(Cmnd, &iqd);
-
- /* tags handled in midlayer */
- /* enable sync mode? */
- if (iqd[7] & 0x10) {
- qpti->dev_param[tgt].device_flags |= 0x10;
- } else {
- qpti->dev_param[tgt].synchronous_offset = 0;
- qpti->dev_param[tgt].synchronous_period = 0;
- }
- /* are we wide capable? */
- if (iqd[7] & 0x20) {
- qpti->dev_param[tgt].device_flags |= 0x20;
- }
-
- scsi_rbuf_put(Cmnd, iqd);
-
- qpti->sbits |= (1 << tgt);
- } else if (!ok) {
- qpti->sbits |= (1 << tgt);
- }
- }
- done(Cmnd);
-}
-
-static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *));
-
-static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd,
- void (*done)(struct scsi_cmnd *))
-{
- struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
-
- /*
- * done checking this host adapter?
- * If not, then rewrite the command
- * to finish through ourdone so we
- * can peek at Inquiry data results.
- */
- if (qpti->sbits && qpti->sbits != 0xffff) {
- /* See above about in ourdone this ugliness... */
- Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;
-#ifdef CONFIG_SPARC64
- Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;
-#endif
- return qlogicpti_queuecommand(Cmnd, ourdone);
- }
-
- /*
- * We've peeked at all targets for this bus- time
- * to set parameters for devices for real now.
- */
- if (qpti->sbits == 0xffff) {
- int i;
- for(i = 0; i < MAX_TARGETS; i++) {
- u_short param[6];
- param[0] = MBOX_SET_TARGET_PARAMS;
- param[1] = (i << 8);
- param[2] = (qpti->dev_param[i].device_flags << 8);
- if (qpti->dev_param[i].device_flags & 0x10) {
- param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
- qpti->dev_param[i].synchronous_period;
- } else {
- param[3] = 0;
- }
- (void) qlogicpti_mbox_command(qpti, param, 0);
- }
- /*
- * set to zero so any traverse through ourdone
- * doesn't start the whole process again,
- */
- qpti->sbits = 0;
- }
-
- /* check to see if we're done with all adapters... */
- for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {
- if (qpti->sbits) {
- break;
- }
+ /* are we wide capable? */
+ if (sdev->wdtr)
+ qpti->dev_param[tgt].device_flags |= 0x20;
+
+ param[0] = MBOX_SET_TARGET_PARAMS;
+ param[1] = (tgt << 8);
+ param[2] = (qpti->dev_param[tgt].device_flags << 8);
+ if (qpti->dev_param[tgt].device_flags & 0x10) {
+ param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) |
+ qpti->dev_param[tgt].synchronous_period;
+ } else {
+ param[3] = 0;
}
-
- /*
- * if we hit the end of the chain w/o finding adapters still
- * capability-configuring, then we're done with all adapters
- * and can rock on..
- */
- if (qpti == NULL)
- Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand;
-
- return qlogicpti_queuecommand(Cmnd, done);
+ qlogicpti_mbox_command(qpti, param, 0);
+ return 0;
}
/*
@@ -1390,7 +1270,8 @@ static struct scsi_host_template qpti_template = {
.module = THIS_MODULE,
.name = "qlogicpti",
.info = qlogicpti_info,
- .queuecommand = qlogicpti_queuecommand_slow,
+ .queuecommand = qlogicpti_queuecommand,
+ .slave_configure = qlogicpti_slave_configure,
.eh_abort_handler = qlogicpti_abort,
.eh_bus_reset_handler = qlogicpti_reset,
.can_queue = QLOGICPTI_REQ_QUEUE_LEN,
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
index 6cd1c0771d2..ef6da2df584 100644
--- a/drivers/scsi/qlogicpti.h
+++ b/drivers/scsi/qlogicpti.h
@@ -380,8 +380,7 @@ struct qlogicpti {
unsigned char swsreg;
unsigned int
gotirq : 1, /* this instance got an irq */
- is_pti : 1, /* Non-zero if this is a PTI board. */
- sbits : 16; /* syncmode known bits */
+ is_pti : 1; /* Non-zero if this is a PTI board. */
};
/* How to twiddle them bits... */