aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-10-01 10:07:52 -0400
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 594887205b0f..e93f80316a19 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)
310 } 310 }
311 qpti->dev_param[i].device_enable = 1; 311 qpti->dev_param[i].device_enable = 1;
312 } 312 }
313 /* this is very important to set! */
314 qpti->sbits = 1 << qpti->scsi_id;
315} 313}
316 314
317static int qlogicpti_reset_hardware(struct Scsi_Host *host) 315static 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
951 host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); 949 host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
952} 950}
953 951
954static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) 952static int qlogicpti_slave_configure(struct scsi_device *sdev)
955{ 953{
956 unsigned char *buf; 954 struct qlogicpti *qpti = shost_priv(sdev->host);
957 unsigned int buflen; 955 int tgt = sdev->id;
958 956 u_short param[6];
959 if (cmd->use_sg) {
960 struct scatterlist *sg;
961 957
962 sg = (struct scatterlist *) cmd->request_buffer; 958 /* tags handled in midlayer */
963 buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; 959 /* enable sync mode? */
964 buflen = sg->length; 960 if (sdev->sdtr) {
961 qpti->dev_param[tgt].device_flags |= 0x10;
965 } else { 962 } else {
966 buf = cmd->request_buffer; 963 qpti->dev_param[tgt].synchronous_offset = 0;
967 buflen = cmd->request_bufflen; 964 qpti->dev_param[tgt].synchronous_period = 0;
968 } 965 }
969 966 /* are we wide capable? */
970 *buf_out = buf; 967 if (sdev->wdtr)
971 return buflen; 968 qpti->dev_param[tgt].device_flags |= 0x20;
972} 969
973 970 param[0] = MBOX_SET_TARGET_PARAMS;
974static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf) 971 param[1] = (tgt << 8);
975{ 972 param[2] = (qpti->dev_param[tgt].device_flags << 8);
976 if (cmd->use_sg) { 973 if (qpti->dev_param[tgt].device_flags & 0x10) {
977 struct scatterlist *sg; 974 param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) |
978 975 qpti->dev_param[tgt].synchronous_period;
979 sg = (struct scatterlist *) cmd->request_buffer; 976 } else {
980 kunmap_atomic(buf - sg->offset, KM_IRQ0); 977 param[3] = 0;
981 }
982}
983
984/*
985 * Until we scan the entire bus with inquiries, go throught this fella...
986 */
987static void ourdone(struct scsi_cmnd *Cmnd)
988{
989 struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
990 int tgt = Cmnd->device->id;
991 void (*done) (struct scsi_cmnd *);
992
993 /* This grot added by DaveM, blame him for ugliness.
994 * The issue is that in the 2.3.x driver we use the
995 * host_scribble portion of the scsi command as a
996 * completion linked list at interrupt service time,
997 * so we have to store the done function pointer elsewhere.
998 */
999 done = (void (*)(struct scsi_cmnd *))
1000 (((unsigned long) Cmnd->SCp.Message)
1001#ifdef __sparc_v9__
1002 | ((unsigned long) Cmnd->SCp.Status << 32UL)
1003#endif
1004 );
1005
1006 if ((qpti->sbits & (1 << tgt)) == 0) {
1007 int ok = host_byte(Cmnd->result) == DID_OK;
1008 if (Cmnd->cmnd[0] == 0x12 && ok) {
1009 unsigned char *iqd;
1010 unsigned int iqd_len;
1011
1012 iqd_len = scsi_rbuf_get(Cmnd, &iqd);
1013
1014 /* tags handled in midlayer */
1015 /* enable sync mode? */
1016 if (iqd[7] & 0x10) {
1017 qpti->dev_param[tgt].device_flags |= 0x10;
1018 } else {
1019 qpti->dev_param[tgt].synchronous_offset = 0;
1020 qpti->dev_param[tgt].synchronous_period = 0;
1021 }
1022 /* are we wide capable? */
1023 if (iqd[7] & 0x20) {
1024 qpti->dev_param[tgt].device_flags |= 0x20;
1025 }
1026
1027 scsi_rbuf_put(Cmnd, iqd);
1028
1029 qpti->sbits |= (1 << tgt);
1030 } else if (!ok) {
1031 qpti->sbits |= (1 << tgt);
1032 }
1033 }
1034 done(Cmnd);
1035}
1036
1037static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *));
1038
1039static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd,
1040 void (*done)(struct scsi_cmnd *))
1041{
1042 struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
1043
1044 /*
1045 * done checking this host adapter?
1046 * If not, then rewrite the command
1047 * to finish through ourdone so we
1048 * can peek at Inquiry data results.
1049 */
1050 if (qpti->sbits && qpti->sbits != 0xffff) {
1051 /* See above about in ourdone this ugliness... */
1052 Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;
1053#ifdef CONFIG_SPARC64
1054 Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;
1055#endif
1056 return qlogicpti_queuecommand(Cmnd, ourdone);
1057 }
1058
1059 /*
1060 * We've peeked at all targets for this bus- time
1061 * to set parameters for devices for real now.
1062 */
1063 if (qpti->sbits == 0xffff) {
1064 int i;
1065 for(i = 0; i < MAX_TARGETS; i++) {
1066 u_short param[6];
1067 param[0] = MBOX_SET_TARGET_PARAMS;
1068 param[1] = (i << 8);
1069 param[2] = (qpti->dev_param[i].device_flags << 8);
1070 if (qpti->dev_param[i].device_flags & 0x10) {
1071 param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
1072 qpti->dev_param[i].synchronous_period;
1073 } else {
1074 param[3] = 0;
1075 }
1076 (void) qlogicpti_mbox_command(qpti, param, 0);
1077 }
1078 /*
1079 * set to zero so any traverse through ourdone
1080 * doesn't start the whole process again,
1081 */
1082 qpti->sbits = 0;
1083 }
1084
1085 /* check to see if we're done with all adapters... */
1086 for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {
1087 if (qpti->sbits) {
1088 break;
1089 }
1090 } 978 }
1091 979 qlogicpti_mbox_command(qpti, param, 0);
1092 /* 980 return 0;
1093 * if we hit the end of the chain w/o finding adapters still
1094 * capability-configuring, then we're done with all adapters
1095 * and can rock on..
1096 */
1097 if (qpti == NULL)
1098 Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand;
1099
1100 return qlogicpti_queuecommand(Cmnd, done);
1101} 981}
1102 982
1103/* 983/*
@@ -1390,7 +1270,8 @@ static struct scsi_host_template qpti_template = {
1390 .module = THIS_MODULE, 1270 .module = THIS_MODULE,
1391 .name = "qlogicpti", 1271 .name = "qlogicpti",
1392 .info = qlogicpti_info, 1272 .info = qlogicpti_info,
1393 .queuecommand = qlogicpti_queuecommand_slow, 1273 .queuecommand = qlogicpti_queuecommand,
1274 .slave_configure = qlogicpti_slave_configure,
1394 .eh_abort_handler = qlogicpti_abort, 1275 .eh_abort_handler = qlogicpti_abort,
1395 .eh_bus_reset_handler = qlogicpti_reset, 1276 .eh_bus_reset_handler = qlogicpti_reset,
1396 .can_queue = QLOGICPTI_REQ_QUEUE_LEN, 1277 .can_queue = QLOGICPTI_REQ_QUEUE_LEN,
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
index 6cd1c0771d29..ef6da2df584b 100644
--- a/drivers/scsi/qlogicpti.h
+++ b/drivers/scsi/qlogicpti.h
@@ -380,8 +380,7 @@ struct qlogicpti {
380 unsigned char swsreg; 380 unsigned char swsreg;
381 unsigned int 381 unsigned int
382 gotirq : 1, /* this instance got an irq */ 382 gotirq : 1, /* this instance got an irq */
383 is_pti : 1, /* Non-zero if this is a PTI board. */ 383 is_pti : 1; /* Non-zero if this is a PTI board. */
384 sbits : 16; /* syncmode known bits */
385}; 384};
386 385
387/* How to twiddle them bits... */ 386/* How to twiddle them bits... */