Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ec76fbf authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley
Browse files

[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: default avatarMatthew Wilcox <willy@linux.intel.com>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 50865c1d
Loading
Loading
Loading
Loading
+26 −145
Original line number Diff line number Diff line
@@ -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;

		sg = (struct scatterlist *) cmd->request_buffer;
		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
		buflen = sg->length;
	} else {
		buf = cmd->request_buffer;
		buflen = cmd->request_bufflen;
	}

	*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);
	struct qlogicpti *qpti = shost_priv(sdev->host);
	int tgt = sdev->id;
	u_short param[6];

	/* tags handled in midlayer */
	/* enable sync mode? */
			if (iqd[7] & 0x10) {
	if (sdev->sdtr) {
		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) {
	if (sdev->wdtr)
		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;
	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;
	}
			(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);
	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,
+1 −2
Original line number Diff line number Diff line
@@ -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... */