diff options
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 1329 |
1 files changed, 539 insertions, 790 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index e62c6bc4ad33..8440f78f6969 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -80,7 +80,7 @@ MODULE_VERSION(my_VERSION); | |||
80 | /* | 80 | /* |
81 | * Other private/forward protos... | 81 | * Other private/forward protos... |
82 | */ | 82 | */ |
83 | static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); | 83 | struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); |
84 | static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); | 84 | static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); |
85 | static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); | 85 | static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); |
86 | static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); | 86 | static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); |
@@ -92,18 +92,24 @@ static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, | |||
92 | SCSIIORequest_t *pReq, int req_idx); | 92 | SCSIIORequest_t *pReq, int req_idx); |
93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); | 93 | static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); |
94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); | 94 | static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); |
95 | static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); | ||
96 | static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); | ||
97 | 95 | ||
98 | static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); | 96 | int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, |
97 | int lun, int ctx2abort, ulong timeout); | ||
99 | 98 | ||
100 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 99 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
101 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 100 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
102 | 101 | ||
102 | void | ||
103 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); | ||
104 | static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, | ||
105 | MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | ||
103 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 106 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
104 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 107 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
105 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 108 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
106 | 109 | ||
110 | static int | ||
111 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, | ||
112 | SCSITaskMgmtReply_t *pScsiTmReply); | ||
107 | void mptscsih_remove(struct pci_dev *); | 113 | void mptscsih_remove(struct pci_dev *); |
108 | void mptscsih_shutdown(struct pci_dev *); | 114 | void mptscsih_shutdown(struct pci_dev *); |
109 | #ifdef CONFIG_PM | 115 | #ifdef CONFIG_PM |
@@ -113,69 +119,6 @@ int mptscsih_resume(struct pci_dev *pdev); | |||
113 | 119 | ||
114 | #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE | 120 | #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE |
115 | 121 | ||
116 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
117 | /** | ||
118 | * mptscsih_add_sge - Place a simple SGE at address pAddr. | ||
119 | * @pAddr: virtual address for SGE | ||
120 | * @flagslength: SGE flags and data transfer length | ||
121 | * @dma_addr: Physical address | ||
122 | * | ||
123 | * This routine places a MPT request frame back on the MPT adapter's | ||
124 | * FreeQ. | ||
125 | */ | ||
126 | static inline void | ||
127 | mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) | ||
128 | { | ||
129 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
130 | SGESimple64_t *pSge = (SGESimple64_t *) pAddr; | ||
131 | u32 tmp = dma_addr & 0xFFFFFFFF; | ||
132 | |||
133 | pSge->FlagsLength = cpu_to_le32(flagslength); | ||
134 | pSge->Address.Low = cpu_to_le32(tmp); | ||
135 | tmp = (u32) ((u64)dma_addr >> 32); | ||
136 | pSge->Address.High = cpu_to_le32(tmp); | ||
137 | |||
138 | } else { | ||
139 | SGESimple32_t *pSge = (SGESimple32_t *) pAddr; | ||
140 | pSge->FlagsLength = cpu_to_le32(flagslength); | ||
141 | pSge->Address = cpu_to_le32(dma_addr); | ||
142 | } | ||
143 | } /* mptscsih_add_sge() */ | ||
144 | |||
145 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
146 | /** | ||
147 | * mptscsih_add_chain - Place a chain SGE at address pAddr. | ||
148 | * @pAddr: virtual address for SGE | ||
149 | * @next: nextChainOffset value (u32's) | ||
150 | * @length: length of next SGL segment | ||
151 | * @dma_addr: Physical address | ||
152 | * | ||
153 | * This routine places a MPT request frame back on the MPT adapter's | ||
154 | * FreeQ. | ||
155 | */ | ||
156 | static inline void | ||
157 | mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr) | ||
158 | { | ||
159 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
160 | SGEChain64_t *pChain = (SGEChain64_t *) pAddr; | ||
161 | u32 tmp = dma_addr & 0xFFFFFFFF; | ||
162 | |||
163 | pChain->Length = cpu_to_le16(length); | ||
164 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); | ||
165 | |||
166 | pChain->NextChainOffset = next; | ||
167 | |||
168 | pChain->Address.Low = cpu_to_le32(tmp); | ||
169 | tmp = (u32) ((u64)dma_addr >> 32); | ||
170 | pChain->Address.High = cpu_to_le32(tmp); | ||
171 | } else { | ||
172 | SGEChain32_t *pChain = (SGEChain32_t *) pAddr; | ||
173 | pChain->Length = cpu_to_le16(length); | ||
174 | pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size(); | ||
175 | pChain->NextChainOffset = next; | ||
176 | pChain->Address = cpu_to_le32(dma_addr); | ||
177 | } | ||
178 | } /* mptscsih_add_chain() */ | ||
179 | 122 | ||
180 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 123 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
181 | /* | 124 | /* |
@@ -281,10 +224,10 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, | |||
281 | */ | 224 | */ |
282 | 225 | ||
283 | nextSGEset: | 226 | nextSGEset: |
284 | numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) ); | 227 | numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size); |
285 | numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; | 228 | numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; |
286 | 229 | ||
287 | sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir; | 230 | sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir; |
288 | 231 | ||
289 | /* Get first (num - 1) SG elements | 232 | /* Get first (num - 1) SG elements |
290 | * Skip any SG entries with a length of 0 | 233 | * Skip any SG entries with a length of 0 |
@@ -293,17 +236,19 @@ nextSGEset: | |||
293 | for (ii=0; ii < (numSgeThisFrame-1); ii++) { | 236 | for (ii=0; ii < (numSgeThisFrame-1); ii++) { |
294 | thisxfer = sg_dma_len(sg); | 237 | thisxfer = sg_dma_len(sg); |
295 | if (thisxfer == 0) { | 238 | if (thisxfer == 0) { |
296 | sg = sg_next(sg); /* Get next SG element from the OS */ | 239 | /* Get next SG element from the OS */ |
240 | sg = sg_next(sg); | ||
297 | sg_done++; | 241 | sg_done++; |
298 | continue; | 242 | continue; |
299 | } | 243 | } |
300 | 244 | ||
301 | v2 = sg_dma_address(sg); | 245 | v2 = sg_dma_address(sg); |
302 | mptscsih_add_sge(psge, sgflags | thisxfer, v2); | 246 | ioc->add_sge(psge, sgflags | thisxfer, v2); |
303 | 247 | ||
304 | sg = sg_next(sg); /* Get next SG element from the OS */ | 248 | /* Get next SG element from the OS */ |
305 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | 249 | sg = sg_next(sg); |
306 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | 250 | psge += ioc->SGE_size; |
251 | sgeOffset += ioc->SGE_size; | ||
307 | sg_done++; | 252 | sg_done++; |
308 | } | 253 | } |
309 | 254 | ||
@@ -320,12 +265,8 @@ nextSGEset: | |||
320 | thisxfer = sg_dma_len(sg); | 265 | thisxfer = sg_dma_len(sg); |
321 | 266 | ||
322 | v2 = sg_dma_address(sg); | 267 | v2 = sg_dma_address(sg); |
323 | mptscsih_add_sge(psge, sgflags | thisxfer, v2); | 268 | ioc->add_sge(psge, sgflags | thisxfer, v2); |
324 | /* | 269 | sgeOffset += ioc->SGE_size; |
325 | sg = sg_next(sg); | ||
326 | psge += (sizeof(u32) + sizeof(dma_addr_t)); | ||
327 | */ | ||
328 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | ||
329 | sg_done++; | 270 | sg_done++; |
330 | 271 | ||
331 | if (chainSge) { | 272 | if (chainSge) { |
@@ -334,7 +275,8 @@ nextSGEset: | |||
334 | * Update the chain element | 275 | * Update the chain element |
335 | * Offset and Length fields. | 276 | * Offset and Length fields. |
336 | */ | 277 | */ |
337 | mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); | 278 | ioc->add_chain((char *)chainSge, 0, sgeOffset, |
279 | ioc->ChainBufferDMA + chain_dma_off); | ||
338 | } else { | 280 | } else { |
339 | /* The current buffer is the original MF | 281 | /* The current buffer is the original MF |
340 | * and there is no Chain buffer. | 282 | * and there is no Chain buffer. |
@@ -367,7 +309,7 @@ nextSGEset: | |||
367 | * set properly). | 309 | * set properly). |
368 | */ | 310 | */ |
369 | if (sg_done) { | 311 | if (sg_done) { |
370 | u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t))); | 312 | u32 *ptmp = (u32 *) (psge - ioc->SGE_size); |
371 | sgflags = le32_to_cpu(*ptmp); | 313 | sgflags = le32_to_cpu(*ptmp); |
372 | sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; | 314 | sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; |
373 | *ptmp = cpu_to_le32(sgflags); | 315 | *ptmp = cpu_to_le32(sgflags); |
@@ -381,8 +323,9 @@ nextSGEset: | |||
381 | * Old chain element is now complete. | 323 | * Old chain element is now complete. |
382 | */ | 324 | */ |
383 | u8 nextChain = (u8) (sgeOffset >> 2); | 325 | u8 nextChain = (u8) (sgeOffset >> 2); |
384 | sgeOffset += (sizeof(u32) + sizeof(dma_addr_t)); | 326 | sgeOffset += ioc->SGE_size; |
385 | mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off); | 327 | ioc->add_chain((char *)chainSge, nextChain, sgeOffset, |
328 | ioc->ChainBufferDMA + chain_dma_off); | ||
386 | } else { | 329 | } else { |
387 | /* The original MF buffer requires a chain buffer - | 330 | /* The original MF buffer requires a chain buffer - |
388 | * set the offset. | 331 | * set the offset. |
@@ -592,14 +535,15 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc | |||
592 | } | 535 | } |
593 | 536 | ||
594 | scsi_print_command(sc); | 537 | scsi_print_command(sc); |
595 | printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n", | 538 | printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\n", |
596 | ioc->name, pScsiReply->Bus, pScsiReply->TargetID); | 539 | ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun); |
597 | printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " | 540 | printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " |
598 | "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, | 541 | "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, |
599 | scsi_get_resid(sc)); | 542 | scsi_get_resid(sc)); |
600 | printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " | 543 | printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " |
601 | "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), | 544 | "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), |
602 | le32_to_cpu(pScsiReply->TransferCount), sc->result); | 545 | le32_to_cpu(pScsiReply->TransferCount), sc->result); |
546 | |||
603 | printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " | 547 | printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " |
604 | "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", | 548 | "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", |
605 | ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, | 549 | ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, |
@@ -654,16 +598,14 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
654 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | 598 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); |
655 | req_idx_MR = (mr != NULL) ? | 599 | req_idx_MR = (mr != NULL) ? |
656 | le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; | 600 | le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; |
601 | |||
602 | /* Special case, where already freed message frame is received from | ||
603 | * Firmware. It happens with Resetting IOC. | ||
604 | * Return immediately. Do not care | ||
605 | */ | ||
657 | if ((req_idx != req_idx_MR) || | 606 | if ((req_idx != req_idx_MR) || |
658 | (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) { | 607 | (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf)) |
659 | printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n", | ||
660 | ioc->name); | ||
661 | printk (MYIOC_s_ERR_FMT | ||
662 | "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n", | ||
663 | ioc->name, req_idx, req_idx_MR, mf, mr, | ||
664 | mptscsih_get_scsi_lookup(ioc, req_idx_MR)); | ||
665 | return 0; | 608 | return 0; |
666 | } | ||
667 | 609 | ||
668 | sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); | 610 | sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); |
669 | if (sc == NULL) { | 611 | if (sc == NULL) { |
@@ -810,12 +752,16 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
810 | */ | 752 | */ |
811 | 753 | ||
812 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | 754 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ |
813 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
814 | /* Linux handles an unsolicited DID_RESET better | 755 | /* Linux handles an unsolicited DID_RESET better |
815 | * than an unsolicited DID_ABORT. | 756 | * than an unsolicited DID_ABORT. |
816 | */ | 757 | */ |
817 | sc->result = DID_RESET << 16; | 758 | sc->result = DID_RESET << 16; |
818 | 759 | ||
760 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
761 | if (ioc->bus_type == FC) | ||
762 | sc->result = DID_ERROR << 16; | ||
763 | else | ||
764 | sc->result = DID_RESET << 16; | ||
819 | break; | 765 | break; |
820 | 766 | ||
821 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ | 767 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ |
@@ -992,9 +938,9 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) | |||
992 | scsi_dma_unmap(sc); | 938 | scsi_dma_unmap(sc); |
993 | sc->result = DID_RESET << 16; | 939 | sc->result = DID_RESET << 16; |
994 | sc->host_scribble = NULL; | 940 | sc->host_scribble = NULL; |
995 | sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT | 941 | dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT |
996 | "completing cmds: fw_channel %d, fw_id %d, sc=%p," | 942 | "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, " |
997 | " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii); | 943 | "idx=%x\n", ioc->name, channel, id, sc, mf, ii)); |
998 | sc->scsi_done(sc); | 944 | sc->scsi_done(sc); |
999 | } | 945 | } |
1000 | } | 946 | } |
@@ -1053,9 +999,11 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) | |||
1053 | scsi_dma_unmap(sc); | 999 | scsi_dma_unmap(sc); |
1054 | sc->host_scribble = NULL; | 1000 | sc->host_scribble = NULL; |
1055 | sc->result = DID_NO_CONNECT << 16; | 1001 | sc->result = DID_NO_CONNECT << 16; |
1056 | sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d," | 1002 | dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, |
1057 | "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, | 1003 | MYIOC_s_FMT "completing cmds: fw_channel %d, " |
1058 | vdevice->vtarget->id, sc, mf, ii); | 1004 | "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, |
1005 | vdevice->vtarget->channel, vdevice->vtarget->id, | ||
1006 | sc, mf, ii)); | ||
1059 | sc->scsi_done(sc); | 1007 | sc->scsi_done(sc); |
1060 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1008 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
1061 | } | 1009 | } |
@@ -1346,7 +1294,6 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1346 | MPT_FRAME_HDR *mf; | 1294 | MPT_FRAME_HDR *mf; |
1347 | SCSIIORequest_t *pScsiReq; | 1295 | SCSIIORequest_t *pScsiReq; |
1348 | VirtDevice *vdevice = SCpnt->device->hostdata; | 1296 | VirtDevice *vdevice = SCpnt->device->hostdata; |
1349 | int lun; | ||
1350 | u32 datalen; | 1297 | u32 datalen; |
1351 | u32 scsictl; | 1298 | u32 scsictl; |
1352 | u32 scsidir; | 1299 | u32 scsidir; |
@@ -1357,13 +1304,12 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1357 | 1304 | ||
1358 | hd = shost_priv(SCpnt->device->host); | 1305 | hd = shost_priv(SCpnt->device->host); |
1359 | ioc = hd->ioc; | 1306 | ioc = hd->ioc; |
1360 | lun = SCpnt->device->lun; | ||
1361 | SCpnt->scsi_done = done; | 1307 | SCpnt->scsi_done = done; |
1362 | 1308 | ||
1363 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", | 1309 | dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", |
1364 | ioc->name, SCpnt, done)); | 1310 | ioc->name, SCpnt, done)); |
1365 | 1311 | ||
1366 | if (hd->resetPending) { | 1312 | if (ioc->taskmgmt_quiesce_io) { |
1367 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", | 1313 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", |
1368 | ioc->name, SCpnt)); | 1314 | ioc->name, SCpnt)); |
1369 | return SCSI_MLQUEUE_HOST_BUSY; | 1315 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -1422,7 +1368,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1422 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1368 | pScsiReq->CDBLength = SCpnt->cmd_len; |
1423 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; | 1369 | pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; |
1424 | pScsiReq->Reserved = 0; | 1370 | pScsiReq->Reserved = 0; |
1425 | pScsiReq->MsgFlags = mpt_msg_flags(); | 1371 | pScsiReq->MsgFlags = mpt_msg_flags(ioc); |
1426 | int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); | 1372 | int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); |
1427 | pScsiReq->Control = cpu_to_le32(scsictl); | 1373 | pScsiReq->Control = cpu_to_le32(scsictl); |
1428 | 1374 | ||
@@ -1448,7 +1394,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1448 | */ | 1394 | */ |
1449 | if (datalen == 0) { | 1395 | if (datalen == 0) { |
1450 | /* Add a NULL SGE */ | 1396 | /* Add a NULL SGE */ |
1451 | mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0, | 1397 | ioc->add_sge((char *)&pScsiReq->SGL, |
1398 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, | ||
1452 | (dma_addr_t) -1); | 1399 | (dma_addr_t) -1); |
1453 | } else { | 1400 | } else { |
1454 | /* Add a 32 or 64 bit SGE */ | 1401 | /* Add a 32 or 64 bit SGE */ |
@@ -1528,8 +1475,8 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1528 | 1475 | ||
1529 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1476 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1530 | /** | 1477 | /** |
1531 | * mptscsih_TMHandler - Generic handler for SCSI Task Management. | 1478 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. |
1532 | * @hd: Pointer to MPT SCSI HOST structure | 1479 | * @hd: Pointer to MPT_SCSI_HOST structure |
1533 | * @type: Task Management type | 1480 | * @type: Task Management type |
1534 | * @channel: channel number for task management | 1481 | * @channel: channel number for task management |
1535 | * @id: Logical Target ID for reset (if appropriate) | 1482 | * @id: Logical Target ID for reset (if appropriate) |
@@ -1537,145 +1484,68 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1537 | * @ctx2abort: Context for the task to be aborted (if appropriate) | 1484 | * @ctx2abort: Context for the task to be aborted (if appropriate) |
1538 | * @timeout: timeout for task management control | 1485 | * @timeout: timeout for task management control |
1539 | * | 1486 | * |
1540 | * Fall through to mpt_HardResetHandler if: not operational, too many | 1487 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) |
1541 | * failed TM requests or handshake failure. | 1488 | * or a non-interrupt thread. In the former, must not call schedule(). |
1542 | * | 1489 | * |
1543 | * Remark: Currently invoked from a non-interrupt thread (_bh). | 1490 | * Not all fields are meaningfull for all task types. |
1544 | * | 1491 | * |
1545 | * Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC | 1492 | * Returns 0 for SUCCESS, or FAILED. |
1546 | * will be active. | ||
1547 | * | 1493 | * |
1548 | * Returns 0 for SUCCESS, or %FAILED. | ||
1549 | **/ | 1494 | **/ |
1550 | int | 1495 | int |
1551 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | 1496 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, |
1497 | int ctx2abort, ulong timeout) | ||
1552 | { | 1498 | { |
1553 | MPT_ADAPTER *ioc; | 1499 | MPT_FRAME_HDR *mf; |
1554 | int rc = -1; | 1500 | SCSITaskMgmt_t *pScsiTm; |
1501 | int ii; | ||
1502 | int retval; | ||
1503 | MPT_ADAPTER *ioc = hd->ioc; | ||
1504 | unsigned long timeleft; | ||
1505 | u8 issue_hard_reset; | ||
1555 | u32 ioc_raw_state; | 1506 | u32 ioc_raw_state; |
1556 | unsigned long flags; | 1507 | unsigned long time_count; |
1557 | |||
1558 | ioc = hd->ioc; | ||
1559 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name)); | ||
1560 | |||
1561 | // SJR - CHECKME - Can we avoid this here? | ||
1562 | // (mpt_HardResetHandler has this check...) | ||
1563 | spin_lock_irqsave(&ioc->diagLock, flags); | ||
1564 | if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) { | ||
1565 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
1566 | return FAILED; | ||
1567 | } | ||
1568 | spin_unlock_irqrestore(&ioc->diagLock, flags); | ||
1569 | |||
1570 | /* Wait a fixed amount of time for the TM pending flag to be cleared. | ||
1571 | * If we time out and not bus reset, then we return a FAILED status | ||
1572 | * to the caller. | ||
1573 | * The call to mptscsih_tm_pending_wait() will set the pending flag | ||
1574 | * if we are | ||
1575 | * successful. Otherwise, reload the FW. | ||
1576 | */ | ||
1577 | if (mptscsih_tm_pending_wait(hd) == FAILED) { | ||
1578 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
1579 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: " | ||
1580 | "Timed out waiting for last TM (%d) to complete! \n", | ||
1581 | ioc->name, hd->tmPending)); | ||
1582 | return FAILED; | ||
1583 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { | ||
1584 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target " | ||
1585 | "reset: Timed out waiting for last TM (%d) " | ||
1586 | "to complete! \n", ioc->name, | ||
1587 | hd->tmPending)); | ||
1588 | return FAILED; | ||
1589 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { | ||
1590 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: " | ||
1591 | "Timed out waiting for last TM (%d) to complete! \n", | ||
1592 | ioc->name, hd->tmPending)); | ||
1593 | return FAILED; | ||
1594 | } | ||
1595 | } else { | ||
1596 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
1597 | hd->tmPending |= (1 << type); | ||
1598 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
1599 | } | ||
1600 | 1508 | ||
1509 | issue_hard_reset = 0; | ||
1601 | ioc_raw_state = mpt_GetIocState(ioc, 0); | 1510 | ioc_raw_state = mpt_GetIocState(ioc, 0); |
1602 | 1511 | ||
1603 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { | 1512 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { |
1604 | printk(MYIOC_s_WARN_FMT | 1513 | printk(MYIOC_s_WARN_FMT |
1605 | "TM Handler for type=%x: IOC Not operational (0x%x)!\n", | 1514 | "TaskMgmt type=%x: IOC Not operational (0x%x)!\n", |
1606 | ioc->name, type, ioc_raw_state); | 1515 | ioc->name, type, ioc_raw_state); |
1607 | printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name); | 1516 | printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", |
1517 | ioc->name, __func__); | ||
1608 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) | 1518 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) |
1609 | printk(MYIOC_s_WARN_FMT "TMHandler: HardReset " | 1519 | printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset " |
1610 | "FAILED!!\n", ioc->name); | 1520 | "FAILED!!\n", ioc->name); |
1611 | return FAILED; | 1521 | return 0; |
1612 | } | 1522 | } |
1613 | 1523 | ||
1614 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { | 1524 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { |
1615 | printk(MYIOC_s_WARN_FMT | 1525 | printk(MYIOC_s_WARN_FMT |
1616 | "TM Handler for type=%x: ioc_state: " | 1526 | "TaskMgmt type=%x: ioc_state: " |
1617 | "DOORBELL_ACTIVE (0x%x)!\n", | 1527 | "DOORBELL_ACTIVE (0x%x)!\n", |
1618 | ioc->name, type, ioc_raw_state); | 1528 | ioc->name, type, ioc_raw_state); |
1619 | return FAILED; | 1529 | return FAILED; |
1620 | } | 1530 | } |
1621 | 1531 | ||
1622 | /* Isse the Task Mgmt request. | 1532 | mutex_lock(&ioc->taskmgmt_cmds.mutex); |
1623 | */ | 1533 | if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { |
1624 | if (hd->hard_resets < -1) | 1534 | mf = NULL; |
1625 | hd->hard_resets++; | 1535 | retval = FAILED; |
1626 | 1536 | goto out; | |
1627 | rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, | 1537 | } |
1628 | ctx2abort, timeout); | ||
1629 | if (rc) | ||
1630 | printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", | ||
1631 | ioc->name); | ||
1632 | else | ||
1633 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n", | ||
1634 | ioc->name)); | ||
1635 | |||
1636 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
1637 | "TMHandler rc = %d!\n", ioc->name, rc)); | ||
1638 | |||
1639 | return rc; | ||
1640 | } | ||
1641 | |||
1642 | |||
1643 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1644 | /** | ||
1645 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. | ||
1646 | * @hd: Pointer to MPT_SCSI_HOST structure | ||
1647 | * @type: Task Management type | ||
1648 | * @channel: channel number for task management | ||
1649 | * @id: Logical Target ID for reset (if appropriate) | ||
1650 | * @lun: Logical Unit for reset (if appropriate) | ||
1651 | * @ctx2abort: Context for the task to be aborted (if appropriate) | ||
1652 | * @timeout: timeout for task management control | ||
1653 | * | ||
1654 | * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) | ||
1655 | * or a non-interrupt thread. In the former, must not call schedule(). | ||
1656 | * | ||
1657 | * Not all fields are meaningfull for all task types. | ||
1658 | * | ||
1659 | * Returns 0 for SUCCESS, or FAILED. | ||
1660 | * | ||
1661 | **/ | ||
1662 | static int | ||
1663 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | ||
1664 | { | ||
1665 | MPT_FRAME_HDR *mf; | ||
1666 | SCSITaskMgmt_t *pScsiTm; | ||
1667 | int ii; | ||
1668 | int retval; | ||
1669 | MPT_ADAPTER *ioc = hd->ioc; | ||
1670 | 1538 | ||
1671 | /* Return Fail to calling function if no message frames available. | 1539 | /* Return Fail to calling function if no message frames available. |
1672 | */ | 1540 | */ |
1673 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { | 1541 | if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { |
1674 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", | 1542 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
1675 | ioc->name)); | 1543 | "TaskMgmt no msg frames!!\n", ioc->name)); |
1676 | return FAILED; | 1544 | retval = FAILED; |
1545 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
1546 | goto out; | ||
1677 | } | 1547 | } |
1678 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", | 1548 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", |
1679 | ioc->name, mf)); | 1549 | ioc->name, mf)); |
1680 | 1550 | ||
1681 | /* Format the Request | 1551 | /* Format the Request |
@@ -1699,11 +1569,14 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
1699 | 1569 | ||
1700 | pScsiTm->TaskMsgContext = ctx2abort; | 1570 | pScsiTm->TaskMsgContext = ctx2abort; |
1701 | 1571 | ||
1702 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " | 1572 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) " |
1703 | "type=%d\n", ioc->name, ctx2abort, type)); | 1573 | "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort, |
1574 | type, timeout)); | ||
1704 | 1575 | ||
1705 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); | 1576 | DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); |
1706 | 1577 | ||
1578 | INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) | ||
1579 | time_count = jiffies; | ||
1707 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && | 1580 | if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && |
1708 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) | 1581 | (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) |
1709 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); | 1582 | mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); |
@@ -1711,47 +1584,50 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
1711 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, | 1584 | retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, |
1712 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); | 1585 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); |
1713 | if (retval) { | 1586 | if (retval) { |
1714 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" | 1587 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT |
1715 | " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd, | 1588 | "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n", |
1716 | ioc, mf, retval)); | 1589 | ioc->name, mf, retval)); |
1717 | goto fail_out; | 1590 | mpt_free_msg_frame(ioc, mf); |
1591 | mpt_clear_taskmgmt_in_progress_flag(ioc); | ||
1592 | goto out; | ||
1718 | } | 1593 | } |
1719 | } | 1594 | } |
1720 | 1595 | ||
1721 | if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { | 1596 | timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, |
1722 | dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" | 1597 | timeout*HZ); |
1723 | " (hd %p, ioc %p, mf %p) \n", ioc->name, hd, | 1598 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
1724 | ioc, mf)); | 1599 | retval = FAILED; |
1725 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", | 1600 | dtmprintk(ioc, printk(MYIOC_s_ERR_FMT |
1726 | ioc->name)); | 1601 | "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf)); |
1727 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); | 1602 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
1728 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", | 1603 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) |
1729 | ioc->name, retval)); | 1604 | goto out; |
1730 | goto fail_out; | 1605 | issue_hard_reset = 1; |
1606 | goto out; | ||
1731 | } | 1607 | } |
1732 | 1608 | ||
1733 | /* | 1609 | retval = mptscsih_taskmgmt_reply(ioc, type, |
1734 | * Handle success case, see if theres a non-zero ioc_status. | 1610 | (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply); |
1735 | */ | ||
1736 | if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || | ||
1737 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
1738 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
1739 | retval = 0; | ||
1740 | else | ||
1741 | retval = FAILED; | ||
1742 | 1611 | ||
1743 | return retval; | 1612 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
1613 | "TaskMgmt completed (%d seconds)\n", | ||
1614 | ioc->name, jiffies_to_msecs(jiffies - time_count)/1000)); | ||
1744 | 1615 | ||
1745 | fail_out: | 1616 | out: |
1746 | 1617 | ||
1747 | /* | 1618 | CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) |
1748 | * Free task management mf, and corresponding tm flags | 1619 | if (issue_hard_reset) { |
1749 | */ | 1620 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
1750 | mpt_free_msg_frame(ioc, mf); | 1621 | ioc->name, __func__); |
1751 | hd->tmPending = 0; | 1622 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); |
1752 | hd->tmState = TM_STATE_NONE; | 1623 | mpt_free_msg_frame(ioc, mf); |
1753 | return FAILED; | 1624 | } |
1625 | |||
1626 | retval = (retval == 0) ? 0 : FAILED; | ||
1627 | mutex_unlock(&ioc->taskmgmt_cmds.mutex); | ||
1628 | return retval; | ||
1754 | } | 1629 | } |
1630 | EXPORT_SYMBOL(mptscsih_IssueTaskMgmt); | ||
1755 | 1631 | ||
1756 | static int | 1632 | static int |
1757 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) | 1633 | mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) |
@@ -1838,13 +1714,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1838 | goto out; | 1714 | goto out; |
1839 | } | 1715 | } |
1840 | 1716 | ||
1841 | if (hd->resetPending) { | 1717 | if (ioc->timeouts < -1) |
1842 | retval = FAILED; | 1718 | ioc->timeouts++; |
1843 | goto out; | ||
1844 | } | ||
1845 | |||
1846 | if (hd->timeouts < -1) | ||
1847 | hd->timeouts++; | ||
1848 | 1719 | ||
1849 | if (mpt_fwfault_debug) | 1720 | if (mpt_fwfault_debug) |
1850 | mpt_halt_firmware(ioc); | 1721 | mpt_halt_firmware(ioc); |
@@ -1861,22 +1732,30 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1861 | 1732 | ||
1862 | hd->abortSCpnt = SCpnt; | 1733 | hd->abortSCpnt = SCpnt; |
1863 | 1734 | ||
1864 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1735 | retval = mptscsih_IssueTaskMgmt(hd, |
1865 | vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, | 1736 | MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
1866 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | 1737 | vdevice->vtarget->channel, |
1738 | vdevice->vtarget->id, vdevice->lun, | ||
1739 | ctx2abort, mptscsih_get_tm_timeout(ioc)); | ||
1867 | 1740 | ||
1868 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && | 1741 | if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && |
1869 | SCpnt->serial_number == sn) | 1742 | SCpnt->serial_number == sn) { |
1743 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
1744 | "task abort: command still in active list! (sc=%p)\n", | ||
1745 | ioc->name, SCpnt)); | ||
1870 | retval = FAILED; | 1746 | retval = FAILED; |
1747 | } else { | ||
1748 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
1749 | "task abort: command cleared from active list! (sc=%p)\n", | ||
1750 | ioc->name, SCpnt)); | ||
1751 | retval = SUCCESS; | ||
1752 | } | ||
1871 | 1753 | ||
1872 | out: | 1754 | out: |
1873 | printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", | 1755 | printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", |
1874 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1756 | ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt); |
1875 | 1757 | ||
1876 | if (retval == 0) | 1758 | return retval; |
1877 | return SUCCESS; | ||
1878 | else | ||
1879 | return FAILED; | ||
1880 | } | 1759 | } |
1881 | 1760 | ||
1882 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1761 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -1909,14 +1788,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1909 | ioc->name, SCpnt); | 1788 | ioc->name, SCpnt); |
1910 | scsi_print_command(SCpnt); | 1789 | scsi_print_command(SCpnt); |
1911 | 1790 | ||
1912 | if (hd->resetPending) { | ||
1913 | retval = FAILED; | ||
1914 | goto out; | ||
1915 | } | ||
1916 | |||
1917 | vdevice = SCpnt->device->hostdata; | 1791 | vdevice = SCpnt->device->hostdata; |
1918 | if (!vdevice || !vdevice->vtarget) { | 1792 | if (!vdevice || !vdevice->vtarget) { |
1919 | retval = 0; | 1793 | retval = SUCCESS; |
1920 | goto out; | 1794 | goto out; |
1921 | } | 1795 | } |
1922 | 1796 | ||
@@ -1927,9 +1801,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1927 | goto out; | 1801 | goto out; |
1928 | } | 1802 | } |
1929 | 1803 | ||
1930 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1804 | retval = mptscsih_IssueTaskMgmt(hd, |
1931 | vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0, | 1805 | MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
1932 | mptscsih_get_tm_timeout(ioc)); | 1806 | vdevice->vtarget->channel, |
1807 | vdevice->vtarget->id, 0, 0, | ||
1808 | mptscsih_get_tm_timeout(ioc)); | ||
1933 | 1809 | ||
1934 | out: | 1810 | out: |
1935 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", | 1811 | printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", |
@@ -1972,12 +1848,16 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
1972 | ioc->name, SCpnt); | 1848 | ioc->name, SCpnt); |
1973 | scsi_print_command(SCpnt); | 1849 | scsi_print_command(SCpnt); |
1974 | 1850 | ||
1975 | if (hd->timeouts < -1) | 1851 | if (ioc->timeouts < -1) |
1976 | hd->timeouts++; | 1852 | ioc->timeouts++; |
1977 | 1853 | ||
1978 | vdevice = SCpnt->device->hostdata; | 1854 | vdevice = SCpnt->device->hostdata; |
1979 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1855 | if (!vdevice || !vdevice->vtarget) |
1980 | vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); | 1856 | return SUCCESS; |
1857 | retval = mptscsih_IssueTaskMgmt(hd, | ||
1858 | MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | ||
1859 | vdevice->vtarget->channel, 0, 0, 0, | ||
1860 | mptscsih_get_tm_timeout(ioc)); | ||
1981 | 1861 | ||
1982 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", | 1862 | printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", |
1983 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1863 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
@@ -2001,8 +1881,9 @@ int | |||
2001 | mptscsih_host_reset(struct scsi_cmnd *SCpnt) | 1881 | mptscsih_host_reset(struct scsi_cmnd *SCpnt) |
2002 | { | 1882 | { |
2003 | MPT_SCSI_HOST * hd; | 1883 | MPT_SCSI_HOST * hd; |
2004 | int retval; | 1884 | int status = SUCCESS; |
2005 | MPT_ADAPTER *ioc; | 1885 | MPT_ADAPTER *ioc; |
1886 | int retval; | ||
2006 | 1887 | ||
2007 | /* If we can't locate the host to reset, then we failed. */ | 1888 | /* If we can't locate the host to reset, then we failed. */ |
2008 | if ((hd = shost_priv(SCpnt->device->host)) == NULL){ | 1889 | if ((hd = shost_priv(SCpnt->device->host)) == NULL){ |
@@ -2021,86 +1902,71 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) | |||
2021 | /* If our attempts to reset the host failed, then return a failed | 1902 | /* If our attempts to reset the host failed, then return a failed |
2022 | * status. The host will be taken off line by the SCSI mid-layer. | 1903 | * status. The host will be taken off line by the SCSI mid-layer. |
2023 | */ | 1904 | */ |
2024 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) { | 1905 | retval = mpt_HardResetHandler(ioc, CAN_SLEEP); |
2025 | retval = FAILED; | 1906 | if (retval < 0) |
2026 | } else { | 1907 | status = FAILED; |
2027 | /* Make sure TM pending is cleared and TM state is set to | 1908 | else |
2028 | * NONE. | 1909 | status = SUCCESS; |
2029 | */ | ||
2030 | retval = 0; | ||
2031 | hd->tmPending = 0; | ||
2032 | hd->tmState = TM_STATE_NONE; | ||
2033 | } | ||
2034 | 1910 | ||
2035 | printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", | 1911 | printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", |
2036 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); | 1912 | ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
2037 | 1913 | ||
2038 | return retval; | 1914 | return status; |
2039 | } | 1915 | } |
2040 | 1916 | ||
2041 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
2042 | /** | ||
2043 | * mptscsih_tm_pending_wait - wait for pending task management request to complete | ||
2044 | * @hd: Pointer to MPT host structure. | ||
2045 | * | ||
2046 | * Returns {SUCCESS,FAILED}. | ||
2047 | */ | ||
2048 | static int | 1917 | static int |
2049 | mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) | 1918 | mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, |
1919 | SCSITaskMgmtReply_t *pScsiTmReply) | ||
2050 | { | 1920 | { |
2051 | unsigned long flags; | 1921 | u16 iocstatus; |
2052 | int loop_count = 4 * 10; /* Wait 10 seconds */ | 1922 | u32 termination_count; |
2053 | int status = FAILED; | 1923 | int retval; |
2054 | MPT_ADAPTER *ioc = hd->ioc; | ||
2055 | 1924 | ||
2056 | do { | 1925 | if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { |
2057 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1926 | retval = FAILED; |
2058 | if (hd->tmState == TM_STATE_NONE) { | 1927 | goto out; |
2059 | hd->tmState = TM_STATE_IN_PROGRESS; | 1928 | } |
2060 | hd->tmPending = 1; | ||
2061 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2062 | status = SUCCESS; | ||
2063 | break; | ||
2064 | } | ||
2065 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2066 | msleep(250); | ||
2067 | } while (--loop_count); | ||
2068 | 1929 | ||
2069 | return status; | 1930 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); |
2070 | } | ||
2071 | 1931 | ||
2072 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1932 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; |
2073 | /** | 1933 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); |
2074 | * mptscsih_tm_wait_for_completion - wait for completion of TM task | ||
2075 | * @hd: Pointer to MPT host structure. | ||
2076 | * @timeout: timeout value | ||
2077 | * | ||
2078 | * Returns {SUCCESS,FAILED}. | ||
2079 | */ | ||
2080 | static int | ||
2081 | mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) | ||
2082 | { | ||
2083 | unsigned long flags; | ||
2084 | int loop_count = 4 * timeout; | ||
2085 | int status = FAILED; | ||
2086 | MPT_ADAPTER *ioc = hd->ioc; | ||
2087 | 1934 | ||
2088 | do { | 1935 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2089 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1936 | "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n" |
2090 | if(hd->tmPending == 0) { | 1937 | "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n" |
2091 | status = SUCCESS; | 1938 | "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus, |
2092 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 1939 | pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus), |
2093 | break; | 1940 | le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, |
2094 | } | 1941 | termination_count)); |
2095 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2096 | msleep(250); | ||
2097 | } while (--loop_count); | ||
2098 | 1942 | ||
2099 | return status; | 1943 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && |
1944 | pScsiTmReply->ResponseCode) | ||
1945 | mptscsih_taskmgmt_response_code(ioc, | ||
1946 | pScsiTmReply->ResponseCode); | ||
1947 | |||
1948 | if (iocstatus == MPI_IOCSTATUS_SUCCESS) { | ||
1949 | retval = 0; | ||
1950 | goto out; | ||
1951 | } | ||
1952 | |||
1953 | retval = FAILED; | ||
1954 | if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { | ||
1955 | if (termination_count == 1) | ||
1956 | retval = 0; | ||
1957 | goto out; | ||
1958 | } | ||
1959 | |||
1960 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
1961 | iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
1962 | retval = 0; | ||
1963 | |||
1964 | out: | ||
1965 | return retval; | ||
2100 | } | 1966 | } |
2101 | 1967 | ||
2102 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1968 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2103 | static void | 1969 | void |
2104 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | 1970 | mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) |
2105 | { | 1971 | { |
2106 | char *desc; | 1972 | char *desc; |
@@ -2134,6 +2000,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
2134 | printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", | 2000 | printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", |
2135 | ioc->name, response_code, desc); | 2001 | ioc->name, response_code, desc); |
2136 | } | 2002 | } |
2003 | EXPORT_SYMBOL(mptscsih_taskmgmt_response_code); | ||
2137 | 2004 | ||
2138 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2005 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2139 | /** | 2006 | /** |
@@ -2150,97 +2017,28 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
2150 | * Returns 1 indicating alloc'd request frame ptr should be freed. | 2017 | * Returns 1 indicating alloc'd request frame ptr should be freed. |
2151 | **/ | 2018 | **/ |
2152 | int | 2019 | int |
2153 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2020 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, |
2021 | MPT_FRAME_HDR *mr) | ||
2154 | { | 2022 | { |
2155 | SCSITaskMgmtReply_t *pScsiTmReply; | 2023 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2156 | SCSITaskMgmt_t *pScsiTmReq; | 2024 | "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr)); |
2157 | MPT_SCSI_HOST *hd; | ||
2158 | unsigned long flags; | ||
2159 | u16 iocstatus; | ||
2160 | u8 tmType; | ||
2161 | u32 termination_count; | ||
2162 | |||
2163 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", | ||
2164 | ioc->name, mf, mr)); | ||
2165 | if (!ioc->sh) { | ||
2166 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
2167 | "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); | ||
2168 | return 1; | ||
2169 | } | ||
2170 | |||
2171 | if (mr == NULL) { | ||
2172 | dtmprintk(ioc, printk(MYIOC_s_WARN_FMT | ||
2173 | "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); | ||
2174 | return 1; | ||
2175 | } | ||
2176 | |||
2177 | hd = shost_priv(ioc->sh); | ||
2178 | pScsiTmReply = (SCSITaskMgmtReply_t*)mr; | ||
2179 | pScsiTmReq = (SCSITaskMgmt_t*)mf; | ||
2180 | tmType = pScsiTmReq->TaskType; | ||
2181 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2182 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); | ||
2183 | 2025 | ||
2184 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && | 2026 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
2185 | pScsiTmReply->ResponseCode) | ||
2186 | mptscsih_taskmgmt_response_code(ioc, | ||
2187 | pScsiTmReply->ResponseCode); | ||
2188 | DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); | ||
2189 | 2027 | ||
2190 | #ifdef CONFIG_FUSION_LOGGING | 2028 | if (!mr) |
2191 | if ((ioc->debug_level & MPT_DEBUG_REPLY) || | ||
2192 | (ioc->debug_level & MPT_DEBUG_TM )) | ||
2193 | printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " | ||
2194 | "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " | ||
2195 | "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus, | ||
2196 | pScsiTmReply->TargetID, pScsiTmReq->TaskType, | ||
2197 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
2198 | le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, | ||
2199 | le32_to_cpu(pScsiTmReply->TerminationCount)); | ||
2200 | #endif | ||
2201 | if (!iocstatus) { | ||
2202 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name)); | ||
2203 | hd->abortSCpnt = NULL; | ||
2204 | goto out; | 2029 | goto out; |
2205 | } | ||
2206 | |||
2207 | /* Error? (anything non-zero?) */ | ||
2208 | |||
2209 | /* clear flags and continue. | ||
2210 | */ | ||
2211 | switch (tmType) { | ||
2212 | |||
2213 | case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: | ||
2214 | if (termination_count == 1) | ||
2215 | iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; | ||
2216 | hd->abortSCpnt = NULL; | ||
2217 | break; | ||
2218 | |||
2219 | case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: | ||
2220 | |||
2221 | /* If an internal command is present | ||
2222 | * or the TM failed - reload the FW. | ||
2223 | * FC FW may respond FAILED to an ABORT | ||
2224 | */ | ||
2225 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || | ||
2226 | hd->cmdPtr) | ||
2227 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) | ||
2228 | printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); | ||
2229 | break; | ||
2230 | |||
2231 | case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: | ||
2232 | default: | ||
2233 | break; | ||
2234 | } | ||
2235 | 2030 | ||
2031 | ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
2032 | memcpy(ioc->taskmgmt_cmds.reply, mr, | ||
2033 | min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); | ||
2236 | out: | 2034 | out: |
2237 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 2035 | if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { |
2238 | hd->tmPending = 0; | 2036 | mpt_clear_taskmgmt_in_progress_flag(ioc); |
2239 | hd->tmState = TM_STATE_NONE; | 2037 | ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
2240 | hd->tm_iocstatus = iocstatus; | 2038 | complete(&ioc->taskmgmt_cmds.done); |
2241 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 2039 | return 1; |
2242 | 2040 | } | |
2243 | return 1; | 2041 | return 0; |
2244 | } | 2042 | } |
2245 | 2043 | ||
2246 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2044 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2290,8 +2088,10 @@ int | |||
2290 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2088 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2291 | { | 2089 | { |
2292 | struct inactive_raid_component_info *component_info; | 2090 | struct inactive_raid_component_info *component_info; |
2293 | int i; | 2091 | int i, j; |
2092 | RaidPhysDiskPage1_t *phys_disk; | ||
2294 | int rc = 0; | 2093 | int rc = 0; |
2094 | int num_paths; | ||
2295 | 2095 | ||
2296 | if (!ioc->raid_data.pIocPg3) | 2096 | if (!ioc->raid_data.pIocPg3) |
2297 | goto out; | 2097 | goto out; |
@@ -2303,6 +2103,45 @@ mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
2303 | } | 2103 | } |
2304 | } | 2104 | } |
2305 | 2105 | ||
2106 | if (ioc->bus_type != SAS) | ||
2107 | goto out; | ||
2108 | |||
2109 | /* | ||
2110 | * Check if dual path | ||
2111 | */ | ||
2112 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2113 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
2114 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
2115 | if (num_paths < 2) | ||
2116 | continue; | ||
2117 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
2118 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
2119 | if (!phys_disk) | ||
2120 | continue; | ||
2121 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
2122 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
2123 | phys_disk))) { | ||
2124 | kfree(phys_disk); | ||
2125 | continue; | ||
2126 | } | ||
2127 | for (j = 0; j < num_paths; j++) { | ||
2128 | if ((phys_disk->Path[j].Flags & | ||
2129 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
2130 | continue; | ||
2131 | if ((phys_disk->Path[j].Flags & | ||
2132 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
2133 | continue; | ||
2134 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
2135 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
2136 | rc = 1; | ||
2137 | kfree(phys_disk); | ||
2138 | goto out; | ||
2139 | } | ||
2140 | } | ||
2141 | kfree(phys_disk); | ||
2142 | } | ||
2143 | |||
2144 | |||
2306 | /* | 2145 | /* |
2307 | * Check inactive list for matching phys disks | 2146 | * Check inactive list for matching phys disks |
2308 | */ | 2147 | */ |
@@ -2327,8 +2166,10 @@ u8 | |||
2327 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | 2166 | mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) |
2328 | { | 2167 | { |
2329 | struct inactive_raid_component_info *component_info; | 2168 | struct inactive_raid_component_info *component_info; |
2330 | int i; | 2169 | int i, j; |
2170 | RaidPhysDiskPage1_t *phys_disk; | ||
2331 | int rc = -ENXIO; | 2171 | int rc = -ENXIO; |
2172 | int num_paths; | ||
2332 | 2173 | ||
2333 | if (!ioc->raid_data.pIocPg3) | 2174 | if (!ioc->raid_data.pIocPg3) |
2334 | goto out; | 2175 | goto out; |
@@ -2340,6 +2181,44 @@ mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) | |||
2340 | } | 2181 | } |
2341 | } | 2182 | } |
2342 | 2183 | ||
2184 | if (ioc->bus_type != SAS) | ||
2185 | goto out; | ||
2186 | |||
2187 | /* | ||
2188 | * Check if dual path | ||
2189 | */ | ||
2190 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { | ||
2191 | num_paths = mpt_raid_phys_disk_get_num_paths(ioc, | ||
2192 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); | ||
2193 | if (num_paths < 2) | ||
2194 | continue; | ||
2195 | phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + | ||
2196 | (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); | ||
2197 | if (!phys_disk) | ||
2198 | continue; | ||
2199 | if ((mpt_raid_phys_disk_pg1(ioc, | ||
2200 | ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, | ||
2201 | phys_disk))) { | ||
2202 | kfree(phys_disk); | ||
2203 | continue; | ||
2204 | } | ||
2205 | for (j = 0; j < num_paths; j++) { | ||
2206 | if ((phys_disk->Path[j].Flags & | ||
2207 | MPI_RAID_PHYSDISK1_FLAG_INVALID)) | ||
2208 | continue; | ||
2209 | if ((phys_disk->Path[j].Flags & | ||
2210 | MPI_RAID_PHYSDISK1_FLAG_BROKEN)) | ||
2211 | continue; | ||
2212 | if ((id == phys_disk->Path[j].PhysDiskID) && | ||
2213 | (channel == phys_disk->Path[j].PhysDiskBus)) { | ||
2214 | rc = phys_disk->PhysDiskNum; | ||
2215 | kfree(phys_disk); | ||
2216 | goto out; | ||
2217 | } | ||
2218 | } | ||
2219 | kfree(phys_disk); | ||
2220 | } | ||
2221 | |||
2343 | /* | 2222 | /* |
2344 | * Check inactive list for matching phys disks | 2223 | * Check inactive list for matching phys disks |
2345 | */ | 2224 | */ |
@@ -2457,7 +2336,6 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
2457 | sdev->ppr, sdev->inquiry_len)); | 2336 | sdev->ppr, sdev->inquiry_len)); |
2458 | 2337 | ||
2459 | vdevice->configured_lun = 1; | 2338 | vdevice->configured_lun = 1; |
2460 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | ||
2461 | 2339 | ||
2462 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2340 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2463 | "Queue depth=%d, tflags=%x\n", | 2341 | "Queue depth=%d, tflags=%x\n", |
@@ -2469,6 +2347,7 @@ mptscsih_slave_configure(struct scsi_device *sdev) | |||
2469 | ioc->name, vtarget->negoFlags, vtarget->maxOffset, | 2347 | ioc->name, vtarget->negoFlags, vtarget->maxOffset, |
2470 | vtarget->minSyncFactor)); | 2348 | vtarget->minSyncFactor)); |
2471 | 2349 | ||
2350 | mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); | ||
2472 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT | 2351 | dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2473 | "tagged %d, simple %d, ordered %d\n", | 2352 | "tagged %d, simple %d, ordered %d\n", |
2474 | ioc->name,sdev->tagged_supported, sdev->simple_tags, | 2353 | ioc->name,sdev->tagged_supported, sdev->simple_tags, |
@@ -2542,15 +2421,13 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR | |||
2542 | } | 2421 | } |
2543 | 2422 | ||
2544 | /** | 2423 | /** |
2545 | * mptscsih_get_scsi_lookup | 2424 | * mptscsih_get_scsi_lookup - retrieves scmd entry |
2546 | * @ioc: Pointer to MPT_ADAPTER structure | 2425 | * @ioc: Pointer to MPT_ADAPTER structure |
2547 | * @i: index into the array | 2426 | * @i: index into the array |
2548 | * | 2427 | * |
2549 | * retrieves scmd entry from ScsiLookup[] array list | ||
2550 | * | ||
2551 | * Returns the scsi_cmd pointer | 2428 | * Returns the scsi_cmd pointer |
2552 | **/ | 2429 | */ |
2553 | static struct scsi_cmnd * | 2430 | struct scsi_cmnd * |
2554 | mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) | 2431 | mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) |
2555 | { | 2432 | { |
2556 | unsigned long flags; | 2433 | unsigned long flags; |
@@ -2562,15 +2439,15 @@ mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) | |||
2562 | 2439 | ||
2563 | return scmd; | 2440 | return scmd; |
2564 | } | 2441 | } |
2442 | EXPORT_SYMBOL(mptscsih_get_scsi_lookup); | ||
2565 | 2443 | ||
2566 | /** | 2444 | /** |
2567 | * mptscsih_getclear_scsi_lookup | 2445 | * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list |
2568 | * @ioc: Pointer to MPT_ADAPTER structure | 2446 | * @ioc: Pointer to MPT_ADAPTER structure |
2569 | * @i: index into the array | 2447 | * @i: index into the array |
2570 | * | 2448 | * |
2571 | * retrieves and clears scmd entry from ScsiLookup[] array list | ||
2572 | * | ||
2573 | * Returns the scsi_cmd pointer | 2449 | * Returns the scsi_cmd pointer |
2450 | * | ||
2574 | **/ | 2451 | **/ |
2575 | static struct scsi_cmnd * | 2452 | static struct scsi_cmnd * |
2576 | mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) | 2453 | mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) |
@@ -2635,94 +2512,33 @@ int | |||
2635 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 2512 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
2636 | { | 2513 | { |
2637 | MPT_SCSI_HOST *hd; | 2514 | MPT_SCSI_HOST *hd; |
2638 | unsigned long flags; | ||
2639 | 2515 | ||
2640 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2641 | ": IOC %s_reset routed to SCSI host driver!\n", | ||
2642 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | ||
2643 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | ||
2644 | |||
2645 | /* If a FW reload request arrives after base installed but | ||
2646 | * before all scsi hosts have been attached, then an alt_ioc | ||
2647 | * may have a NULL sh pointer. | ||
2648 | */ | ||
2649 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) | 2516 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) |
2650 | return 0; | 2517 | return 0; |
2651 | else | ||
2652 | hd = shost_priv(ioc->sh); | ||
2653 | |||
2654 | if (reset_phase == MPT_IOC_SETUP_RESET) { | ||
2655 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); | ||
2656 | |||
2657 | /* Clean Up: | ||
2658 | * 1. Set Hard Reset Pending Flag | ||
2659 | * All new commands go to doneQ | ||
2660 | */ | ||
2661 | hd->resetPending = 1; | ||
2662 | |||
2663 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | ||
2664 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name)); | ||
2665 | 2518 | ||
2666 | /* 2. Flush running commands | 2519 | hd = shost_priv(ioc->sh); |
2667 | * Clean ScsiLookup (and associated memory) | 2520 | switch (reset_phase) { |
2668 | * AND clean mytaskQ | 2521 | case MPT_IOC_SETUP_RESET: |
2669 | */ | 2522 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2670 | 2523 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); | |
2671 | /* 2b. Reply to OS all known outstanding I/O commands. | 2524 | break; |
2672 | */ | 2525 | case MPT_IOC_PRE_RESET: |
2526 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2527 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | ||
2673 | mptscsih_flush_running_cmds(hd); | 2528 | mptscsih_flush_running_cmds(hd); |
2674 | 2529 | break; | |
2675 | /* 2c. If there was an internal command that | 2530 | case MPT_IOC_POST_RESET: |
2676 | * has not completed, configuration or io request, | 2531 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2677 | * free these resources. | 2532 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
2678 | */ | 2533 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) { |
2679 | if (hd->cmdPtr) { | 2534 | ioc->internal_cmds.status |= |
2680 | del_timer(&hd->timer); | 2535 | MPT_MGMT_STATUS_DID_IOCRESET; |
2681 | mpt_free_msg_frame(ioc, hd->cmdPtr); | 2536 | complete(&ioc->internal_cmds.done); |
2682 | } | ||
2683 | |||
2684 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name)); | ||
2685 | |||
2686 | } else { | ||
2687 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name)); | ||
2688 | |||
2689 | /* Once a FW reload begins, all new OS commands are | ||
2690 | * redirected to the doneQ w/ a reset status. | ||
2691 | * Init all control structures. | ||
2692 | */ | ||
2693 | |||
2694 | /* 2. Chain Buffer initialization | ||
2695 | */ | ||
2696 | |||
2697 | /* 4. Renegotiate to all devices, if SPI | ||
2698 | */ | ||
2699 | |||
2700 | /* 5. Enable new commands to be posted | ||
2701 | */ | ||
2702 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
2703 | hd->tmPending = 0; | ||
2704 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2705 | hd->resetPending = 0; | ||
2706 | hd->tmState = TM_STATE_NONE; | ||
2707 | |||
2708 | /* 6. If there was an internal command, | ||
2709 | * wake this process up. | ||
2710 | */ | ||
2711 | if (hd->cmdPtr) { | ||
2712 | /* | ||
2713 | * Wake up the original calling thread | ||
2714 | */ | ||
2715 | hd->pLocal = &hd->localReply; | ||
2716 | hd->pLocal->completion = MPT_SCANDV_DID_RESET; | ||
2717 | hd->scandv_wait_done = 1; | ||
2718 | wake_up(&hd->scandv_waitq); | ||
2719 | hd->cmdPtr = NULL; | ||
2720 | } | 2537 | } |
2721 | 2538 | break; | |
2722 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name)); | 2539 | default: |
2723 | 2540 | break; | |
2724 | } | 2541 | } |
2725 | |||
2726 | return 1; /* currently means nothing really */ | 2542 | return 1; /* currently means nothing really */ |
2727 | } | 2543 | } |
2728 | 2544 | ||
@@ -2730,55 +2546,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2730 | int | 2546 | int |
2731 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | 2547 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) |
2732 | { | 2548 | { |
2733 | MPT_SCSI_HOST *hd; | ||
2734 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | 2549 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; |
2735 | 2550 | ||
2736 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2551 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2737 | ioc->name, event)); | 2552 | "MPT event (=%02Xh) routed to SCSI host driver!\n", |
2738 | 2553 | ioc->name, event)); | |
2739 | if (ioc->sh == NULL || | ||
2740 | ((hd = shost_priv(ioc->sh)) == NULL)) | ||
2741 | return 1; | ||
2742 | |||
2743 | switch (event) { | ||
2744 | case MPI_EVENT_UNIT_ATTENTION: /* 03 */ | ||
2745 | /* FIXME! */ | ||
2746 | break; | ||
2747 | case MPI_EVENT_IOC_BUS_RESET: /* 04 */ | ||
2748 | case MPI_EVENT_EXT_BUS_RESET: /* 05 */ | ||
2749 | if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1)) | ||
2750 | hd->soft_resets++; | ||
2751 | break; | ||
2752 | case MPI_EVENT_LOGOUT: /* 09 */ | ||
2753 | /* FIXME! */ | ||
2754 | break; | ||
2755 | |||
2756 | case MPI_EVENT_RESCAN: /* 06 */ | ||
2757 | break; | ||
2758 | |||
2759 | /* | ||
2760 | * CHECKME! Don't think we need to do | ||
2761 | * anything for these, but... | ||
2762 | */ | ||
2763 | case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ | ||
2764 | case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ | ||
2765 | /* | ||
2766 | * CHECKME! Falling thru... | ||
2767 | */ | ||
2768 | break; | ||
2769 | |||
2770 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | ||
2771 | break; | ||
2772 | 2554 | ||
2773 | case MPI_EVENT_NONE: /* 00 */ | 2555 | if ((event == MPI_EVENT_IOC_BUS_RESET || |
2774 | case MPI_EVENT_LOG_DATA: /* 01 */ | 2556 | event == MPI_EVENT_EXT_BUS_RESET) && |
2775 | case MPI_EVENT_STATE_CHANGE: /* 02 */ | 2557 | (ioc->bus_type == SPI) && (ioc->soft_resets < -1)) |
2776 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ | 2558 | ioc->soft_resets++; |
2777 | default: | ||
2778 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n", | ||
2779 | ioc->name, event)); | ||
2780 | break; | ||
2781 | } | ||
2782 | 2559 | ||
2783 | return 1; /* currently means nothing really */ | 2560 | return 1; /* currently means nothing really */ |
2784 | } | 2561 | } |
@@ -2809,153 +2586,44 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2809 | * Used ONLY for DV and other internal commands. | 2586 | * Used ONLY for DV and other internal commands. |
2810 | */ | 2587 | */ |
2811 | int | 2588 | int |
2812 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2589 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
2590 | MPT_FRAME_HDR *reply) | ||
2813 | { | 2591 | { |
2814 | MPT_SCSI_HOST *hd; | ||
2815 | SCSIIORequest_t *pReq; | 2592 | SCSIIORequest_t *pReq; |
2816 | int completionCode; | 2593 | SCSIIOReply_t *pReply; |
2594 | u8 cmd; | ||
2817 | u16 req_idx; | 2595 | u16 req_idx; |
2596 | u8 *sense_data; | ||
2597 | int sz; | ||
2818 | 2598 | ||
2819 | hd = shost_priv(ioc->sh); | 2599 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
2820 | 2600 | ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD; | |
2821 | if ((mf == NULL) || | 2601 | if (!reply) |
2822 | (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { | 2602 | goto out; |
2823 | printk(MYIOC_s_ERR_FMT | ||
2824 | "ScanDvComplete, %s req frame ptr! (=%p)\n", | ||
2825 | ioc->name, mf?"BAD":"NULL", (void *) mf); | ||
2826 | goto wakeup; | ||
2827 | } | ||
2828 | |||
2829 | del_timer(&hd->timer); | ||
2830 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
2831 | mptscsih_set_scsi_lookup(ioc, req_idx, NULL); | ||
2832 | pReq = (SCSIIORequest_t *) mf; | ||
2833 | 2603 | ||
2834 | if (mf != hd->cmdPtr) { | 2604 | pReply = (SCSIIOReply_t *) reply; |
2835 | printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", | 2605 | pReq = (SCSIIORequest_t *) req; |
2836 | ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); | 2606 | ioc->internal_cmds.completion_code = |
2607 | mptscsih_get_completion_code(ioc, req, reply); | ||
2608 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
2609 | memcpy(ioc->internal_cmds.reply, reply, | ||
2610 | min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength)); | ||
2611 | cmd = reply->u.hdr.Function; | ||
2612 | if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
2613 | (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) && | ||
2614 | (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) { | ||
2615 | req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
2616 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
2617 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
2618 | sz = min_t(int, pReq->SenseBufferLength, | ||
2619 | MPT_SENSE_BUFFER_ALLOC); | ||
2620 | memcpy(ioc->internal_cmds.sense, sense_data, sz); | ||
2837 | } | 2621 | } |
2838 | hd->cmdPtr = NULL; | 2622 | out: |
2839 | 2623 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING)) | |
2840 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", | 2624 | return 0; |
2841 | ioc->name, mf, mr, req_idx)); | 2625 | ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
2842 | 2626 | complete(&ioc->internal_cmds.done); | |
2843 | hd->pLocal = &hd->localReply; | ||
2844 | hd->pLocal->scsiStatus = 0; | ||
2845 | |||
2846 | /* If target struct exists, clear sense valid flag. | ||
2847 | */ | ||
2848 | if (mr == NULL) { | ||
2849 | completionCode = MPT_SCANDV_GOOD; | ||
2850 | } else { | ||
2851 | SCSIIOReply_t *pReply; | ||
2852 | u16 status; | ||
2853 | u8 scsi_status; | ||
2854 | |||
2855 | pReply = (SCSIIOReply_t *) mr; | ||
2856 | |||
2857 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2858 | scsi_status = pReply->SCSIStatus; | ||
2859 | |||
2860 | |||
2861 | switch(status) { | ||
2862 | |||
2863 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
2864 | completionCode = MPT_SCANDV_SELECTION_TIMEOUT; | ||
2865 | break; | ||
2866 | |||
2867 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
2868 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
2869 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
2870 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
2871 | completionCode = MPT_SCANDV_DID_RESET; | ||
2872 | break; | ||
2873 | |||
2874 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
2875 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
2876 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
2877 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
2878 | ConfigReply_t *pr = (ConfigReply_t *)mr; | ||
2879 | completionCode = MPT_SCANDV_GOOD; | ||
2880 | hd->pLocal->header.PageVersion = pr->Header.PageVersion; | ||
2881 | hd->pLocal->header.PageLength = pr->Header.PageLength; | ||
2882 | hd->pLocal->header.PageNumber = pr->Header.PageNumber; | ||
2883 | hd->pLocal->header.PageType = pr->Header.PageType; | ||
2884 | |||
2885 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
2886 | /* If the RAID Volume request is successful, | ||
2887 | * return GOOD, else indicate that | ||
2888 | * some type of error occurred. | ||
2889 | */ | ||
2890 | MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr; | ||
2891 | if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
2892 | completionCode = MPT_SCANDV_GOOD; | ||
2893 | else | ||
2894 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2895 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
2896 | |||
2897 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | ||
2898 | u8 *sense_data; | ||
2899 | int sz; | ||
2900 | |||
2901 | /* save sense data in global structure | ||
2902 | */ | ||
2903 | completionCode = MPT_SCANDV_SENSE; | ||
2904 | hd->pLocal->scsiStatus = scsi_status; | ||
2905 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
2906 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
2907 | |||
2908 | sz = min_t(int, pReq->SenseBufferLength, | ||
2909 | SCSI_STD_SENSE_BYTES); | ||
2910 | memcpy(hd->pLocal->sense, sense_data, sz); | ||
2911 | |||
2912 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n", | ||
2913 | ioc->name, sense_data)); | ||
2914 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
2915 | if (pReq->CDB[0] == INQUIRY) | ||
2916 | completionCode = MPT_SCANDV_ISSUE_SENSE; | ||
2917 | else | ||
2918 | completionCode = MPT_SCANDV_DID_RESET; | ||
2919 | } | ||
2920 | else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
2921 | completionCode = MPT_SCANDV_DID_RESET; | ||
2922 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2923 | completionCode = MPT_SCANDV_DID_RESET; | ||
2924 | else { | ||
2925 | completionCode = MPT_SCANDV_GOOD; | ||
2926 | hd->pLocal->scsiStatus = scsi_status; | ||
2927 | } | ||
2928 | break; | ||
2929 | |||
2930 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
2931 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2932 | completionCode = MPT_SCANDV_DID_RESET; | ||
2933 | else | ||
2934 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2935 | break; | ||
2936 | |||
2937 | default: | ||
2938 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2939 | break; | ||
2940 | |||
2941 | } /* switch(status) */ | ||
2942 | |||
2943 | } /* end of address reply case */ | ||
2944 | |||
2945 | hd->pLocal->completion = completionCode; | ||
2946 | |||
2947 | /* MF and RF are freed in mpt_interrupt | ||
2948 | */ | ||
2949 | wakeup: | ||
2950 | /* Free Chain buffers (will never chain) in scan or dv */ | ||
2951 | //mptscsih_freeChainBuffers(ioc, req_idx); | ||
2952 | |||
2953 | /* | ||
2954 | * Wake up the original calling thread | ||
2955 | */ | ||
2956 | hd->scandv_wait_done = 1; | ||
2957 | wake_up(&hd->scandv_waitq); | ||
2958 | |||
2959 | return 1; | 2627 | return 1; |
2960 | } | 2628 | } |
2961 | 2629 | ||
@@ -3004,6 +2672,95 @@ mptscsih_timer_expired(unsigned long data) | |||
3004 | return; | 2672 | return; |
3005 | } | 2673 | } |
3006 | 2674 | ||
2675 | /** | ||
2676 | * mptscsih_get_completion_code - | ||
2677 | * @ioc: Pointer to MPT_ADAPTER structure | ||
2678 | * @req: Pointer to original MPT request frame | ||
2679 | * @reply: Pointer to MPT reply frame (NULL if TurboReply) | ||
2680 | * | ||
2681 | **/ | ||
2682 | static int | ||
2683 | mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, | ||
2684 | MPT_FRAME_HDR *reply) | ||
2685 | { | ||
2686 | SCSIIOReply_t *pReply; | ||
2687 | MpiRaidActionReply_t *pr; | ||
2688 | u8 scsi_status; | ||
2689 | u16 status; | ||
2690 | int completion_code; | ||
2691 | |||
2692 | pReply = (SCSIIOReply_t *)reply; | ||
2693 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2694 | scsi_status = pReply->SCSIStatus; | ||
2695 | |||
2696 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2697 | "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh," | ||
2698 | "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState, | ||
2699 | scsi_status, le32_to_cpu(pReply->IOCLogInfo))); | ||
2700 | |||
2701 | switch (status) { | ||
2702 | |||
2703 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
2704 | completion_code = MPT_SCANDV_SELECTION_TIMEOUT; | ||
2705 | break; | ||
2706 | |||
2707 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
2708 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
2709 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
2710 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
2711 | completion_code = MPT_SCANDV_DID_RESET; | ||
2712 | break; | ||
2713 | |||
2714 | case MPI_IOCSTATUS_BUSY: | ||
2715 | case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: | ||
2716 | completion_code = MPT_SCANDV_BUSY; | ||
2717 | break; | ||
2718 | |||
2719 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
2720 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
2721 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
2722 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
2723 | completion_code = MPT_SCANDV_GOOD; | ||
2724 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
2725 | pr = (MpiRaidActionReply_t *)reply; | ||
2726 | if (le16_to_cpu(pr->ActionStatus) == | ||
2727 | MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
2728 | completion_code = MPT_SCANDV_GOOD; | ||
2729 | else | ||
2730 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2731 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) | ||
2732 | completion_code = MPT_SCANDV_SENSE; | ||
2733 | else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
2734 | if (req->u.scsireq.CDB[0] == INQUIRY) | ||
2735 | completion_code = MPT_SCANDV_ISSUE_SENSE; | ||
2736 | else | ||
2737 | completion_code = MPT_SCANDV_DID_RESET; | ||
2738 | } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
2739 | completion_code = MPT_SCANDV_DID_RESET; | ||
2740 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2741 | completion_code = MPT_SCANDV_DID_RESET; | ||
2742 | else if (scsi_status == MPI_SCSI_STATUS_BUSY) | ||
2743 | completion_code = MPT_SCANDV_BUSY; | ||
2744 | else | ||
2745 | completion_code = MPT_SCANDV_GOOD; | ||
2746 | break; | ||
2747 | |||
2748 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
2749 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2750 | completion_code = MPT_SCANDV_DID_RESET; | ||
2751 | else | ||
2752 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2753 | break; | ||
2754 | default: | ||
2755 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2756 | break; | ||
2757 | |||
2758 | } /* switch(status) */ | ||
2759 | |||
2760 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2761 | " completionCode set to %08xh\n", ioc->name, completion_code)); | ||
2762 | return completion_code; | ||
2763 | } | ||
3007 | 2764 | ||
3008 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2765 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3009 | /** | 2766 | /** |
@@ -3030,22 +2787,27 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3030 | { | 2787 | { |
3031 | MPT_FRAME_HDR *mf; | 2788 | MPT_FRAME_HDR *mf; |
3032 | SCSIIORequest_t *pScsiReq; | 2789 | SCSIIORequest_t *pScsiReq; |
3033 | SCSIIORequest_t ReqCopy; | ||
3034 | int my_idx, ii, dir; | 2790 | int my_idx, ii, dir; |
3035 | int rc, cmdTimeout; | 2791 | int timeout; |
3036 | int in_isr; | ||
3037 | char cmdLen; | 2792 | char cmdLen; |
3038 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 2793 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
3039 | char cmd = io->cmd; | 2794 | u8 cmd = io->cmd; |
3040 | MPT_ADAPTER *ioc = hd->ioc; | 2795 | MPT_ADAPTER *ioc = hd->ioc; |
2796 | int ret = 0; | ||
2797 | unsigned long timeleft; | ||
2798 | unsigned long flags; | ||
3041 | 2799 | ||
3042 | in_isr = in_interrupt(); | 2800 | /* don't send internal command during diag reset */ |
3043 | if (in_isr) { | 2801 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); |
3044 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", | 2802 | if (ioc->ioc_reset_in_progress) { |
3045 | ioc->name)); | 2803 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); |
3046 | return -EPERM; | 2804 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2805 | "%s: busy with host reset\n", ioc->name, __func__)); | ||
2806 | return MPT_SCANDV_BUSY; | ||
3047 | } | 2807 | } |
2808 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
3048 | 2809 | ||
2810 | mutex_lock(&ioc->internal_cmds.mutex); | ||
3049 | 2811 | ||
3050 | /* Set command specific information | 2812 | /* Set command specific information |
3051 | */ | 2813 | */ |
@@ -3055,13 +2817,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3055 | dir = MPI_SCSIIO_CONTROL_READ; | 2817 | dir = MPI_SCSIIO_CONTROL_READ; |
3056 | CDB[0] = cmd; | 2818 | CDB[0] = cmd; |
3057 | CDB[4] = io->size; | 2819 | CDB[4] = io->size; |
3058 | cmdTimeout = 10; | 2820 | timeout = 10; |
3059 | break; | 2821 | break; |
3060 | 2822 | ||
3061 | case TEST_UNIT_READY: | 2823 | case TEST_UNIT_READY: |
3062 | cmdLen = 6; | 2824 | cmdLen = 6; |
3063 | dir = MPI_SCSIIO_CONTROL_READ; | 2825 | dir = MPI_SCSIIO_CONTROL_READ; |
3064 | cmdTimeout = 10; | 2826 | timeout = 10; |
3065 | break; | 2827 | break; |
3066 | 2828 | ||
3067 | case START_STOP: | 2829 | case START_STOP: |
@@ -3069,7 +2831,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3069 | dir = MPI_SCSIIO_CONTROL_READ; | 2831 | dir = MPI_SCSIIO_CONTROL_READ; |
3070 | CDB[0] = cmd; | 2832 | CDB[0] = cmd; |
3071 | CDB[4] = 1; /*Spin up the disk */ | 2833 | CDB[4] = 1; /*Spin up the disk */ |
3072 | cmdTimeout = 15; | 2834 | timeout = 15; |
3073 | break; | 2835 | break; |
3074 | 2836 | ||
3075 | case REQUEST_SENSE: | 2837 | case REQUEST_SENSE: |
@@ -3077,7 +2839,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3077 | CDB[0] = cmd; | 2839 | CDB[0] = cmd; |
3078 | CDB[4] = io->size; | 2840 | CDB[4] = io->size; |
3079 | dir = MPI_SCSIIO_CONTROL_READ; | 2841 | dir = MPI_SCSIIO_CONTROL_READ; |
3080 | cmdTimeout = 10; | 2842 | timeout = 10; |
3081 | break; | 2843 | break; |
3082 | 2844 | ||
3083 | case READ_BUFFER: | 2845 | case READ_BUFFER: |
@@ -3096,7 +2858,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3096 | CDB[6] = (io->size >> 16) & 0xFF; | 2858 | CDB[6] = (io->size >> 16) & 0xFF; |
3097 | CDB[7] = (io->size >> 8) & 0xFF; | 2859 | CDB[7] = (io->size >> 8) & 0xFF; |
3098 | CDB[8] = io->size & 0xFF; | 2860 | CDB[8] = io->size & 0xFF; |
3099 | cmdTimeout = 10; | 2861 | timeout = 10; |
3100 | break; | 2862 | break; |
3101 | 2863 | ||
3102 | case WRITE_BUFFER: | 2864 | case WRITE_BUFFER: |
@@ -3111,21 +2873,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3111 | CDB[6] = (io->size >> 16) & 0xFF; | 2873 | CDB[6] = (io->size >> 16) & 0xFF; |
3112 | CDB[7] = (io->size >> 8) & 0xFF; | 2874 | CDB[7] = (io->size >> 8) & 0xFF; |
3113 | CDB[8] = io->size & 0xFF; | 2875 | CDB[8] = io->size & 0xFF; |
3114 | cmdTimeout = 10; | 2876 | timeout = 10; |
3115 | break; | 2877 | break; |
3116 | 2878 | ||
3117 | case RESERVE: | 2879 | case RESERVE: |
3118 | cmdLen = 6; | 2880 | cmdLen = 6; |
3119 | dir = MPI_SCSIIO_CONTROL_READ; | 2881 | dir = MPI_SCSIIO_CONTROL_READ; |
3120 | CDB[0] = cmd; | 2882 | CDB[0] = cmd; |
3121 | cmdTimeout = 10; | 2883 | timeout = 10; |
3122 | break; | 2884 | break; |
3123 | 2885 | ||
3124 | case RELEASE: | 2886 | case RELEASE: |
3125 | cmdLen = 6; | 2887 | cmdLen = 6; |
3126 | dir = MPI_SCSIIO_CONTROL_READ; | 2888 | dir = MPI_SCSIIO_CONTROL_READ; |
3127 | CDB[0] = cmd; | 2889 | CDB[0] = cmd; |
3128 | cmdTimeout = 10; | 2890 | timeout = 10; |
3129 | break; | 2891 | break; |
3130 | 2892 | ||
3131 | case SYNCHRONIZE_CACHE: | 2893 | case SYNCHRONIZE_CACHE: |
@@ -3133,20 +2895,23 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3133 | dir = MPI_SCSIIO_CONTROL_READ; | 2895 | dir = MPI_SCSIIO_CONTROL_READ; |
3134 | CDB[0] = cmd; | 2896 | CDB[0] = cmd; |
3135 | // CDB[1] = 0x02; /* set immediate bit */ | 2897 | // CDB[1] = 0x02; /* set immediate bit */ |
3136 | cmdTimeout = 10; | 2898 | timeout = 10; |
3137 | break; | 2899 | break; |
3138 | 2900 | ||
3139 | default: | 2901 | default: |
3140 | /* Error Case */ | 2902 | /* Error Case */ |
3141 | return -EFAULT; | 2903 | ret = -EFAULT; |
2904 | goto out; | ||
3142 | } | 2905 | } |
3143 | 2906 | ||
3144 | /* Get and Populate a free Frame | 2907 | /* Get and Populate a free Frame |
2908 | * MsgContext set in mpt_get_msg_frame call | ||
3145 | */ | 2909 | */ |
3146 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { | 2910 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { |
3147 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n", | 2911 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n", |
3148 | ioc->name)); | 2912 | ioc->name, __func__)); |
3149 | return -EBUSY; | 2913 | ret = MPT_SCANDV_BUSY; |
2914 | goto out; | ||
3150 | } | 2915 | } |
3151 | 2916 | ||
3152 | pScsiReq = (SCSIIORequest_t *) mf; | 2917 | pScsiReq = (SCSIIORequest_t *) mf; |
@@ -3172,7 +2937,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3172 | 2937 | ||
3173 | pScsiReq->Reserved = 0; | 2938 | pScsiReq->Reserved = 0; |
3174 | 2939 | ||
3175 | pScsiReq->MsgFlags = mpt_msg_flags(); | 2940 | pScsiReq->MsgFlags = mpt_msg_flags(ioc); |
3176 | /* MsgContext set in mpt_get_msg_fram call */ | 2941 | /* MsgContext set in mpt_get_msg_fram call */ |
3177 | 2942 | ||
3178 | int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); | 2943 | int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); |
@@ -3184,74 +2949,58 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3184 | 2949 | ||
3185 | if (cmd == REQUEST_SENSE) { | 2950 | if (cmd == REQUEST_SENSE) { |
3186 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); | 2951 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); |
3187 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", | 2952 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3188 | ioc->name, cmd)); | 2953 | "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd)); |
3189 | } | 2954 | } |
3190 | 2955 | ||
3191 | for (ii=0; ii < 16; ii++) | 2956 | for (ii = 0; ii < 16; ii++) |
3192 | pScsiReq->CDB[ii] = CDB[ii]; | 2957 | pScsiReq->CDB[ii] = CDB[ii]; |
3193 | 2958 | ||
3194 | pScsiReq->DataLength = cpu_to_le32(io->size); | 2959 | pScsiReq->DataLength = cpu_to_le32(io->size); |
3195 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma | 2960 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma |
3196 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); | 2961 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); |
3197 | 2962 | ||
3198 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", | 2963 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3199 | ioc->name, cmd, io->channel, io->id, io->lun)); | 2964 | "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n", |
2965 | ioc->name, __func__, cmd, io->channel, io->id, io->lun)); | ||
3200 | 2966 | ||
3201 | if (dir == MPI_SCSIIO_CONTROL_READ) { | 2967 | if (dir == MPI_SCSIIO_CONTROL_READ) |
3202 | mpt_add_sge((char *) &pScsiReq->SGL, | 2968 | ioc->add_sge((char *) &pScsiReq->SGL, |
3203 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, | 2969 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma); |
3204 | io->data_dma); | 2970 | else |
3205 | } else { | 2971 | ioc->add_sge((char *) &pScsiReq->SGL, |
3206 | mpt_add_sge((char *) &pScsiReq->SGL, | 2972 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma); |
3207 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, | ||
3208 | io->data_dma); | ||
3209 | } | ||
3210 | |||
3211 | /* The ISR will free the request frame, but we need | ||
3212 | * the information to initialize the target. Duplicate. | ||
3213 | */ | ||
3214 | memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t)); | ||
3215 | |||
3216 | /* Issue this command after: | ||
3217 | * finish init | ||
3218 | * add timer | ||
3219 | * Wait until the reply has been received | ||
3220 | * ScsiScanDvCtx callback function will | ||
3221 | * set hd->pLocal; | ||
3222 | * set scandv_wait_done and call wake_up | ||
3223 | */ | ||
3224 | hd->pLocal = NULL; | ||
3225 | hd->timer.expires = jiffies + HZ*cmdTimeout; | ||
3226 | hd->scandv_wait_done = 0; | ||
3227 | |||
3228 | /* Save cmd pointer, for resource free if timeout or | ||
3229 | * FW reload occurs | ||
3230 | */ | ||
3231 | hd->cmdPtr = mf; | ||
3232 | 2973 | ||
3233 | add_timer(&hd->timer); | 2974 | INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) |
3234 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); | 2975 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); |
3235 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | 2976 | timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, |
3236 | 2977 | timeout*HZ); | |
3237 | if (hd->pLocal) { | 2978 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
3238 | rc = hd->pLocal->completion; | 2979 | ret = MPT_SCANDV_DID_RESET; |
3239 | hd->pLocal->skip = 0; | 2980 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3240 | 2981 | "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__, | |
3241 | /* Always set fatal error codes in some cases. | 2982 | cmd)); |
3242 | */ | 2983 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { |
3243 | if (rc == MPT_SCANDV_SELECTION_TIMEOUT) | 2984 | mpt_free_msg_frame(ioc, mf); |
3244 | rc = -ENXIO; | 2985 | goto out; |
3245 | else if (rc == MPT_SCANDV_SOME_ERROR) | 2986 | } |
3246 | rc = -rc; | 2987 | if (!timeleft) { |
3247 | } else { | 2988 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
3248 | rc = -EFAULT; | 2989 | ioc->name, __func__); |
3249 | /* This should never happen. */ | 2990 | mpt_HardResetHandler(ioc, CAN_SLEEP); |
3250 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", | 2991 | mpt_free_msg_frame(ioc, mf); |
3251 | ioc->name)); | 2992 | } |
2993 | goto out; | ||
3252 | } | 2994 | } |
3253 | 2995 | ||
3254 | return rc; | 2996 | ret = ioc->internal_cmds.completion_code; |
2997 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n", | ||
2998 | ioc->name, __func__, ret)); | ||
2999 | |||
3000 | out: | ||
3001 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
3002 | mutex_unlock(&ioc->internal_cmds.mutex); | ||
3003 | return ret; | ||
3255 | } | 3004 | } |
3256 | 3005 | ||
3257 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3006 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -3491,6 +3240,7 @@ struct device_attribute *mptscsih_host_attrs[] = { | |||
3491 | &dev_attr_debug_level, | 3240 | &dev_attr_debug_level, |
3492 | NULL, | 3241 | NULL, |
3493 | }; | 3242 | }; |
3243 | |||
3494 | EXPORT_SYMBOL(mptscsih_host_attrs); | 3244 | EXPORT_SYMBOL(mptscsih_host_attrs); |
3495 | 3245 | ||
3496 | EXPORT_SYMBOL(mptscsih_remove); | 3246 | EXPORT_SYMBOL(mptscsih_remove); |
@@ -3516,6 +3266,5 @@ EXPORT_SYMBOL(mptscsih_event_process); | |||
3516 | EXPORT_SYMBOL(mptscsih_ioc_reset); | 3266 | EXPORT_SYMBOL(mptscsih_ioc_reset); |
3517 | EXPORT_SYMBOL(mptscsih_change_queue_depth); | 3267 | EXPORT_SYMBOL(mptscsih_change_queue_depth); |
3518 | EXPORT_SYMBOL(mptscsih_timer_expired); | 3268 | EXPORT_SYMBOL(mptscsih_timer_expired); |
3519 | EXPORT_SYMBOL(mptscsih_TMHandler); | ||
3520 | 3269 | ||
3521 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3270 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |