diff options
-rw-r--r-- | drivers/scsi/stex.c | 201 |
1 files changed, 125 insertions, 76 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index c4eb5c1cc1bc..75f5079e5696 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c | |||
@@ -95,19 +95,8 @@ enum { | |||
95 | TASK_ATTRIBUTE_ORDERED = 0x2, | 95 | TASK_ATTRIBUTE_ORDERED = 0x2, |
96 | TASK_ATTRIBUTE_ACA = 0x4, | 96 | TASK_ATTRIBUTE_ACA = 0x4, |
97 | 97 | ||
98 | /* request count, etc. */ | ||
99 | MU_MAX_REQUEST = 32, | ||
100 | |||
101 | /* one message wasted, use MU_MAX_REQUEST+1 | ||
102 | to handle MU_MAX_REQUEST messages */ | ||
103 | MU_REQ_COUNT = (MU_MAX_REQUEST + 1), | ||
104 | MU_STATUS_COUNT = (MU_MAX_REQUEST + 1), | ||
105 | |||
106 | STEX_CDB_LENGTH = 16, | 98 | STEX_CDB_LENGTH = 16, |
107 | REQ_VARIABLE_LEN = 1024, | ||
108 | STATUS_VAR_LEN = 128, | 99 | STATUS_VAR_LEN = 128, |
109 | ST_CAN_QUEUE = MU_MAX_REQUEST, | ||
110 | ST_CMD_PER_LUN = MU_MAX_REQUEST, | ||
111 | ST_MAX_SG = 32, | 100 | ST_MAX_SG = 32, |
112 | 101 | ||
113 | /* sg flags */ | 102 | /* sg flags */ |
@@ -120,9 +109,8 @@ enum { | |||
120 | 109 | ||
121 | st_shasta = 0, | 110 | st_shasta = 0, |
122 | st_vsc = 1, | 111 | st_vsc = 1, |
123 | st_vsc1 = 2, | 112 | st_yosemite = 2, |
124 | st_yosemite = 3, | 113 | st_seq = 3, |
125 | st_seq = 4, | ||
126 | 114 | ||
127 | PASSTHRU_REQ_TYPE = 0x00000001, | 115 | PASSTHRU_REQ_TYPE = 0x00000001, |
128 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, | 116 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, |
@@ -196,7 +184,7 @@ struct req_msg { | |||
196 | u8 data_dir; | 184 | u8 data_dir; |
197 | u8 payload_sz; /* payload size in 4-byte, not used */ | 185 | u8 payload_sz; /* payload size in 4-byte, not used */ |
198 | u8 cdb[STEX_CDB_LENGTH]; | 186 | u8 cdb[STEX_CDB_LENGTH]; |
199 | u8 variable[REQ_VARIABLE_LEN]; | 187 | u32 variable[0]; |
200 | }; | 188 | }; |
201 | 189 | ||
202 | struct status_msg { | 190 | struct status_msg { |
@@ -252,12 +240,6 @@ struct st_drvver { | |||
252 | u32 reserved[3]; | 240 | u32 reserved[3]; |
253 | }; | 241 | }; |
254 | 242 | ||
255 | #define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg)) | ||
256 | #define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg)) | ||
257 | #define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE) | ||
258 | #define STEX_EXTRA_SIZE sizeof(struct st_frame) | ||
259 | #define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE) | ||
260 | |||
261 | struct st_ccb { | 243 | struct st_ccb { |
262 | struct req_msg *req; | 244 | struct req_msg *req; |
263 | struct scsi_cmnd *cmd; | 245 | struct scsi_cmnd *cmd; |
@@ -288,13 +270,26 @@ struct st_hba { | |||
288 | 270 | ||
289 | struct status_msg *status_buffer; | 271 | struct status_msg *status_buffer; |
290 | void *copy_buffer; /* temp buffer for driver-handled commands */ | 272 | void *copy_buffer; /* temp buffer for driver-handled commands */ |
291 | struct st_ccb ccb[MU_MAX_REQUEST]; | 273 | struct st_ccb *ccb; |
292 | struct st_ccb *wait_ccb; | 274 | struct st_ccb *wait_ccb; |
293 | 275 | ||
294 | unsigned int mu_status; | 276 | unsigned int mu_status; |
295 | unsigned int cardtype; | 277 | unsigned int cardtype; |
296 | int msi_enabled; | 278 | int msi_enabled; |
297 | int out_req_cnt; | 279 | int out_req_cnt; |
280 | u32 extra_offset; | ||
281 | u16 rq_count; | ||
282 | u16 rq_size; | ||
283 | u16 sts_count; | ||
284 | }; | ||
285 | |||
286 | struct st_card_info { | ||
287 | unsigned int max_id; | ||
288 | unsigned int max_lun; | ||
289 | unsigned int max_channel; | ||
290 | u16 rq_count; | ||
291 | u16 rq_size; | ||
292 | u16 sts_count; | ||
298 | }; | 293 | }; |
299 | 294 | ||
300 | static int msi; | 295 | static int msi; |
@@ -331,7 +326,7 @@ static struct status_msg *stex_get_status(struct st_hba *hba) | |||
331 | struct status_msg *status = hba->status_buffer + hba->status_tail; | 326 | struct status_msg *status = hba->status_buffer + hba->status_tail; |
332 | 327 | ||
333 | ++hba->status_tail; | 328 | ++hba->status_tail; |
334 | hba->status_tail %= MU_STATUS_COUNT; | 329 | hba->status_tail %= hba->sts_count+1; |
335 | 330 | ||
336 | return status; | 331 | return status; |
337 | } | 332 | } |
@@ -349,11 +344,10 @@ static void stex_invalid_field(struct scsi_cmnd *cmd, | |||
349 | 344 | ||
350 | static struct req_msg *stex_alloc_req(struct st_hba *hba) | 345 | static struct req_msg *stex_alloc_req(struct st_hba *hba) |
351 | { | 346 | { |
352 | struct req_msg *req = ((struct req_msg *)hba->dma_mem) + | 347 | struct req_msg *req = hba->dma_mem + hba->req_head * hba->rq_size; |
353 | hba->req_head; | ||
354 | 348 | ||
355 | ++hba->req_head; | 349 | ++hba->req_head; |
356 | hba->req_head %= MU_REQ_COUNT; | 350 | hba->req_head %= hba->rq_count+1; |
357 | 351 | ||
358 | return req; | 352 | return req; |
359 | } | 353 | } |
@@ -653,7 +647,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) | |||
653 | 647 | ||
654 | /* status payloads */ | 648 | /* status payloads */ |
655 | hba->status_head = readl(base + OMR1); | 649 | hba->status_head = readl(base + OMR1); |
656 | if (unlikely(hba->status_head >= MU_STATUS_COUNT)) { | 650 | if (unlikely(hba->status_head > hba->sts_count)) { |
657 | printk(KERN_WARNING DRV_NAME "(%s): invalid status head\n", | 651 | printk(KERN_WARNING DRV_NAME "(%s): invalid status head\n", |
658 | pci_name(hba->pdev)); | 652 | pci_name(hba->pdev)); |
659 | return; | 653 | return; |
@@ -789,19 +783,19 @@ static int stex_handshake(struct st_hba *hba) | |||
789 | 783 | ||
790 | h = (struct handshake_frame *)hba->status_buffer; | 784 | h = (struct handshake_frame *)hba->status_buffer; |
791 | h->rb_phy = cpu_to_le64(hba->dma_handle); | 785 | h->rb_phy = cpu_to_le64(hba->dma_handle); |
792 | h->req_sz = cpu_to_le16(sizeof(struct req_msg)); | 786 | h->req_sz = cpu_to_le16(hba->rq_size); |
793 | h->req_cnt = cpu_to_le16(MU_REQ_COUNT); | 787 | h->req_cnt = cpu_to_le16(hba->rq_count+1); |
794 | h->status_sz = cpu_to_le16(sizeof(struct status_msg)); | 788 | h->status_sz = cpu_to_le16(sizeof(struct status_msg)); |
795 | h->status_cnt = cpu_to_le16(MU_STATUS_COUNT); | 789 | h->status_cnt = cpu_to_le16(hba->sts_count+1); |
796 | stex_gettime(&h->hosttime); | 790 | stex_gettime(&h->hosttime); |
797 | h->partner_type = HMU_PARTNER_TYPE; | 791 | h->partner_type = HMU_PARTNER_TYPE; |
798 | if (hba->dma_size > STEX_BUFFER_SIZE) { | 792 | if (hba->extra_offset) { |
799 | h->extra_offset = cpu_to_le32(STEX_BUFFER_SIZE); | 793 | h->extra_offset = cpu_to_le32(hba->extra_offset); |
800 | h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); | 794 | h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); |
801 | } else | 795 | } else |
802 | h->extra_offset = h->extra_size = 0; | 796 | h->extra_offset = h->extra_size = 0; |
803 | 797 | ||
804 | status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE; | 798 | status_phys = hba->dma_handle + (hba->rq_count+1) * hba->rq_size; |
805 | writel(status_phys, base + IMR0); | 799 | writel(status_phys, base + IMR0); |
806 | readl(base + IMR0); | 800 | readl(base + IMR0); |
807 | writel((status_phys >> 16) >> 16, base + IMR1); | 801 | writel((status_phys >> 16) >> 16, base + IMR1); |
@@ -1026,10 +1020,72 @@ static struct scsi_host_template driver_template = { | |||
1026 | .slave_destroy = stex_slave_destroy, | 1020 | .slave_destroy = stex_slave_destroy, |
1027 | .eh_abort_handler = stex_abort, | 1021 | .eh_abort_handler = stex_abort, |
1028 | .eh_host_reset_handler = stex_reset, | 1022 | .eh_host_reset_handler = stex_reset, |
1029 | .can_queue = ST_CAN_QUEUE, | ||
1030 | .this_id = -1, | 1023 | .this_id = -1, |
1031 | .sg_tablesize = ST_MAX_SG, | 1024 | .sg_tablesize = ST_MAX_SG, |
1032 | .cmd_per_lun = ST_CMD_PER_LUN, | 1025 | }; |
1026 | |||
1027 | static struct pci_device_id stex_pci_tbl[] = { | ||
1028 | /* st_shasta */ | ||
1029 | { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1030 | st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */ | ||
1031 | { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1032 | st_shasta }, /* SuperTrak EX12350 */ | ||
1033 | { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1034 | st_shasta }, /* SuperTrak EX4350 */ | ||
1035 | { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1036 | st_shasta }, /* SuperTrak EX24350 */ | ||
1037 | |||
1038 | /* st_vsc */ | ||
1039 | { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, | ||
1040 | |||
1041 | /* st_yosemite */ | ||
1042 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, | ||
1043 | |||
1044 | /* st_seq */ | ||
1045 | { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, | ||
1046 | { } /* terminate list */ | ||
1047 | }; | ||
1048 | |||
1049 | static struct st_card_info stex_card_info[] = { | ||
1050 | /* st_shasta */ | ||
1051 | { | ||
1052 | .max_id = 17, | ||
1053 | .max_lun = 8, | ||
1054 | .max_channel = 0, | ||
1055 | .rq_count = 32, | ||
1056 | .rq_size = 1048, | ||
1057 | .sts_count = 32, | ||
1058 | }, | ||
1059 | |||
1060 | /* st_vsc */ | ||
1061 | { | ||
1062 | .max_id = 129, | ||
1063 | .max_lun = 1, | ||
1064 | .max_channel = 0, | ||
1065 | .rq_count = 32, | ||
1066 | .rq_size = 1048, | ||
1067 | .sts_count = 32, | ||
1068 | }, | ||
1069 | |||
1070 | /* st_yosemite */ | ||
1071 | { | ||
1072 | .max_id = 2, | ||
1073 | .max_lun = 256, | ||
1074 | .max_channel = 0, | ||
1075 | .rq_count = 256, | ||
1076 | .rq_size = 1048, | ||
1077 | .sts_count = 256, | ||
1078 | }, | ||
1079 | |||
1080 | /* st_seq */ | ||
1081 | { | ||
1082 | .max_id = 129, | ||
1083 | .max_lun = 1, | ||
1084 | .max_channel = 0, | ||
1085 | .rq_count = 32, | ||
1086 | .rq_size = 1048, | ||
1087 | .sts_count = 32, | ||
1088 | }, | ||
1033 | }; | 1089 | }; |
1034 | 1090 | ||
1035 | static int stex_set_dma_mask(struct pci_dev * pdev) | 1091 | static int stex_set_dma_mask(struct pci_dev * pdev) |
@@ -1084,6 +1140,8 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1084 | { | 1140 | { |
1085 | struct st_hba *hba; | 1141 | struct st_hba *hba; |
1086 | struct Scsi_Host *host; | 1142 | struct Scsi_Host *host; |
1143 | const struct st_card_info *ci = NULL; | ||
1144 | u32 sts_offset, cp_offset; | ||
1087 | int err; | 1145 | int err; |
1088 | 1146 | ||
1089 | err = pci_enable_device(pdev); | 1147 | err = pci_enable_device(pdev); |
@@ -1127,10 +1185,15 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1127 | } | 1185 | } |
1128 | 1186 | ||
1129 | hba->cardtype = (unsigned int) id->driver_data; | 1187 | hba->cardtype = (unsigned int) id->driver_data; |
1130 | if (hba->cardtype == st_vsc && (pdev->subsystem_device & 1)) | 1188 | ci = &stex_card_info[hba->cardtype]; |
1131 | hba->cardtype = st_vsc1; | 1189 | sts_offset = (ci->rq_count+1) * ci->rq_size; |
1132 | hba->dma_size = (hba->cardtype == st_vsc1 || hba->cardtype == st_seq) ? | 1190 | cp_offset = sts_offset + (ci->sts_count+1) * sizeof(struct status_msg); |
1133 | (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); | 1191 | hba->dma_size = cp_offset + sizeof(struct st_frame); |
1192 | if (hba->cardtype == st_seq || | ||
1193 | (hba->cardtype == st_vsc && (pdev->subsystem_device & 1))) { | ||
1194 | hba->extra_offset = hba->dma_size; | ||
1195 | hba->dma_size += ST_ADDITIONAL_MEM; | ||
1196 | } | ||
1134 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, | 1197 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, |
1135 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); | 1198 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); |
1136 | if (!hba->dma_mem) { | 1199 | if (!hba->dma_mem) { |
@@ -1140,23 +1203,26 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1140 | goto out_iounmap; | 1203 | goto out_iounmap; |
1141 | } | 1204 | } |
1142 | 1205 | ||
1143 | hba->status_buffer = | 1206 | hba->ccb = kcalloc(ci->rq_count, sizeof(struct st_ccb), GFP_KERNEL); |
1144 | (struct status_msg *)(hba->dma_mem + MU_REQ_BUFFER_SIZE); | 1207 | if (!hba->ccb) { |
1145 | hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE; | 1208 | err = -ENOMEM; |
1209 | printk(KERN_ERR DRV_NAME "(%s): ccb alloc failed\n", | ||
1210 | pci_name(pdev)); | ||
1211 | goto out_pci_free; | ||
1212 | } | ||
1213 | |||
1214 | hba->status_buffer = (struct status_msg *)(hba->dma_mem + sts_offset); | ||
1215 | hba->copy_buffer = hba->dma_mem + cp_offset; | ||
1216 | hba->rq_count = ci->rq_count; | ||
1217 | hba->rq_size = ci->rq_size; | ||
1218 | hba->sts_count = ci->sts_count; | ||
1146 | hba->mu_status = MU_STATE_STARTING; | 1219 | hba->mu_status = MU_STATE_STARTING; |
1147 | 1220 | ||
1148 | if (hba->cardtype == st_shasta) { | 1221 | host->can_queue = ci->rq_count; |
1149 | host->max_lun = 8; | 1222 | host->cmd_per_lun = ci->rq_count; |
1150 | host->max_id = 16 + 1; | 1223 | host->max_id = ci->max_id; |
1151 | } else if (hba->cardtype == st_yosemite) { | 1224 | host->max_lun = ci->max_lun; |
1152 | host->max_lun = 256; | 1225 | host->max_channel = ci->max_channel; |
1153 | host->max_id = 1 + 1; | ||
1154 | } else { | ||
1155 | /* st_vsc , st_vsc1 and st_seq */ | ||
1156 | host->max_lun = 1; | ||
1157 | host->max_id = 128 + 1; | ||
1158 | } | ||
1159 | host->max_channel = 0; | ||
1160 | host->unique_id = host->host_no; | 1226 | host->unique_id = host->host_no; |
1161 | host->max_cmd_len = STEX_CDB_LENGTH; | 1227 | host->max_cmd_len = STEX_CDB_LENGTH; |
1162 | 1228 | ||
@@ -1167,7 +1233,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1167 | if (err) { | 1233 | if (err) { |
1168 | printk(KERN_ERR DRV_NAME "(%s): request irq failed\n", | 1234 | printk(KERN_ERR DRV_NAME "(%s): request irq failed\n", |
1169 | pci_name(pdev)); | 1235 | pci_name(pdev)); |
1170 | goto out_pci_free; | 1236 | goto out_ccb_free; |
1171 | } | 1237 | } |
1172 | 1238 | ||
1173 | err = stex_handshake(hba); | 1239 | err = stex_handshake(hba); |
@@ -1196,6 +1262,8 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1196 | 1262 | ||
1197 | out_free_irq: | 1263 | out_free_irq: |
1198 | stex_free_irq(hba); | 1264 | stex_free_irq(hba); |
1265 | out_ccb_free: | ||
1266 | kfree(hba->ccb); | ||
1199 | out_pci_free: | 1267 | out_pci_free: |
1200 | dma_free_coherent(&pdev->dev, hba->dma_size, | 1268 | dma_free_coherent(&pdev->dev, hba->dma_size, |
1201 | hba->dma_mem, hba->dma_handle); | 1269 | hba->dma_mem, hba->dma_handle); |
@@ -1260,6 +1328,8 @@ static void stex_hba_free(struct st_hba *hba) | |||
1260 | 1328 | ||
1261 | pci_release_regions(hba->pdev); | 1329 | pci_release_regions(hba->pdev); |
1262 | 1330 | ||
1331 | kfree(hba->ccb); | ||
1332 | |||
1263 | dma_free_coherent(&hba->pdev->dev, hba->dma_size, | 1333 | dma_free_coherent(&hba->pdev->dev, hba->dma_size, |
1264 | hba->dma_mem, hba->dma_handle); | 1334 | hba->dma_mem, hba->dma_handle); |
1265 | } | 1335 | } |
@@ -1288,27 +1358,6 @@ static void stex_shutdown(struct pci_dev *pdev) | |||
1288 | stex_hba_stop(hba); | 1358 | stex_hba_stop(hba); |
1289 | } | 1359 | } |
1290 | 1360 | ||
1291 | static struct pci_device_id stex_pci_tbl[] = { | ||
1292 | /* st_shasta */ | ||
1293 | { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1294 | st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */ | ||
1295 | { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1296 | st_shasta }, /* SuperTrak EX12350 */ | ||
1297 | { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1298 | st_shasta }, /* SuperTrak EX4350 */ | ||
1299 | { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1300 | st_shasta }, /* SuperTrak EX24350 */ | ||
1301 | |||
1302 | /* st_vsc */ | ||
1303 | { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, | ||
1304 | |||
1305 | /* st_yosemite */ | ||
1306 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, | ||
1307 | |||
1308 | /* st_seq */ | ||
1309 | { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, | ||
1310 | { } /* terminate list */ | ||
1311 | }; | ||
1312 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); | 1361 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); |
1313 | 1362 | ||
1314 | static struct pci_driver stex_pci_driver = { | 1363 | static struct pci_driver stex_pci_driver = { |