diff options
author | Matthew Wilcox <matthew@wil.cx> | 2007-10-01 10:07:52 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:52:38 -0400 |
commit | 9ec76fbf7d6da3e98070a7059699d0ca019b0c9b (patch) | |
tree | 6370b64b39555c4df92232a3ba9a65b11bebbba1 | |
parent | 50865c1d38e3fbe17a1843582a8e10f2dbbeb6d3 (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.c | 171 | ||||
-rw-r--r-- | drivers/scsi/qlogicpti.h | 3 |
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 | ||
317 | static int qlogicpti_reset_hardware(struct Scsi_Host *host) | 315 | 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 | |||
951 | host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); | 949 | host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); |
952 | } | 950 | } |
953 | 951 | ||
954 | static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) | 952 | static 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; | |
974 | static 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 | */ | ||
987 | static 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 | |||
1037 | static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *)); | ||
1038 | |||
1039 | static 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... */ |