[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>
This commit is contained in:
parent
50865c1d38
commit
9ec76fbf7d
|
@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
|
||||||
}
|
}
|
||||||
qpti->dev_param[i].device_enable = 1;
|
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)
|
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);
|
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;
|
struct qlogicpti *qpti = shost_priv(sdev->host);
|
||||||
unsigned int buflen;
|
int tgt = sdev->id;
|
||||||
|
u_short param[6];
|
||||||
|
|
||||||
if (cmd->use_sg) {
|
/* tags handled in midlayer */
|
||||||
struct scatterlist *sg;
|
/* enable sync mode? */
|
||||||
|
if (sdev->sdtr) {
|
||||||
sg = (struct scatterlist *) cmd->request_buffer;
|
qpti->dev_param[tgt].device_flags |= 0x10;
|
||||||
buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
|
||||||
buflen = sg->length;
|
|
||||||
} else {
|
} else {
|
||||||
buf = cmd->request_buffer;
|
qpti->dev_param[tgt].synchronous_offset = 0;
|
||||||
buflen = cmd->request_bufflen;
|
qpti->dev_param[tgt].synchronous_period = 0;
|
||||||
}
|
}
|
||||||
|
/* are we wide capable? */
|
||||||
|
if (sdev->wdtr)
|
||||||
|
qpti->dev_param[tgt].device_flags |= 0x20;
|
||||||
|
|
||||||
*buf_out = buf;
|
param[0] = MBOX_SET_TARGET_PARAMS;
|
||||||
return buflen;
|
param[1] = (tgt << 8);
|
||||||
}
|
param[2] = (qpti->dev_param[tgt].device_flags << 8);
|
||||||
|
if (qpti->dev_param[tgt].device_flags & 0x10) {
|
||||||
static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf)
|
param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) |
|
||||||
{
|
qpti->dev_param[tgt].synchronous_period;
|
||||||
if (cmd->use_sg) {
|
} else {
|
||||||
struct scatterlist *sg;
|
param[3] = 0;
|
||||||
|
|
||||||
sg = (struct scatterlist *) cmd->request_buffer;
|
|
||||||
kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
|
||||||
}
|
}
|
||||||
}
|
qlogicpti_mbox_command(qpti, param, 0);
|
||||||
|
return 0;
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1390,7 +1270,8 @@ static struct scsi_host_template qpti_template = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.name = "qlogicpti",
|
.name = "qlogicpti",
|
||||||
.info = qlogicpti_info,
|
.info = qlogicpti_info,
|
||||||
.queuecommand = qlogicpti_queuecommand_slow,
|
.queuecommand = qlogicpti_queuecommand,
|
||||||
|
.slave_configure = qlogicpti_slave_configure,
|
||||||
.eh_abort_handler = qlogicpti_abort,
|
.eh_abort_handler = qlogicpti_abort,
|
||||||
.eh_bus_reset_handler = qlogicpti_reset,
|
.eh_bus_reset_handler = qlogicpti_reset,
|
||||||
.can_queue = QLOGICPTI_REQ_QUEUE_LEN,
|
.can_queue = QLOGICPTI_REQ_QUEUE_LEN,
|
||||||
|
|
|
@ -380,8 +380,7 @@ struct qlogicpti {
|
||||||
unsigned char swsreg;
|
unsigned char swsreg;
|
||||||
unsigned int
|
unsigned int
|
||||||
gotirq : 1, /* this instance got an irq */
|
gotirq : 1, /* this instance got an irq */
|
||||||
is_pti : 1, /* Non-zero if this is a PTI board. */
|
is_pti : 1; /* Non-zero if this is a PTI board. */
|
||||||
sbits : 16; /* syncmode known bits */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* How to twiddle them bits... */
|
/* How to twiddle them bits... */
|
||||||
|
|
Loading…
Reference in New Issue