2 * linux/drivers/message/fusion/mptscsih.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2007 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsi.com)
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
47 #include "linux_compat.h" /* linux-2.6 tweaks */
48 #include <linux/module.h>
49 #include <linux/kernel.h>
50 #include <linux/init.h>
51 #include <linux/errno.h>
52 #include <linux/kdev_t.h>
53 #include <linux/blkdev.h>
54 #include <linux/delay.h> /* for mdelay */
55 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
56 #include <linux/reboot.h> /* notifier code */
57 #include <linux/workqueue.h>
59 #include <scsi/scsi.h>
60 #include <scsi/scsi_cmnd.h>
61 #include <scsi/scsi_device.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include <scsi/scsi_dbg.h>
68 #include "lsi/mpi_log_sas.h"
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT SCSI Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptscsih"
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 MODULE_VERSION(my_VERSION);
80 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
82 * Other private/forward protos...
84 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
85 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
86 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
88 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
89 SCSIIORequest_t *pReq, int req_idx);
90 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
91 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
92 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
93 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
94 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
96 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
98 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
99 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
101 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
102 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
103 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
105 void mptscsih_remove(struct pci_dev *);
106 void mptscsih_shutdown(struct pci_dev *);
108 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
109 int mptscsih_resume(struct pci_dev *pdev);
112 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
116 * mptscsih_add_sge - Place a simple SGE at address pAddr.
117 * @pAddr: virtual address for SGE
118 * @flagslength: SGE flags and data transfer length
119 * @dma_addr: Physical address
121 * This routine places a MPT request frame back on the MPT adapter's
125 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
127 if (sizeof(dma_addr_t) == sizeof(u64)) {
128 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
129 u32 tmp = dma_addr & 0xFFFFFFFF;
131 pSge->FlagsLength = cpu_to_le32(flagslength);
132 pSge->Address.Low = cpu_to_le32(tmp);
133 tmp = (u32) ((u64)dma_addr >> 32);
134 pSge->Address.High = cpu_to_le32(tmp);
137 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
138 pSge->FlagsLength = cpu_to_le32(flagslength);
139 pSge->Address = cpu_to_le32(dma_addr);
141 } /* mptscsih_add_sge() */
143 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
145 * mptscsih_add_chain - Place a chain SGE at address pAddr.
146 * @pAddr: virtual address for SGE
147 * @next: nextChainOffset value (u32's)
148 * @length: length of next SGL segment
149 * @dma_addr: Physical address
151 * This routine places a MPT request frame back on the MPT adapter's
155 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
157 if (sizeof(dma_addr_t) == sizeof(u64)) {
158 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
159 u32 tmp = dma_addr & 0xFFFFFFFF;
161 pChain->Length = cpu_to_le16(length);
162 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
164 pChain->NextChainOffset = next;
166 pChain->Address.Low = cpu_to_le32(tmp);
167 tmp = (u32) ((u64)dma_addr >> 32);
168 pChain->Address.High = cpu_to_le32(tmp);
170 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
171 pChain->Length = cpu_to_le16(length);
172 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
173 pChain->NextChainOffset = next;
174 pChain->Address = cpu_to_le32(dma_addr);
176 } /* mptscsih_add_chain() */
178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
180 * mptscsih_getFreeChainBuffer - Function to get a free chain
181 * from the MPT_SCSI_HOST FreeChainQ.
182 * @ioc: Pointer to MPT_ADAPTER structure
183 * @req_idx: Index of the SCSI IO request frame. (output)
185 * return SUCCESS or FAILED
188 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
190 MPT_FRAME_HDR *chainBuf;
195 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
197 spin_lock_irqsave(&ioc->FreeQlock, flags);
198 if (!list_empty(&ioc->FreeChainQ)) {
201 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
202 u.frame.linkage.list);
203 list_del(&chainBuf->u.frame.linkage.list);
204 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
205 chain_idx = offset / ioc->req_sz;
207 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
208 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
211 chain_idx = MPT_HOST_NO_CHAIN;
212 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
215 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
217 *retIndex = chain_idx;
219 } /* mptscsih_getFreeChainBuffer() */
221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
223 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
224 * SCSIIORequest_t Message Frame.
225 * @ioc: Pointer to MPT_ADAPTER structure
226 * @SCpnt: Pointer to scsi_cmnd structure
227 * @pReq: Pointer to SCSIIORequest_t structure
232 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
233 SCSIIORequest_t *pReq, int req_idx)
237 struct scatterlist *sg;
239 int sges_left, sg_done;
240 int chain_idx = MPT_HOST_NO_CHAIN;
242 int numSgeSlots, numSgeThisFrame;
243 u32 sgflags, sgdir, thisxfer = 0;
244 int chain_dma_off = 0;
250 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
251 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
252 sgdir = MPT_TRANSFER_HOST_TO_IOC;
254 sgdir = MPT_TRANSFER_IOC_TO_HOST;
257 psge = (char *) &pReq->SGL;
258 frm_sz = ioc->req_sz;
260 /* Map the data portion, if any.
261 * sges_left = 0 if no data transfer.
263 sges_left = scsi_dma_map(SCpnt);
267 /* Handle the SG case.
269 sg = scsi_sglist(SCpnt);
271 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
274 /* Prior to entering this loop - the following must be set
275 * current MF: sgeOffset (bytes)
276 * chainSge (Null if original MF is not a chain buffer)
277 * sg_done (num SGE done for this MF)
281 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
282 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
284 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
286 /* Get first (num - 1) SG elements
287 * Skip any SG entries with a length of 0
288 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
290 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
291 thisxfer = sg_dma_len(sg);
293 sg ++; /* Get next SG element from the OS */
298 v2 = sg_dma_address(sg);
299 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
301 sg++; /* Get next SG element from the OS */
302 psge += (sizeof(u32) + sizeof(dma_addr_t));
303 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
307 if (numSgeThisFrame == sges_left) {
308 /* Add last element, end of buffer and end of list flags.
310 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
311 MPT_SGE_FLAGS_END_OF_BUFFER |
312 MPT_SGE_FLAGS_END_OF_LIST;
314 /* Add last SGE and set termination flags.
315 * Note: Last SGE may have a length of 0 - which should be ok.
317 thisxfer = sg_dma_len(sg);
319 v2 = sg_dma_address(sg);
320 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
323 psge += (sizeof(u32) + sizeof(dma_addr_t));
325 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
329 /* The current buffer is a chain buffer,
330 * but there is not another one.
331 * Update the chain element
332 * Offset and Length fields.
334 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
336 /* The current buffer is the original MF
337 * and there is no Chain buffer.
339 pReq->ChainOffset = 0;
340 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
341 dsgprintk((MYIOC_s_INFO_FMT
342 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
343 ioc->RequestNB[req_idx] = RequestNB;
346 /* At least one chain buffer is needed.
347 * Complete the first MF
348 * - last SGE element, set the LastElement bit
349 * - set ChainOffset (words) for orig MF
350 * (OR finish previous MF chain buffer)
351 * - update MFStructPtr ChainIndex
352 * - Populate chain element
357 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
358 ioc->name, sg_done));
360 /* Set LAST_ELEMENT flag for last non-chain element
361 * in the buffer. Since psge points at the NEXT
362 * SGE element, go back one SGE element, update the flags
363 * and reset the pointer. (Note: sgflags & thisxfer are already
367 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
368 sgflags = le32_to_cpu(*ptmp);
369 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
370 *ptmp = cpu_to_le32(sgflags);
374 /* The current buffer is a chain buffer.
375 * chainSge points to the previous Chain Element.
376 * Update its chain element Offset and Length (must
377 * include chain element size) fields.
378 * Old chain element is now complete.
380 u8 nextChain = (u8) (sgeOffset >> 2);
381 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
382 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
384 /* The original MF buffer requires a chain buffer -
386 * Last element in this MF is a chain element.
388 pReq->ChainOffset = (u8) (sgeOffset >> 2);
389 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
390 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
391 ioc->RequestNB[req_idx] = RequestNB;
394 sges_left -= sg_done;
397 /* NOTE: psge points to the beginning of the chain element
398 * in current buffer. Get a chain buffer.
400 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
401 dfailprintk((MYIOC_s_INFO_FMT
402 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
403 ioc->name, pReq->CDB[0], SCpnt));
407 /* Update the tracking arrays.
408 * If chainSge == NULL, update ReqToChain, else ChainToChain
411 ioc->ChainToChain[chain_idx] = newIndex;
413 ioc->ReqToChain[req_idx] = newIndex;
415 chain_idx = newIndex;
416 chain_dma_off = ioc->req_sz * chain_idx;
418 /* Populate the chainSGE for the current buffer.
419 * - Set chain buffer pointer to psge and fill
420 * out the Address and Flags fields.
422 chainSge = (char *) psge;
423 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
426 /* Start the SGE for the next buffer
428 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
432 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
435 /* Start the SGE for the next buffer
442 } /* mptscsih_AddSGE() */
445 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
449 SEPRequest_t *SEPMsg;
451 if (ioc->bus_type == FC)
454 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
455 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
456 ioc->name,__FUNCTION__));
460 SEPMsg = (SEPRequest_t *)mf;
461 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
462 SEPMsg->Bus = vtarget->channel;
463 SEPMsg->TargetID = vtarget->id;
464 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
465 SEPMsg->SlotStatus = SlotStatus;
466 devtverboseprintk((MYIOC_s_WARN_FMT
467 "Sending SEP cmd=%x channel=%d id=%d\n",
468 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
469 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
472 #ifdef MPT_DEBUG_REPLY
474 * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
475 * @ioc: Pointer to MPT_ADAPTER structure
476 * @ioc_status: U32 IOCStatus word from IOC
477 * @scsi_status: U8 sam status from target
478 * @scsi_state: U8 scsi state
479 * @sc: original scsi cmnd pointer
480 * @mf: Pointer to MPT request frame
482 * Refer to lsi/mpi.h.
485 mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
486 u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
488 char extend_desc[EVENT_DESCR_STR_SZ];
491 switch (ioc_status) {
493 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
494 desc = "SCSI Invalid Bus";
497 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
498 desc = "SCSI Invalid TargetID";
501 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
503 * Inquiry is issued for device scanning
505 if (sc->cmnd[0] != 0x12)
506 desc = "SCSI Device Not There";
509 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
510 desc = "SCSI Data Overrun";
513 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
514 desc = "SCSI I/O Data Error";
517 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
518 desc = "SCSI Protocol Error";
521 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
522 desc = "SCSI Task Terminated";
525 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
526 desc = "SCSI Residual Mismatch";
529 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
530 desc = "SCSI Task Management Failed";
533 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
534 desc = "SCSI IOC Terminated";
537 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
538 desc = "SCSI Ext Terminated";
545 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
546 "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
547 sc->device->host->host_no,
548 sc->device->channel, sc->device->id, sc->device->lun,
549 sc->cmnd[0], scsi_status, scsi_state);
551 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
552 ioc->name, ioc_status, desc, extend_desc);
556 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
558 * mptscsih_io_done - Main SCSI IO callback routine registered to
559 * Fusion MPT (base) driver
560 * @ioc: Pointer to MPT_ADAPTER structure
561 * @mf: Pointer to original MPT request frame
562 * @r: Pointer to MPT reply frame (NULL if TurboReply)
564 * This routine is called from mpt.c::mpt_interrupt() at the completion
565 * of any SCSI IO request.
566 * This routine is registered with the Fusion MPT (base) driver at driver
567 * load/init time via the mpt_register() API call.
569 * Returns 1 indicating alloc'd request frame ptr should be freed.
572 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
574 struct scsi_cmnd *sc;
576 SCSIIORequest_t *pScsiReq;
577 SCSIIOReply_t *pScsiReply;
578 u16 req_idx, req_idx_MR;
582 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
584 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
585 req_idx_MR = (mr != NULL) ?
586 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
587 if ((req_idx != req_idx_MR) ||
588 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
589 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
591 printk (MYIOC_s_ERR_FMT
592 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
593 ioc->name, req_idx, req_idx_MR, mf, mr,
594 hd->ScsiLookup[req_idx_MR]);
598 sc = hd->ScsiLookup[req_idx];
599 hd->ScsiLookup[req_idx] = NULL;
601 MPIHeader_t *hdr = (MPIHeader_t *)mf;
603 /* Remark: writeSDP1 will use the ScsiDoneCtx
604 * If a SCSI I/O cmd, device disabled by OS and
605 * completion done. Cannot touch sc struct. Just free mem.
607 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
608 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
611 mptscsih_freeChainBuffers(ioc, req_idx);
615 if ((unsigned char *)mf != sc->host_scribble) {
616 mptscsih_freeChainBuffers(ioc, req_idx);
620 sc->host_scribble = NULL;
621 sc->result = DID_OK << 16; /* Set default reply as OK */
622 pScsiReq = (SCSIIORequest_t *) mf;
623 pScsiReply = (SCSIIOReply_t *) mr;
625 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
626 dmfprintk((MYIOC_s_INFO_FMT
627 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
628 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
630 dmfprintk((MYIOC_s_INFO_FMT
631 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
632 ioc->name, mf, mr, sc, req_idx));
635 if (pScsiReply == NULL) {
636 /* special context reply handling */
641 u8 scsi_state, scsi_status;
644 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
645 scsi_state = pScsiReply->SCSIState;
646 scsi_status = pScsiReply->SCSIStatus;
647 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
648 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
649 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
652 * if we get a data underrun indication, yet no data was
653 * transferred and the SCSI status indicates that the
654 * command was never started, change the data underrun
657 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
658 (scsi_status == MPI_SCSI_STATUS_BUSY ||
659 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
660 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
661 status = MPI_IOCSTATUS_SUCCESS;
664 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
665 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
668 * Look for + dump FCP ResponseInfo[]!
670 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
671 pScsiReply->ResponseInfo) {
672 printk(KERN_NOTICE "[%d:%d:%d:%d] "
673 "FCP_ResponseInfo=%08xh\n",
674 sc->device->host->host_no, sc->device->channel,
675 sc->device->id, sc->device->lun,
676 le32_to_cpu(pScsiReply->ResponseInfo));
680 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
682 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
683 * But not: DID_BUS_BUSY lest one risk
684 * killing interrupt handler:-(
686 sc->result = SAM_STAT_BUSY;
689 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
690 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
691 sc->result = DID_BAD_TARGET << 16;
694 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
695 /* Spoof to SCSI Selection Timeout! */
696 if (ioc->bus_type != FC)
697 sc->result = DID_NO_CONNECT << 16;
698 /* else fibre, just stall until rescan event */
700 sc->result = DID_REQUEUE << 16;
702 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
703 hd->sel_timeout[pScsiReq->TargetID]++;
705 vdev = sc->device->hostdata;
708 vtarget = vdev->vtarget;
709 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
710 mptscsih_issue_sep_command(ioc, vtarget,
711 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
712 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
716 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
717 if ( ioc->bus_type == SAS ) {
718 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
719 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
720 if ((log_info & SAS_LOGINFO_MASK)
721 == SAS_LOGINFO_NEXUS_LOSS) {
722 sc->result = (DID_BUS_BUSY << 16);
726 } else if (ioc->bus_type == FC) {
728 * The FC IOC may kill a request for variety of
729 * reasons, some of which may be recovered by a
730 * retry, some which are unlikely to be
731 * recovered. Return DID_ERROR instead of
732 * DID_RESET to permit retry of the command,
733 * just not an infinite number of them
735 sc->result = DID_ERROR << 16;
740 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
743 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
744 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
745 /* Linux handles an unsolicited DID_RESET better
746 * than an unsolicited DID_ABORT.
748 sc->result = DID_RESET << 16;
752 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
753 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
754 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
755 sc->result=DID_SOFT_ERROR << 16;
756 else /* Sufficient data transfer occurred */
757 sc->result = (DID_OK << 16) | scsi_status;
758 dreplyprintk((KERN_NOTICE
759 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
760 sc->result, sc->device->channel, sc->device->id));
763 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
765 * Do upfront check for valid SenseData and give it
768 sc->result = (DID_OK << 16) | scsi_status;
769 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
770 /* Have already saved the status and sense data
774 if (xfer_cnt < sc->underflow) {
775 if (scsi_status == SAM_STAT_BUSY)
776 sc->result = SAM_STAT_BUSY;
778 sc->result = DID_SOFT_ERROR << 16;
780 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
783 sc->result = DID_SOFT_ERROR << 16;
785 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
786 /* Not real sure here either... */
787 sc->result = DID_RESET << 16;
791 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
793 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
796 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
797 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
801 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
802 scsi_set_resid(sc, 0);
803 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
804 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
805 sc->result = (DID_OK << 16) | scsi_status;
806 if (scsi_state == 0) {
808 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
810 * If running against circa 200003dd 909 MPT f/w,
811 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
812 * (QUEUE_FULL) returned from device! --> get 0x0000?128
813 * and with SenseBytes set to 0.
815 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
816 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
819 else if (scsi_state &
820 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
825 sc->result = DID_SOFT_ERROR << 16;
827 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
828 /* Not real sure here either... */
829 sc->result = DID_RESET << 16;
831 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
832 /* Device Inq. data indicates that it supports
833 * QTags, but rejects QTag messages.
834 * This command completed OK.
836 * Not real sure here either so do nothing... */
839 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
840 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
843 * Reservation Conflict, Busy,
844 * Command Terminated, CHECK
848 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
849 sc->result = DID_SOFT_ERROR << 16;
852 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
853 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
854 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
855 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
856 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
857 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
858 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
859 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
860 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
865 sc->result = DID_SOFT_ERROR << 16;
868 } /* switch(status) */
870 #ifdef MPT_DEBUG_REPLY
873 mptscsih_iocstatus_info_scsiio(ioc, status,
874 scsi_status, scsi_state, sc);
876 dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
877 "result=0x%08x\n\tiocstatus=0x%04X "
878 "scsi_state=0x%02X scsi_status=0x%02X "
879 "loginfo=0x%08X\n", __FUNCTION__,
880 sc->device->host->host_no, sc->device->channel, sc->device->id,
881 sc->device->lun, sc->cmnd[0], sc->result, status,
882 scsi_state, scsi_status, log_info));
884 dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
885 "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
886 sc->device->host->host_no,
887 sc->device->channel, sc->device->id,
888 sc->device->lun, scsi_get_resid(sc),
889 scsi_bufflen(sc), xfer_cnt));
893 } /* end of address reply case */
895 /* Unmap the DMA buffers, if any. */
898 sc->scsi_done(sc); /* Issue the command callback */
900 /* Free Chain buffers */
901 mptscsih_freeChainBuffers(ioc, req_idx);
906 * mptscsih_flush_running_cmds - For each command found, search
907 * Scsi_Host instance taskQ and reply to OS.
908 * Called only if recovering from a FW reload.
909 * @hd: Pointer to a SCSI HOST structure
913 * Must be called while new I/Os are being queued.
916 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
918 MPT_ADAPTER *ioc = hd->ioc;
919 struct scsi_cmnd *SCpnt;
922 int max = ioc->req_depth;
924 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
925 for (ii= 0; ii < max; ii++) {
926 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
931 /* Null ScsiLookup index
933 hd->ScsiLookup[ii] = NULL;
935 mf = MPT_INDEX_2_MFPTR(ioc, ii);
936 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
939 /* Free Chain buffers */
940 mptscsih_freeChainBuffers(ioc, ii);
942 /* Free Message frames */
943 mpt_free_msg_frame(ioc, mf);
945 if ((unsigned char *)mf != SCpnt->host_scribble)
948 /* Set status, free OS resources (SG DMA buffers)
951 scsi_dma_unmap(SCpnt);
953 SCpnt->result = DID_RESET << 16;
954 SCpnt->host_scribble = NULL;
956 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
964 * mptscsih_search_running_cmds - Delete any commands associated
965 * with the specified target and lun. Function called only
966 * when a lun is disable by mid-layer.
967 * Do NOT access the referenced scsi_cmnd structure or
968 * members. Will cause either a paging or NULL ptr error.
969 * (BUT, BUT, BUT, the code does reference it! - mdr)
970 * @hd: Pointer to a SCSI HOST structure
971 * @vdevice: per device private data
975 * Called from slave_destroy.
978 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
980 SCSIIORequest_t *mf = NULL;
982 int max = hd->ioc->req_depth;
983 struct scsi_cmnd *sc;
986 dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
987 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
989 for (ii=0; ii < max; ii++) {
990 if ((sc = hd->ScsiLookup[ii]) != NULL) {
992 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
995 int_to_scsilun(vdevice->lun, &lun);
996 if ((mf->Bus != vdevice->vtarget->channel) ||
997 (mf->TargetID != vdevice->vtarget->id) ||
998 memcmp(lun.scsi_lun, mf->LUN, 8))
1000 dsprintk(( "search_running: found (sc=%p, mf = %p) "
1001 "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
1002 mf, mf->Bus, mf->TargetID, vdevice->lun));
1006 hd->ScsiLookup[ii] = NULL;
1007 mptscsih_freeChainBuffers(hd->ioc, ii);
1008 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1009 if ((unsigned char *)mf != sc->host_scribble)
1013 sc->host_scribble = NULL;
1014 sc->result = DID_NO_CONNECT << 16;
1021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1025 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1026 * from a SCSI target device.
1027 * @sc: Pointer to scsi_cmnd structure
1028 * @pScsiReply: Pointer to SCSIIOReply_t
1029 * @pScsiReq: Pointer to original SCSI request
1031 * This routine periodically reports QUEUE_FULL status returned from a
1032 * SCSI target device. It reports this to the console via kernel
1033 * printk() API call, not more than once every 10 seconds.
1036 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1038 long time = jiffies;
1041 if (sc->device == NULL)
1043 if (sc->device->host == NULL)
1045 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1048 if (time - hd->last_queue_full > 10 * HZ) {
1049 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1050 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1051 hd->last_queue_full = time;
1055 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1057 * mptscsih_remove - Removed scsi devices
1058 * @pdev: Pointer to pci_dev structure
1063 mptscsih_remove(struct pci_dev *pdev)
1065 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1066 struct Scsi_Host *host = ioc->sh;
1075 scsi_remove_host(host);
1077 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1080 mptscsih_shutdown(pdev);
1084 if (hd->ScsiLookup != NULL) {
1085 sz1 = hd->ioc->req_depth * sizeof(void *);
1086 kfree(hd->ScsiLookup);
1087 hd->ScsiLookup = NULL;
1090 dprintk((MYIOC_s_INFO_FMT
1091 "Free'd ScsiLookup (%d) memory\n",
1092 hd->ioc->name, sz1));
1094 kfree(hd->info_kbuf);
1096 /* NULL the Scsi_Host pointer
1100 scsi_host_put(host);
1106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1108 * mptscsih_shutdown - reboot notifier
1112 mptscsih_shutdown(struct pci_dev *pdev)
1114 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1115 struct Scsi_Host *host = ioc->sh;
1121 hd = (MPT_SCSI_HOST *)host->hostdata;
1126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1128 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1133 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1135 mptscsih_shutdown(pdev);
1136 return mpt_suspend(pdev,state);
1139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1141 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1146 mptscsih_resume(struct pci_dev *pdev)
1148 return mpt_resume(pdev);
1153 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1155 * mptscsih_info - Return information about MPT adapter
1156 * @SChost: Pointer to Scsi_Host structure
1158 * (linux scsi_host_template.info routine)
1160 * Returns pointer to buffer where information was written.
1163 mptscsih_info(struct Scsi_Host *SChost)
1168 h = (MPT_SCSI_HOST *)SChost->hostdata;
1171 if (h->info_kbuf == NULL)
1172 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1173 return h->info_kbuf;
1174 h->info_kbuf[0] = '\0';
1176 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1177 h->info_kbuf[size-1] = '\0';
1180 return h->info_kbuf;
1191 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1193 if (info->pos + len > info->length)
1194 len = info->length - info->pos;
1196 if (info->pos + len < info->offset) {
1201 if (info->pos < info->offset) {
1202 data += (info->offset - info->pos);
1203 len -= (info->offset - info->pos);
1207 memcpy(info->buffer + info->pos, data, len);
1213 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1219 va_start(args, fmt);
1220 len = vsprintf(buf, fmt, args);
1223 mptscsih_copy_mem_info(info, buf, len);
1228 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1230 struct info_str info;
1234 info.offset = offset;
1237 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1238 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1239 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1240 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1242 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1247 * mptscsih_proc_info - Return information about MPT adapter
1248 * @host: scsi host struct
1249 * @buffer: if write, user data; if read, buffer for user
1250 * @start: returns the buffer address
1251 * @offset: if write, 0; if read, the current offset into the buffer from
1252 * the previous read.
1253 * @length: if write, return length;
1254 * @func: write = 1; read = 0
1256 * (linux scsi_host_template.info routine)
1259 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1260 int length, int func)
1262 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1263 MPT_ADAPTER *ioc = hd->ioc;
1268 * write is not supported
1274 size = mptscsih_host_info(ioc, buffer, offset, length);
1280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1281 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1283 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1285 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1286 * @SCpnt: Pointer to scsi_cmnd structure
1287 * @done: Pointer SCSI mid-layer IO completion function
1289 * (linux scsi_host_template.queuecommand routine)
1290 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1291 * from a linux scsi_cmnd request and send it to the IOC.
1293 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1296 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1300 SCSIIORequest_t *pScsiReq;
1301 VirtDevice *vdev = SCpnt->device->hostdata;
1310 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1311 lun = SCpnt->device->lun;
1312 SCpnt->scsi_done = done;
1314 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1315 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1317 if (hd->resetPending) {
1318 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1319 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1320 return SCSI_MLQUEUE_HOST_BUSY;
1324 * Put together a MPT SCSI request...
1326 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1327 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1329 return SCSI_MLQUEUE_HOST_BUSY;
1332 pScsiReq = (SCSIIORequest_t *) mf;
1334 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1336 ADD_INDEX_LOG(my_idx);
1338 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1339 * Seems we may receive a buffer (datalen>0) even when there
1340 * will be no data transfer! GRRRRR...
1342 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1343 datalen = scsi_bufflen(SCpnt);
1344 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1345 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1346 datalen = scsi_bufflen(SCpnt);
1347 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1350 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1353 /* Default to untagged. Once a target structure has been allocated,
1354 * use the Inquiry data to determine if device supports tagged.
1357 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1358 && (SCpnt->device->tagged_supported)) {
1359 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1361 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1364 /* Use the above information to set up the message frame
1366 pScsiReq->TargetID = (u8) vdev->vtarget->id;
1367 pScsiReq->Bus = vdev->vtarget->channel;
1368 pScsiReq->ChainOffset = 0;
1369 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1370 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1372 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1373 pScsiReq->CDBLength = SCpnt->cmd_len;
1374 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1375 pScsiReq->Reserved = 0;
1376 pScsiReq->MsgFlags = mpt_msg_flags();
1377 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1378 pScsiReq->Control = cpu_to_le32(scsictl);
1381 * Write SCSI CDB into the message
1383 cmd_len = SCpnt->cmd_len;
1384 for (ii=0; ii < cmd_len; ii++)
1385 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1387 for (ii=cmd_len; ii < 16; ii++)
1388 pScsiReq->CDB[ii] = 0;
1391 pScsiReq->DataLength = cpu_to_le32(datalen);
1393 /* SenseBuffer low address */
1394 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1395 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1397 /* Now add the SG list
1398 * Always have a SGE even if null length.
1401 /* Add a NULL SGE */
1402 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1405 /* Add a 32 or 64 bit SGE */
1406 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1410 SCpnt->host_scribble = (unsigned char *)mf;
1411 hd->ScsiLookup[my_idx] = SCpnt;
1413 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1414 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1415 hd->ioc->name, SCpnt, mf, my_idx));
1416 DBG_DUMP_REQUEST_FRAME(mf)
1420 hd->ScsiLookup[my_idx] = NULL;
1421 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1422 mpt_free_msg_frame(hd->ioc, mf);
1423 return SCSI_MLQUEUE_HOST_BUSY;
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1429 * with a SCSI IO request
1430 * @hd: Pointer to the MPT_SCSI_HOST instance
1431 * @req_idx: Index of the SCSI IO request frame.
1433 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1437 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1439 MPT_FRAME_HDR *chain;
1440 unsigned long flags;
1444 /* Get the first chain index and reset
1447 chain_idx = ioc->ReqToChain[req_idx];
1448 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1450 while (chain_idx != MPT_HOST_NO_CHAIN) {
1452 /* Save the next chain buffer index */
1453 next = ioc->ChainToChain[chain_idx];
1455 /* Free this chain buffer and reset
1458 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1460 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1461 + (chain_idx * ioc->req_sz));
1463 spin_lock_irqsave(&ioc->FreeQlock, flags);
1464 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1465 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1467 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1468 ioc->name, chain_idx));
1476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484 * @hd: Pointer to MPT SCSI HOST structure
1485 * @type: Task Management type
1486 * @channel: channel number for task management
1487 * @id: Logical Target ID for reset (if appropriate)
1488 * @lun: Logical Unit for reset (if appropriate)
1489 * @ctx2abort: Context for the task to be aborted (if appropriate)
1490 * @timeout: timeout for task management control
1492 * Fall through to mpt_HardResetHandler if: not operational, too many
1493 * failed TM requests or handshake failure.
1495 * Remark: Currently invoked from a non-interrupt thread (_bh).
1497 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1500 * Returns 0 for SUCCESS, or %FAILED.
1503 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1508 unsigned long flags;
1511 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1513 // SJR - CHECKME - Can we avoid this here?
1514 // (mpt_HardResetHandler has this check...)
1515 spin_lock_irqsave(&ioc->diagLock, flags);
1516 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1517 spin_unlock_irqrestore(&ioc->diagLock, flags);
1520 spin_unlock_irqrestore(&ioc->diagLock, flags);
1522 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1523 * If we time out and not bus reset, then we return a FAILED status
1525 * The call to mptscsih_tm_pending_wait() will set the pending flag
1527 * successful. Otherwise, reload the FW.
1529 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1530 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1531 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1532 "Timed out waiting for last TM (%d) to complete! \n",
1533 hd->ioc->name, hd->tmPending));
1535 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1536 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
1537 "reset: Timed out waiting for last TM (%d) "
1538 "to complete! \n", hd->ioc->name,
1541 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1542 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1543 "Timed out waiting for last TM (%d) to complete! \n",
1544 hd->ioc->name, hd->tmPending));
1548 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1549 hd->tmPending |= (1 << type);
1550 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1553 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1555 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1556 printk(MYIOC_s_WARN_FMT
1557 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1558 ioc->name, type, ioc_raw_state);
1559 printk(KERN_WARNING " Issuing HardReset!!\n");
1560 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1561 printk((KERN_WARNING "TMHandler: HardReset "
1566 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1567 printk(MYIOC_s_WARN_FMT
1568 "TM Handler for type=%x: ioc_state: "
1569 "DOORBELL_ACTIVE (0x%x)!\n",
1570 ioc->name, type, ioc_raw_state);
1574 /* Isse the Task Mgmt request.
1576 if (hd->hard_resets < -1)
1579 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1580 ctx2abort, timeout);
1582 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1585 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
1588 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1596 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1597 * @hd: Pointer to MPT_SCSI_HOST structure
1598 * @type: Task Management type
1599 * @channel: channel number for task management
1600 * @id: Logical Target ID for reset (if appropriate)
1601 * @lun: Logical Unit for reset (if appropriate)
1602 * @ctx2abort: Context for the task to be aborted (if appropriate)
1603 * @timeout: timeout for task management control
1605 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1606 * or a non-interrupt thread. In the former, must not call schedule().
1608 * Not all fields are meaningfull for all task types.
1610 * Returns 0 for SUCCESS, or FAILED.
1614 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1617 SCSITaskMgmt_t *pScsiTm;
1621 /* Return Fail to calling function if no message frames available.
1623 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1624 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1628 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1629 hd->ioc->name, mf));
1631 /* Format the Request
1633 pScsiTm = (SCSITaskMgmt_t *) mf;
1634 pScsiTm->TargetID = id;
1635 pScsiTm->Bus = channel;
1636 pScsiTm->ChainOffset = 0;
1637 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1639 pScsiTm->Reserved = 0;
1640 pScsiTm->TaskType = type;
1641 pScsiTm->Reserved1 = 0;
1642 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1643 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1645 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1647 for (ii=0; ii < 7; ii++)
1648 pScsiTm->Reserved2[ii] = 0;
1650 pScsiTm->TaskMsgContext = ctx2abort;
1652 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1653 "type=%d\n", hd->ioc->name, ctx2abort, type));
1655 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1657 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1658 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
1659 dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
1660 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1661 hd->ioc, mf, retval));
1665 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1666 dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1667 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1669 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1671 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1672 dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
1673 hd->ioc->name, retval));
1678 * Handle success case, see if theres a non-zero ioc_status.
1680 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1681 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1682 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1692 * Free task managment mf, and corresponding tm flags
1694 mpt_free_msg_frame(hd->ioc, mf);
1696 hd->tmState = TM_STATE_NONE;
1701 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1703 switch (ioc->bus_type) {
1714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1716 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1717 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1719 * (linux scsi_host_template.eh_abort_handler routine)
1721 * Returns SUCCESS or FAILED.
1724 mptscsih_abort(struct scsi_cmnd * SCpnt)
1732 ulong sn = SCpnt->serial_number;
1734 /* If we can't locate our host adapter structure, return FAILED status.
1736 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1737 SCpnt->result = DID_RESET << 16;
1738 SCpnt->scsi_done(SCpnt);
1739 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1740 "Can't locate host! (sc=%p)\n",
1745 /* Find this command
1747 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1748 /* Cmd not found in ScsiLookup.
1751 SCpnt->result = DID_RESET << 16;
1752 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1753 "Command not in the active list! (sc=%p)\n",
1754 hd->ioc->name, SCpnt));
1758 if (hd->resetPending)
1761 if (hd->timeouts < -1)
1764 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1765 hd->ioc->name, SCpnt);
1766 scsi_print_command(SCpnt);
1768 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1769 * (the IO to be ABORT'd)
1771 * NOTE: Since we do not byteswap MsgContext, we do not
1772 * swap it here either. It is an opaque cookie to
1773 * the controller, so it does not matter. -DaveM
1775 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1776 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1778 hd->abortSCpnt = SCpnt;
1780 vdev = SCpnt->device->hostdata;
1781 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1782 vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
1783 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1785 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1786 SCpnt->serial_number == sn)
1789 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1791 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1799 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1801 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1802 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1804 * (linux scsi_host_template.eh_dev_reset_handler routine)
1806 * Returns SUCCESS or FAILED.
1809 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1815 /* If we can't locate our host adapter structure, return FAILED status.
1817 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1818 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1819 "Can't locate host! (sc=%p)\n",
1824 if (hd->resetPending)
1827 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1828 hd->ioc->name, SCpnt);
1829 scsi_print_command(SCpnt);
1831 vdev = SCpnt->device->hostdata;
1832 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1833 vdev->vtarget->channel, vdev->vtarget->id,
1834 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1836 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1838 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1847 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1849 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1850 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1852 * (linux scsi_host_template.eh_bus_reset_handler routine)
1854 * Returns SUCCESS or FAILED.
1857 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1863 /* If we can't locate our host adapter structure, return FAILED status.
1865 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1866 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1867 "Can't locate host! (sc=%p)\n",
1872 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1873 hd->ioc->name, SCpnt);
1874 scsi_print_command(SCpnt);
1876 if (hd->timeouts < -1)
1879 vdev = SCpnt->device->hostdata;
1880 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1881 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1883 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1885 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1895 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1896 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1898 * (linux scsi_host_template.eh_host_reset_handler routine)
1900 * Returns SUCCESS or FAILED.
1903 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1906 int status = SUCCESS;
1908 /* If we can't locate the host to reset, then we failed. */
1909 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1910 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1911 "Can't locate host! (sc=%p)\n",
1916 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1917 hd->ioc->name, SCpnt);
1919 /* If our attempts to reset the host failed, then return a failed
1920 * status. The host will be taken off line by the SCSI mid-layer.
1922 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1925 /* Make sure TM pending is cleared and TM state is set to
1929 hd->tmState = TM_STATE_NONE;
1932 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1934 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1939 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1941 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1942 * @hd: Pointer to MPT host structure.
1944 * Returns {SUCCESS,FAILED}.
1947 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1949 unsigned long flags;
1950 int loop_count = 4 * 10; /* Wait 10 seconds */
1951 int status = FAILED;
1954 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1955 if (hd->tmState == TM_STATE_NONE) {
1956 hd->tmState = TM_STATE_IN_PROGRESS;
1958 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1962 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1964 } while (--loop_count);
1969 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1971 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1972 * @hd: Pointer to MPT host structure.
1973 * @timeout: timeout value
1975 * Returns {SUCCESS,FAILED}.
1978 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1980 unsigned long flags;
1981 int loop_count = 4 * timeout;
1982 int status = FAILED;
1985 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1986 if(hd->tmPending == 0) {
1988 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1991 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1993 } while (--loop_count);
1998 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2000 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2004 switch (response_code) {
2005 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2006 desc = "The task completed.";
2008 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2009 desc = "The IOC received an invalid frame status.";
2011 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2012 desc = "The task type is not supported.";
2014 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2015 desc = "The requested task failed.";
2017 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2018 desc = "The task completed successfully.";
2020 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2021 desc = "The LUN request is invalid.";
2023 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2024 desc = "The task is in the IOC queue and has not been sent to target.";
2030 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2031 ioc->name, response_code, desc);
2034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2036 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2037 * @ioc: Pointer to MPT_ADAPTER structure
2038 * @mf: Pointer to SCSI task mgmt request frame
2039 * @mr: Pointer to SCSI task mgmt reply frame
2041 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2042 * of any SCSI task management request.
2043 * This routine is registered with the MPT (base) driver at driver
2044 * load/init time via the mpt_register() API call.
2046 * Returns 1 indicating alloc'd request frame ptr should be freed.
2049 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2051 SCSITaskMgmtReply_t *pScsiTmReply;
2052 SCSITaskMgmt_t *pScsiTmReq;
2054 unsigned long flags;
2057 u32 termination_count;
2059 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2060 ioc->name, mf, mr));
2062 dtmprintk((MYIOC_s_WARN_FMT
2063 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2068 dtmprintk((MYIOC_s_WARN_FMT
2069 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2073 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2074 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2075 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2076 tmType = pScsiTmReq->TaskType;
2077 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2078 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2080 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2081 pScsiTmReply->ResponseCode)
2082 mptscsih_taskmgmt_response_code(ioc,
2083 pScsiTmReply->ResponseCode);
2084 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2086 #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
2087 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2088 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2089 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2090 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2091 le16_to_cpu(pScsiTmReply->IOCStatus),
2092 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2093 le32_to_cpu(pScsiTmReply->TerminationCount));
2096 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2097 hd->abortSCpnt = NULL;
2101 /* Error? (anything non-zero?) */
2103 /* clear flags and continue.
2107 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2108 if (termination_count == 1)
2109 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2110 hd->abortSCpnt = NULL;
2113 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2115 /* If an internal command is present
2116 * or the TM failed - reload the FW.
2117 * FC FW may respond FAILED to an ABORT
2119 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2121 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2122 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2125 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2131 spin_lock_irqsave(&ioc->FreeQlock, flags);
2133 hd->tmState = TM_STATE_NONE;
2134 hd->tm_iocstatus = iocstatus;
2135 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2142 * This is anyones guess quite frankly.
2145 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2146 sector_t capacity, int geom[])
2156 dummy = heads * sectors;
2157 cylinders = capacity;
2158 sector_div(cylinders,dummy);
2161 * Handle extended translation size for logical drives
2164 if ((ulong)capacity >= 0x200000) {
2167 dummy = heads * sectors;
2168 cylinders = capacity;
2169 sector_div(cylinders,dummy);
2175 geom[2] = cylinders;
2177 dprintk((KERN_NOTICE
2178 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2179 sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
2184 /* Search IOC page 3 to determine if this is hidden physical disk
2188 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2190 struct inactive_raid_component_info *component_info;
2194 if (!ioc->raid_data.pIocPg3)
2196 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2197 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2198 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2205 * Check inactive list for matching phys disks
2207 if (list_empty(&ioc->raid_data.inactive_list))
2210 down(&ioc->raid_data.inactive_list_mutex);
2211 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2213 if ((component_info->d.PhysDiskID == id) &&
2214 (component_info->d.PhysDiskBus == channel))
2217 up(&ioc->raid_data.inactive_list_mutex);
2222 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2225 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2227 struct inactive_raid_component_info *component_info;
2231 if (!ioc->raid_data.pIocPg3)
2233 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2234 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2235 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2236 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2242 * Check inactive list for matching phys disks
2244 if (list_empty(&ioc->raid_data.inactive_list))
2247 down(&ioc->raid_data.inactive_list_mutex);
2248 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2250 if ((component_info->d.PhysDiskID == id) &&
2251 (component_info->d.PhysDiskBus == channel))
2252 rc = component_info->d.PhysDiskNum;
2254 up(&ioc->raid_data.inactive_list_mutex);
2259 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2262 * OS entry point to allow for host driver to free allocated memory
2263 * Called if no device present or device being unloaded
2266 mptscsih_slave_destroy(struct scsi_device *sdev)
2268 struct Scsi_Host *host = sdev->host;
2269 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2270 VirtTarget *vtarget;
2271 VirtDevice *vdevice;
2272 struct scsi_target *starget;
2274 starget = scsi_target(sdev);
2275 vtarget = starget->hostdata;
2276 vdevice = sdev->hostdata;
2278 mptscsih_search_running_cmds(hd, vdevice);
2279 vtarget->num_luns--;
2280 mptscsih_synchronize_cache(hd, vdevice);
2282 sdev->hostdata = NULL;
2285 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2287 * mptscsih_change_queue_depth - This function will set a devices queue depth
2288 * @sdev: per scsi_device pointer
2289 * @qdepth: requested queue depth
2291 * Adding support for new 'change_queue_depth' api.
2294 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2296 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2297 VirtTarget *vtarget;
2298 struct scsi_target *starget;
2302 starget = scsi_target(sdev);
2303 vtarget = starget->hostdata;
2305 if (hd->ioc->bus_type == SPI) {
2306 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2308 else if (sdev->type == TYPE_DISK &&
2309 vtarget->minSyncFactor <= MPT_ULTRA160)
2310 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2312 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2314 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2316 if (qdepth > max_depth)
2321 tagged = MSG_SIMPLE_TAG;
2323 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2324 return sdev->queue_depth;
2328 * OS entry point to adjust the queue_depths on a per-device basis.
2329 * Called once per device the bus scan. Use it to force the queue_depth
2330 * member to 1 if a device does not support Q tags.
2331 * Return non-zero if fails.
2334 mptscsih_slave_configure(struct scsi_device *sdev)
2336 struct Scsi_Host *sh = sdev->host;
2337 VirtTarget *vtarget;
2338 VirtDevice *vdevice;
2339 struct scsi_target *starget;
2340 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2342 starget = scsi_target(sdev);
2343 vtarget = starget->hostdata;
2344 vdevice = sdev->hostdata;
2346 dsprintk((MYIOC_s_INFO_FMT
2347 "device @ %p, channel=%d, id=%d, lun=%d\n",
2348 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2349 if (hd->ioc->bus_type == SPI)
2350 dsprintk((MYIOC_s_INFO_FMT
2351 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2352 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2353 sdev->ppr, sdev->inquiry_len));
2355 if (sdev->id > sh->max_id) {
2356 /* error case, should never happen */
2357 scsi_adjust_queue_depth(sdev, 0, 1);
2358 goto slave_configure_exit;
2361 vdevice->configured_lun = 1;
2362 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2364 dsprintk((MYIOC_s_INFO_FMT
2365 "Queue depth=%d, tflags=%x\n",
2366 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2368 if (hd->ioc->bus_type == SPI)
2369 dsprintk((MYIOC_s_INFO_FMT
2370 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2371 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2372 vtarget->minSyncFactor));
2374 slave_configure_exit:
2376 dsprintk((MYIOC_s_INFO_FMT
2377 "tagged %d, simple %d, ordered %d\n",
2378 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2379 sdev->ordered_tags));
2384 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2386 * Private routines...
2389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2390 /* Utility function to copy sense data from the scsi_cmnd buffer
2391 * to the FC and SCSI target structures.
2395 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2398 SCSIIORequest_t *pReq;
2399 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2401 /* Get target structure
2403 pReq = (SCSIIORequest_t *) mf;
2404 vdev = sc->device->hostdata;
2410 /* Copy the sense received into the scsi command block. */
2411 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2412 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2413 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2415 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2417 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2418 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2420 MPT_ADAPTER *ioc = hd->ioc;
2422 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2423 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2424 ioc->events[idx].eventContext = ioc->eventContext;
2426 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2427 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2428 (sc->device->channel << 8) | sc->device->id;
2430 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2432 ioc->eventContext++;
2433 if (hd->ioc->pcidev->vendor ==
2434 PCI_VENDOR_ID_IBM) {
2435 mptscsih_issue_sep_command(hd->ioc,
2436 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2437 vdev->vtarget->tflags |=
2438 MPT_TARGET_FLAGS_LED_ON;
2443 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2449 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2454 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2456 for (i = 0; i < hd->ioc->req_depth; i++) {
2457 if (hd->ScsiLookup[i] == sc) {
2465 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2467 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2470 unsigned long flags;
2473 dtmprintk((KERN_WARNING MYNAM
2474 ": IOC %s_reset routed to SCSI host driver!\n",
2475 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2476 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2478 /* If a FW reload request arrives after base installed but
2479 * before all scsi hosts have been attached, then an alt_ioc
2480 * may have a NULL sh pointer.
2482 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2485 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2487 if (reset_phase == MPT_IOC_SETUP_RESET) {
2488 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2491 * 1. Set Hard Reset Pending Flag
2492 * All new commands go to doneQ
2494 hd->resetPending = 1;
2496 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2497 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2499 /* 2. Flush running commands
2500 * Clean ScsiLookup (and associated memory)
2504 /* 2b. Reply to OS all known outstanding I/O commands.
2506 mptscsih_flush_running_cmds(hd);
2508 /* 2c. If there was an internal command that
2509 * has not completed, configuration or io request,
2510 * free these resources.
2513 del_timer(&hd->timer);
2514 mpt_free_msg_frame(ioc, hd->cmdPtr);
2517 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2520 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2522 /* Once a FW reload begins, all new OS commands are
2523 * redirected to the doneQ w/ a reset status.
2524 * Init all control structures.
2527 /* ScsiLookup initialization
2529 for (ii=0; ii < hd->ioc->req_depth; ii++)
2530 hd->ScsiLookup[ii] = NULL;
2532 /* 2. Chain Buffer initialization
2535 /* 4. Renegotiate to all devices, if SPI
2538 /* 5. Enable new commands to be posted
2540 spin_lock_irqsave(&ioc->FreeQlock, flags);
2542 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2543 hd->resetPending = 0;
2544 hd->tmState = TM_STATE_NONE;
2546 /* 6. If there was an internal command,
2547 * wake this process up.
2551 * Wake up the original calling thread
2553 hd->pLocal = &hd->localReply;
2554 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2555 hd->scandv_wait_done = 1;
2556 wake_up(&hd->scandv_waitq);
2560 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2564 return 1; /* currently means nothing really */
2567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2569 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2572 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2574 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2577 if (ioc->sh == NULL ||
2578 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2582 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2585 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2586 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2587 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2590 case MPI_EVENT_LOGOUT: /* 09 */
2594 case MPI_EVENT_RESCAN: /* 06 */
2598 * CHECKME! Don't think we need to do
2599 * anything for these, but...
2601 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2602 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2604 * CHECKME! Falling thru...
2608 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2611 case MPI_EVENT_NONE: /* 00 */
2612 case MPI_EVENT_LOG_DATA: /* 01 */
2613 case MPI_EVENT_STATE_CHANGE: /* 02 */
2614 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2616 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2620 return 1; /* currently means nothing really */
2623 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2625 * Bus Scan and Domain Validation functionality ...
2628 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2630 * mptscsih_scandv_complete - Scan and DV callback routine registered
2631 * to Fustion MPT (base) driver.
2633 * @ioc: Pointer to MPT_ADAPTER structure
2634 * @mf: Pointer to original MPT request frame
2635 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2637 * This routine is called from mpt.c::mpt_interrupt() at the completion
2638 * of any SCSI IO request.
2639 * This routine is registered with the Fusion MPT (base) driver at driver
2640 * load/init time via the mpt_register() API call.
2642 * Returns 1 indicating alloc'd request frame ptr should be freed.
2644 * Remark: Sets a completion code and (possibly) saves sense data
2645 * in the IOC member localReply structure.
2646 * Used ONLY for DV and other internal commands.
2649 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2652 SCSIIORequest_t *pReq;
2656 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2659 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2660 printk(MYIOC_s_ERR_FMT
2661 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2662 ioc->name, mf?"BAD":"NULL", (void *) mf);
2666 del_timer(&hd->timer);
2667 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2668 hd->ScsiLookup[req_idx] = NULL;
2669 pReq = (SCSIIORequest_t *) mf;
2671 if (mf != hd->cmdPtr) {
2672 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2673 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2677 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2678 hd->ioc->name, mf, mr, req_idx));
2680 hd->pLocal = &hd->localReply;
2681 hd->pLocal->scsiStatus = 0;
2683 /* If target struct exists, clear sense valid flag.
2686 completionCode = MPT_SCANDV_GOOD;
2688 SCSIIOReply_t *pReply;
2692 pReply = (SCSIIOReply_t *) mr;
2694 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2695 scsi_status = pReply->SCSIStatus;
2697 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
2698 status, pReply->SCSIState, scsi_status,
2699 le32_to_cpu(pReply->IOCLogInfo)));
2703 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2704 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
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 completionCode = MPT_SCANDV_DID_RESET;
2714 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2715 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2716 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2717 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2718 ConfigReply_t *pr = (ConfigReply_t *)mr;
2719 completionCode = MPT_SCANDV_GOOD;
2720 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2721 hd->pLocal->header.PageLength = pr->Header.PageLength;
2722 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2723 hd->pLocal->header.PageType = pr->Header.PageType;
2725 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2726 /* If the RAID Volume request is successful,
2727 * return GOOD, else indicate that
2728 * some type of error occurred.
2730 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2731 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2732 completionCode = MPT_SCANDV_GOOD;
2734 completionCode = MPT_SCANDV_SOME_ERROR;
2735 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2737 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2741 /* save sense data in global structure
2743 completionCode = MPT_SCANDV_SENSE;
2744 hd->pLocal->scsiStatus = scsi_status;
2745 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2746 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2748 sz = min_t(int, pReq->SenseBufferLength,
2749 SCSI_STD_SENSE_BYTES);
2750 memcpy(hd->pLocal->sense, sense_data, sz);
2752 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
2754 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2755 if (pReq->CDB[0] == INQUIRY)
2756 completionCode = MPT_SCANDV_ISSUE_SENSE;
2758 completionCode = MPT_SCANDV_DID_RESET;
2760 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2761 completionCode = MPT_SCANDV_DID_RESET;
2762 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2763 completionCode = MPT_SCANDV_DID_RESET;
2765 completionCode = MPT_SCANDV_GOOD;
2766 hd->pLocal->scsiStatus = scsi_status;
2770 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2771 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2772 completionCode = MPT_SCANDV_DID_RESET;
2774 completionCode = MPT_SCANDV_SOME_ERROR;
2778 completionCode = MPT_SCANDV_SOME_ERROR;
2781 } /* switch(status) */
2783 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
2785 } /* end of address reply case */
2787 hd->pLocal->completion = completionCode;
2789 /* MF and RF are freed in mpt_interrupt
2792 /* Free Chain buffers (will never chain) in scan or dv */
2793 //mptscsih_freeChainBuffers(ioc, req_idx);
2796 * Wake up the original calling thread
2798 hd->scandv_wait_done = 1;
2799 wake_up(&hd->scandv_waitq);
2804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2805 /* mptscsih_timer_expired - Call back for timer process.
2806 * Used only for dv functionality.
2807 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2811 mptscsih_timer_expired(unsigned long data)
2813 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2815 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2818 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2820 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2821 /* Desire to issue a task management request here.
2822 * TM requests MUST be single threaded.
2823 * If old eh code and no TM current, issue request.
2824 * If new eh code, do nothing. Wait for OS cmd timeout
2827 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
2829 /* Perform a FW reload */
2830 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2831 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2835 /* This should NEVER happen */
2836 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2839 /* No more processing.
2840 * TM call will generate an interrupt for SCSI TM Management.
2841 * The FW will reply to all outstanding commands, callback will finish cleanup.
2842 * Hard reset clean-up will free all resources.
2844 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
2850 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2852 * mptscsih_do_cmd - Do internal command.
2853 * @hd: MPT_SCSI_HOST pointer
2854 * @io: INTERNAL_CMD pointer.
2856 * Issue the specified internally generated command and do command
2857 * specific cleanup. For bus scan / DV only.
2858 * NOTES: If command is Inquiry and status is good,
2859 * initialize a target structure, save the data
2861 * Remark: Single threaded access only.
2864 * < 0 if an illegal command or no resources
2868 * > 0 if command complete but some type of completion error.
2871 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2874 SCSIIORequest_t *pScsiReq;
2875 SCSIIORequest_t ReqCopy;
2876 int my_idx, ii, dir;
2880 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2883 in_isr = in_interrupt();
2885 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2891 /* Set command specific information
2896 dir = MPI_SCSIIO_CONTROL_READ;
2902 case TEST_UNIT_READY:
2904 dir = MPI_SCSIIO_CONTROL_READ;
2910 dir = MPI_SCSIIO_CONTROL_READ;
2912 CDB[4] = 1; /*Spin up the disk */
2920 dir = MPI_SCSIIO_CONTROL_READ;
2926 dir = MPI_SCSIIO_CONTROL_READ;
2928 if (io->flags & MPT_ICFLAG_ECHO) {
2934 if (io->flags & MPT_ICFLAG_BUF_CAP) {
2937 CDB[6] = (io->size >> 16) & 0xFF;
2938 CDB[7] = (io->size >> 8) & 0xFF;
2939 CDB[8] = io->size & 0xFF;
2945 dir = MPI_SCSIIO_CONTROL_WRITE;
2947 if (io->flags & MPT_ICFLAG_ECHO) {
2952 CDB[6] = (io->size >> 16) & 0xFF;
2953 CDB[7] = (io->size >> 8) & 0xFF;
2954 CDB[8] = io->size & 0xFF;
2960 dir = MPI_SCSIIO_CONTROL_READ;
2967 dir = MPI_SCSIIO_CONTROL_READ;
2972 case SYNCHRONIZE_CACHE:
2974 dir = MPI_SCSIIO_CONTROL_READ;
2976 // CDB[1] = 0x02; /* set immediate bit */
2985 /* Get and Populate a free Frame
2987 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
2988 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
2993 pScsiReq = (SCSIIORequest_t *) mf;
2995 /* Get the request index */
2996 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2997 ADD_INDEX_LOG(my_idx); /* for debug */
2999 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3000 pScsiReq->TargetID = io->physDiskNum;
3002 pScsiReq->ChainOffset = 0;
3003 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3005 pScsiReq->TargetID = io->id;
3006 pScsiReq->Bus = io->channel;
3007 pScsiReq->ChainOffset = 0;
3008 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3011 pScsiReq->CDBLength = cmdLen;
3012 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3014 pScsiReq->Reserved = 0;
3016 pScsiReq->MsgFlags = mpt_msg_flags();
3017 /* MsgContext set in mpt_get_msg_fram call */
3019 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3021 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3022 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3024 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3026 if (cmd == REQUEST_SENSE) {
3027 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3028 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3029 hd->ioc->name, cmd));
3032 for (ii=0; ii < 16; ii++)
3033 pScsiReq->CDB[ii] = CDB[ii];
3035 pScsiReq->DataLength = cpu_to_le32(io->size);
3036 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3037 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3039 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3040 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3042 if (dir == MPI_SCSIIO_CONTROL_READ) {
3043 mpt_add_sge((char *) &pScsiReq->SGL,
3044 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3047 mpt_add_sge((char *) &pScsiReq->SGL,
3048 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3052 /* The ISR will free the request frame, but we need
3053 * the information to initialize the target. Duplicate.
3055 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3057 /* Issue this command after:
3060 * Wait until the reply has been received
3061 * ScsiScanDvCtx callback function will
3063 * set scandv_wait_done and call wake_up
3066 hd->timer.expires = jiffies + HZ*cmdTimeout;
3067 hd->scandv_wait_done = 0;
3069 /* Save cmd pointer, for resource free if timeout or
3074 add_timer(&hd->timer);
3075 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3076 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3079 rc = hd->pLocal->completion;
3080 hd->pLocal->skip = 0;
3082 /* Always set fatal error codes in some cases.
3084 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3086 else if (rc == MPT_SCANDV_SOME_ERROR)
3090 /* This should never happen. */
3091 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3098 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3100 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3101 * @hd: Pointer to a SCSI HOST structure
3102 * @vdevice: virtual target device
3104 * Uses the ISR, but with special processing.
3105 * MUST be single-threaded.
3109 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3113 /* Following parameters will not change
3116 iocmd.cmd = SYNCHRONIZE_CACHE;
3118 iocmd.physDiskNum = -1;
3120 iocmd.data_dma = -1;
3122 iocmd.rsvd = iocmd.rsvd2 = 0;
3123 iocmd.channel = vdevice->vtarget->channel;
3124 iocmd.id = vdevice->vtarget->id;
3125 iocmd.lun = vdevice->lun;
3127 if ((vdevice->vtarget->type == TYPE_DISK) &&
3128 (vdevice->configured_lun))
3129 mptscsih_do_cmd(hd, &iocmd);
3132 EXPORT_SYMBOL(mptscsih_remove);
3133 EXPORT_SYMBOL(mptscsih_shutdown);
3135 EXPORT_SYMBOL(mptscsih_suspend);
3136 EXPORT_SYMBOL(mptscsih_resume);
3138 EXPORT_SYMBOL(mptscsih_proc_info);
3139 EXPORT_SYMBOL(mptscsih_info);
3140 EXPORT_SYMBOL(mptscsih_qcmd);
3141 EXPORT_SYMBOL(mptscsih_slave_destroy);
3142 EXPORT_SYMBOL(mptscsih_slave_configure);
3143 EXPORT_SYMBOL(mptscsih_abort);
3144 EXPORT_SYMBOL(mptscsih_dev_reset);
3145 EXPORT_SYMBOL(mptscsih_bus_reset);
3146 EXPORT_SYMBOL(mptscsih_host_reset);
3147 EXPORT_SYMBOL(mptscsih_bios_param);
3148 EXPORT_SYMBOL(mptscsih_io_done);
3149 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3150 EXPORT_SYMBOL(mptscsih_scandv_complete);
3151 EXPORT_SYMBOL(mptscsih_event_process);
3152 EXPORT_SYMBOL(mptscsih_ioc_reset);
3153 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3154 EXPORT_SYMBOL(mptscsih_timer_expired);
3155 EXPORT_SYMBOL(mptscsih_TMHandler);
3157 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/