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@lsil.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/sched.h>
58 #include <linux/workqueue.h>
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65 #include <scsi/scsi_dbg.h>
69 #include "lsi/mpi_log_sas.h"
71 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
72 #define my_NAME "Fusion MPT SCSI Host driver"
73 #define my_VERSION MPT_LINUX_VERSION_COMMON
74 #define MYNAM "mptscsih"
76 MODULE_AUTHOR(MODULEAUTHOR);
77 MODULE_DESCRIPTION(my_NAME);
78 MODULE_LICENSE("GPL");
79 MODULE_VERSION(my_VERSION);
81 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
83 * Other private/forward protos...
85 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
86 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
87 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
89 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
90 SCSIIORequest_t *pReq, int req_idx);
91 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
92 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
93 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
94 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
95 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
97 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
99 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
100 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
102 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
103 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, struct scsi_device *sdev);
104 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id);
105 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
106 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
107 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
109 void mptscsih_remove(struct pci_dev *);
110 void mptscsih_shutdown(struct pci_dev *);
112 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
113 int mptscsih_resume(struct pci_dev *pdev);
116 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
118 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
120 * mptscsih_add_sge - Place a simple SGE at address pAddr.
121 * @pAddr: virtual address for SGE
122 * @flagslength: SGE flags and data transfer length
123 * @dma_addr: Physical address
125 * This routine places a MPT request frame back on the MPT adapter's
129 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
131 if (sizeof(dma_addr_t) == sizeof(u64)) {
132 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
133 u32 tmp = dma_addr & 0xFFFFFFFF;
135 pSge->FlagsLength = cpu_to_le32(flagslength);
136 pSge->Address.Low = cpu_to_le32(tmp);
137 tmp = (u32) ((u64)dma_addr >> 32);
138 pSge->Address.High = cpu_to_le32(tmp);
141 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
142 pSge->FlagsLength = cpu_to_le32(flagslength);
143 pSge->Address = cpu_to_le32(dma_addr);
145 } /* mptscsih_add_sge() */
147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
149 * mptscsih_add_chain - Place a chain SGE at address pAddr.
150 * @pAddr: virtual address for SGE
151 * @next: nextChainOffset value (u32's)
152 * @length: length of next SGL segment
153 * @dma_addr: Physical address
155 * This routine places a MPT request frame back on the MPT adapter's
159 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
161 if (sizeof(dma_addr_t) == sizeof(u64)) {
162 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
163 u32 tmp = dma_addr & 0xFFFFFFFF;
165 pChain->Length = cpu_to_le16(length);
166 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
168 pChain->NextChainOffset = next;
170 pChain->Address.Low = cpu_to_le32(tmp);
171 tmp = (u32) ((u64)dma_addr >> 32);
172 pChain->Address.High = cpu_to_le32(tmp);
174 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
175 pChain->Length = cpu_to_le16(length);
176 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
177 pChain->NextChainOffset = next;
178 pChain->Address = cpu_to_le32(dma_addr);
180 } /* mptscsih_add_chain() */
182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
184 * mptscsih_getFreeChainBuffer - Function to get a free chain
185 * from the MPT_SCSI_HOST FreeChainQ.
186 * @ioc: Pointer to MPT_ADAPTER structure
187 * @req_idx: Index of the SCSI IO request frame. (output)
189 * return SUCCESS or FAILED
192 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
194 MPT_FRAME_HDR *chainBuf;
199 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
201 spin_lock_irqsave(&ioc->FreeQlock, flags);
202 if (!list_empty(&ioc->FreeChainQ)) {
205 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
206 u.frame.linkage.list);
207 list_del(&chainBuf->u.frame.linkage.list);
208 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
209 chain_idx = offset / ioc->req_sz;
211 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
212 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
215 chain_idx = MPT_HOST_NO_CHAIN;
216 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
219 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
221 *retIndex = chain_idx;
223 } /* mptscsih_getFreeChainBuffer() */
225 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
227 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
228 * SCSIIORequest_t Message Frame.
229 * @ioc: Pointer to MPT_ADAPTER structure
230 * @SCpnt: Pointer to scsi_cmnd structure
231 * @pReq: Pointer to SCSIIORequest_t structure
236 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
237 SCSIIORequest_t *pReq, int req_idx)
241 struct scatterlist *sg;
243 int sges_left, sg_done;
244 int chain_idx = MPT_HOST_NO_CHAIN;
246 int numSgeSlots, numSgeThisFrame;
247 u32 sgflags, sgdir, thisxfer = 0;
248 int chain_dma_off = 0;
254 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
255 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
256 sgdir = MPT_TRANSFER_HOST_TO_IOC;
258 sgdir = MPT_TRANSFER_IOC_TO_HOST;
261 psge = (char *) &pReq->SGL;
262 frm_sz = ioc->req_sz;
264 /* Map the data portion, if any.
265 * sges_left = 0 if no data transfer.
267 if ( (sges_left = SCpnt->use_sg) ) {
268 sges_left = pci_map_sg(ioc->pcidev,
269 (struct scatterlist *) SCpnt->request_buffer,
271 SCpnt->sc_data_direction);
274 } else if (SCpnt->request_bufflen) {
275 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
276 SCpnt->request_buffer,
277 SCpnt->request_bufflen,
278 SCpnt->sc_data_direction);
279 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
280 ioc->name, SCpnt, SCpnt->request_bufflen));
281 mptscsih_add_sge((char *) &pReq->SGL,
282 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
283 SCpnt->SCp.dma_handle);
288 /* Handle the SG case.
290 sg = (struct scatterlist *) SCpnt->request_buffer;
292 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
295 /* Prior to entering this loop - the following must be set
296 * current MF: sgeOffset (bytes)
297 * chainSge (Null if original MF is not a chain buffer)
298 * sg_done (num SGE done for this MF)
302 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
303 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
305 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
307 /* Get first (num - 1) SG elements
308 * Skip any SG entries with a length of 0
309 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
311 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
312 thisxfer = sg_dma_len(sg);
314 sg ++; /* Get next SG element from the OS */
319 v2 = sg_dma_address(sg);
320 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
322 sg++; /* Get next SG element from the OS */
323 psge += (sizeof(u32) + sizeof(dma_addr_t));
324 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
328 if (numSgeThisFrame == sges_left) {
329 /* Add last element, end of buffer and end of list flags.
331 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
332 MPT_SGE_FLAGS_END_OF_BUFFER |
333 MPT_SGE_FLAGS_END_OF_LIST;
335 /* Add last SGE and set termination flags.
336 * Note: Last SGE may have a length of 0 - which should be ok.
338 thisxfer = sg_dma_len(sg);
340 v2 = sg_dma_address(sg);
341 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
344 psge += (sizeof(u32) + sizeof(dma_addr_t));
346 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
350 /* The current buffer is a chain buffer,
351 * but there is not another one.
352 * Update the chain element
353 * Offset and Length fields.
355 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
357 /* The current buffer is the original MF
358 * and there is no Chain buffer.
360 pReq->ChainOffset = 0;
361 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
362 dsgprintk((MYIOC_s_INFO_FMT
363 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
364 ioc->RequestNB[req_idx] = RequestNB;
367 /* At least one chain buffer is needed.
368 * Complete the first MF
369 * - last SGE element, set the LastElement bit
370 * - set ChainOffset (words) for orig MF
371 * (OR finish previous MF chain buffer)
372 * - update MFStructPtr ChainIndex
373 * - Populate chain element
378 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
379 ioc->name, sg_done));
381 /* Set LAST_ELEMENT flag for last non-chain element
382 * in the buffer. Since psge points at the NEXT
383 * SGE element, go back one SGE element, update the flags
384 * and reset the pointer. (Note: sgflags & thisxfer are already
388 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
389 sgflags = le32_to_cpu(*ptmp);
390 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
391 *ptmp = cpu_to_le32(sgflags);
395 /* The current buffer is a chain buffer.
396 * chainSge points to the previous Chain Element.
397 * Update its chain element Offset and Length (must
398 * include chain element size) fields.
399 * Old chain element is now complete.
401 u8 nextChain = (u8) (sgeOffset >> 2);
402 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
403 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
405 /* The original MF buffer requires a chain buffer -
407 * Last element in this MF is a chain element.
409 pReq->ChainOffset = (u8) (sgeOffset >> 2);
410 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
411 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
412 ioc->RequestNB[req_idx] = RequestNB;
415 sges_left -= sg_done;
418 /* NOTE: psge points to the beginning of the chain element
419 * in current buffer. Get a chain buffer.
421 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
422 dfailprintk((MYIOC_s_INFO_FMT
423 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
424 ioc->name, pReq->CDB[0], SCpnt));
428 /* Update the tracking arrays.
429 * If chainSge == NULL, update ReqToChain, else ChainToChain
432 ioc->ChainToChain[chain_idx] = newIndex;
434 ioc->ReqToChain[req_idx] = newIndex;
436 chain_idx = newIndex;
437 chain_dma_off = ioc->req_sz * chain_idx;
439 /* Populate the chainSGE for the current buffer.
440 * - Set chain buffer pointer to psge and fill
441 * out the Address and Flags fields.
443 chainSge = (char *) psge;
444 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
447 /* Start the SGE for the next buffer
449 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
453 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
456 /* Start the SGE for the next buffer
463 } /* mptscsih_AddSGE() */
466 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
470 SEPRequest_t *SEPMsg;
472 if (ioc->bus_type == FC)
475 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
476 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
477 ioc->name,__FUNCTION__));
481 SEPMsg = (SEPRequest_t *)mf;
482 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
483 SEPMsg->Bus = vtarget->channel;
484 SEPMsg->TargetID = vtarget->id;
485 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
486 SEPMsg->SlotStatus = SlotStatus;
487 devtverboseprintk((MYIOC_s_WARN_FMT
488 "Sending SEP cmd=%x channel=%d id=%d\n",
489 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
490 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
495 * mptscsih_io_done - Main SCSI IO callback routine registered to
496 * Fusion MPT (base) driver
497 * @ioc: Pointer to MPT_ADAPTER structure
498 * @mf: Pointer to original MPT request frame
499 * @r: Pointer to MPT reply frame (NULL if TurboReply)
501 * This routine is called from mpt.c::mpt_interrupt() at the completion
502 * of any SCSI IO request.
503 * This routine is registered with the Fusion MPT (base) driver at driver
504 * load/init time via the mpt_register() API call.
506 * Returns 1 indicating alloc'd request frame ptr should be freed.
509 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
511 struct scsi_cmnd *sc;
513 SCSIIORequest_t *pScsiReq;
514 SCSIIOReply_t *pScsiReply;
515 u16 req_idx, req_idx_MR;
519 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
521 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
522 req_idx_MR = (mr != NULL) ?
523 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
524 if ((req_idx != req_idx_MR) ||
525 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
526 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
528 printk (MYIOC_s_ERR_FMT
529 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
530 ioc->name, req_idx, req_idx_MR, mf, mr,
531 hd->ScsiLookup[req_idx_MR]);
535 sc = hd->ScsiLookup[req_idx];
536 hd->ScsiLookup[req_idx] = NULL;
538 MPIHeader_t *hdr = (MPIHeader_t *)mf;
540 /* Remark: writeSDP1 will use the ScsiDoneCtx
541 * If a SCSI I/O cmd, device disabled by OS and
542 * completion done. Cannot touch sc struct. Just free mem.
544 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
545 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
548 mptscsih_freeChainBuffers(ioc, req_idx);
552 if ((unsigned char *)mf != sc->host_scribble) {
553 mptscsih_freeChainBuffers(ioc, req_idx);
557 sc->host_scribble = NULL;
558 sc->result = DID_OK << 16; /* Set default reply as OK */
559 pScsiReq = (SCSIIORequest_t *) mf;
560 pScsiReply = (SCSIIOReply_t *) mr;
562 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
563 dmfprintk((MYIOC_s_INFO_FMT
564 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
565 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
567 dmfprintk((MYIOC_s_INFO_FMT
568 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
569 ioc->name, mf, mr, sc, req_idx));
572 if (pScsiReply == NULL) {
573 /* special context reply handling */
578 u8 scsi_state, scsi_status;
580 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
581 scsi_state = pScsiReply->SCSIState;
582 scsi_status = pScsiReply->SCSIStatus;
583 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
584 sc->resid = sc->request_bufflen - xfer_cnt;
587 * if we get a data underrun indication, yet no data was
588 * transferred and the SCSI status indicates that the
589 * command was never started, change the data underrun
592 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
593 (scsi_status == MPI_SCSI_STATUS_BUSY ||
594 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
595 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
596 status = MPI_IOCSTATUS_SUCCESS;
599 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
600 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
601 "resid=%d bufflen=%d xfer_cnt=%d\n",
602 ioc->id, sc->device->id, sc->device->lun,
603 status, scsi_state, scsi_status, sc->resid,
604 sc->request_bufflen, xfer_cnt));
606 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
607 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
610 * Look for + dump FCP ResponseInfo[]!
612 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
613 pScsiReply->ResponseInfo) {
614 printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
615 "FCP_ResponseInfo=%08xh\n",
616 ioc->id, sc->device->id, sc->device->lun,
617 le32_to_cpu(pScsiReply->ResponseInfo));
621 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
623 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
624 * But not: DID_BUS_BUSY lest one risk
625 * killing interrupt handler:-(
627 sc->result = SAM_STAT_BUSY;
630 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
631 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
632 sc->result = DID_BAD_TARGET << 16;
635 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
636 /* Spoof to SCSI Selection Timeout! */
637 if (ioc->bus_type != FC)
638 sc->result = DID_NO_CONNECT << 16;
639 /* else fibre, just stall until rescan event */
641 sc->result = DID_REQUEUE << 16;
643 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
644 hd->sel_timeout[pScsiReq->TargetID]++;
646 vdev = sc->device->hostdata;
649 vtarget = vdev->vtarget;
650 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
651 mptscsih_issue_sep_command(ioc, vtarget,
652 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
653 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
657 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
658 if ( ioc->bus_type == SAS ) {
659 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
660 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
661 u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
662 log_info &=SAS_LOGINFO_MASK;
663 if (log_info == SAS_LOGINFO_NEXUS_LOSS) {
664 sc->result = (DID_BUS_BUSY << 16);
668 } else if (ioc->bus_type == FC) {
670 * The FC IOC may kill a request for variety of
671 * reasons, some of which may be recovered by a
672 * retry, some which are unlikely to be
673 * recovered. Return DID_ERROR instead of
674 * DID_RESET to permit retry of the command,
675 * just not an infinite number of them
677 sc->result = DID_ERROR << 16;
682 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
685 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
686 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
687 /* Linux handles an unsolicited DID_RESET better
688 * than an unsolicited DID_ABORT.
690 sc->result = DID_RESET << 16;
694 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
695 sc->resid = sc->request_bufflen - xfer_cnt;
696 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
697 sc->result=DID_SOFT_ERROR << 16;
698 else /* Sufficient data transfer occurred */
699 sc->result = (DID_OK << 16) | scsi_status;
700 dreplyprintk((KERN_NOTICE
701 "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id));
704 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
706 * Do upfront check for valid SenseData and give it
709 sc->result = (DID_OK << 16) | scsi_status;
710 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
711 /* Have already saved the status and sense data
715 if (xfer_cnt < sc->underflow) {
716 if (scsi_status == SAM_STAT_BUSY)
717 sc->result = SAM_STAT_BUSY;
719 sc->result = DID_SOFT_ERROR << 16;
721 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
724 sc->result = DID_SOFT_ERROR << 16;
726 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
727 /* Not real sure here either... */
728 sc->result = DID_RESET << 16;
732 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
734 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
737 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
738 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
742 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
744 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
745 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
746 if (scsi_status == MPI_SCSI_STATUS_BUSY)
747 sc->result = (DID_BUS_BUSY << 16) | scsi_status;
749 sc->result = (DID_OK << 16) | scsi_status;
750 if (scsi_state == 0) {
752 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
754 * If running against circa 200003dd 909 MPT f/w,
755 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
756 * (QUEUE_FULL) returned from device! --> get 0x0000?128
757 * and with SenseBytes set to 0.
759 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
760 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
763 else if (scsi_state &
764 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
769 sc->result = DID_SOFT_ERROR << 16;
771 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
772 /* Not real sure here either... */
773 sc->result = DID_RESET << 16;
775 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
776 /* Device Inq. data indicates that it supports
777 * QTags, but rejects QTag messages.
778 * This command completed OK.
780 * Not real sure here either so do nothing... */
783 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
784 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
787 * Reservation Conflict, Busy,
788 * Command Terminated, CHECK
792 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
793 sc->result = DID_SOFT_ERROR << 16;
796 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
797 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
798 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
799 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
800 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
801 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
802 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
803 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
804 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
809 sc->result = DID_SOFT_ERROR << 16;
812 } /* switch(status) */
814 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
815 } /* end of address reply case */
817 /* Unmap the DMA buffers, if any. */
819 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
820 sc->use_sg, sc->sc_data_direction);
821 } else if (sc->request_bufflen) {
822 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
823 sc->request_bufflen, sc->sc_data_direction);
826 sc->scsi_done(sc); /* Issue the command callback */
828 /* Free Chain buffers */
829 mptscsih_freeChainBuffers(ioc, req_idx);
834 * mptscsih_flush_running_cmds - For each command found, search
835 * Scsi_Host instance taskQ and reply to OS.
836 * Called only if recovering from a FW reload.
837 * @hd: Pointer to a SCSI HOST structure
841 * Must be called while new I/Os are being queued.
844 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
846 MPT_ADAPTER *ioc = hd->ioc;
847 struct scsi_cmnd *SCpnt;
850 int max = ioc->req_depth;
852 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
853 for (ii= 0; ii < max; ii++) {
854 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
859 /* Null ScsiLookup index
861 hd->ScsiLookup[ii] = NULL;
863 mf = MPT_INDEX_2_MFPTR(ioc, ii);
864 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
867 /* Free Chain buffers */
868 mptscsih_freeChainBuffers(ioc, ii);
870 /* Free Message frames */
871 mpt_free_msg_frame(ioc, mf);
873 if ((unsigned char *)mf != SCpnt->host_scribble)
876 /* Set status, free OS resources (SG DMA buffers)
880 pci_unmap_sg(ioc->pcidev,
881 (struct scatterlist *) SCpnt->request_buffer,
883 SCpnt->sc_data_direction);
884 } else if (SCpnt->request_bufflen) {
885 pci_unmap_single(ioc->pcidev,
886 SCpnt->SCp.dma_handle,
887 SCpnt->request_bufflen,
888 SCpnt->sc_data_direction);
890 SCpnt->result = DID_RESET << 16;
891 SCpnt->host_scribble = NULL;
893 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
901 * mptscsih_search_running_cmds - Delete any commands associated
902 * with the specified target and lun. Function called only
903 * when a lun is disable by mid-layer.
904 * Do NOT access the referenced scsi_cmnd structure or
905 * members. Will cause either a paging or NULL ptr error.
906 * (BUT, BUT, BUT, the code does reference it! - mdr)
907 * @hd: Pointer to a SCSI HOST structure
908 * @vdevice: per device private data
912 * Called from slave_destroy.
915 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
917 SCSIIORequest_t *mf = NULL;
919 int max = hd->ioc->req_depth;
920 struct scsi_cmnd *sc;
923 dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
924 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
926 for (ii=0; ii < max; ii++) {
927 if ((sc = hd->ScsiLookup[ii]) != NULL) {
929 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
932 int_to_scsilun(vdevice->lun, &lun);
933 if ((mf->Bus != vdevice->vtarget->channel) ||
934 (mf->TargetID != vdevice->vtarget->id) ||
935 memcmp(lun.scsi_lun, mf->LUN, 8))
937 dsprintk(( "search_running: found (sc=%p, mf = %p) "
938 "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
939 mf, mf->Bus, mf->TargetID, vdevice->lun));
943 hd->ScsiLookup[ii] = NULL;
944 mptscsih_freeChainBuffers(hd->ioc, ii);
945 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
946 if ((unsigned char *)mf != sc->host_scribble)
949 pci_unmap_sg(hd->ioc->pcidev,
950 (struct scatterlist *) sc->request_buffer,
952 sc->sc_data_direction);
953 } else if (sc->request_bufflen) {
954 pci_unmap_single(hd->ioc->pcidev,
957 sc->sc_data_direction);
959 sc->host_scribble = NULL;
960 sc->result = DID_NO_CONNECT << 16;
967 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
969 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
971 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
972 * from a SCSI target device.
973 * @sc: Pointer to scsi_cmnd structure
974 * @pScsiReply: Pointer to SCSIIOReply_t
975 * @pScsiReq: Pointer to original SCSI request
977 * This routine periodically reports QUEUE_FULL status returned from a
978 * SCSI target device. It reports this to the console via kernel
979 * printk() API call, not more than once every 10 seconds.
982 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
987 if (sc->device == NULL)
989 if (sc->device->host == NULL)
991 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
994 if (time - hd->last_queue_full > 10 * HZ) {
995 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
996 hd->ioc->name, 0, sc->device->id, sc->device->lun));
997 hd->last_queue_full = time;
1001 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1003 * mptscsih_remove - Removed scsi devices
1004 * @pdev: Pointer to pci_dev structure
1009 mptscsih_remove(struct pci_dev *pdev)
1011 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1012 struct Scsi_Host *host = ioc->sh;
1021 scsi_remove_host(host);
1023 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1026 mptscsih_shutdown(pdev);
1030 if (hd->ScsiLookup != NULL) {
1031 sz1 = hd->ioc->req_depth * sizeof(void *);
1032 kfree(hd->ScsiLookup);
1033 hd->ScsiLookup = NULL;
1036 dprintk((MYIOC_s_INFO_FMT
1037 "Free'd ScsiLookup (%d) memory\n",
1038 hd->ioc->name, sz1));
1040 kfree(hd->info_kbuf);
1042 /* NULL the Scsi_Host pointer
1046 scsi_host_put(host);
1052 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1054 * mptscsih_shutdown - reboot notifier
1058 mptscsih_shutdown(struct pci_dev *pdev)
1060 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1061 struct Scsi_Host *host = ioc->sh;
1067 hd = (MPT_SCSI_HOST *)host->hostdata;
1072 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1074 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1079 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1081 mptscsih_shutdown(pdev);
1082 return mpt_suspend(pdev,state);
1085 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1087 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1092 mptscsih_resume(struct pci_dev *pdev)
1094 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1095 struct Scsi_Host *host = ioc->sh;
1103 hd = (MPT_SCSI_HOST *)host->hostdata;
1112 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1114 * mptscsih_info - Return information about MPT adapter
1115 * @SChost: Pointer to Scsi_Host structure
1117 * (linux scsi_host_template.info routine)
1119 * Returns pointer to buffer where information was written.
1122 mptscsih_info(struct Scsi_Host *SChost)
1127 h = (MPT_SCSI_HOST *)SChost->hostdata;
1130 if (h->info_kbuf == NULL)
1131 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1132 return h->info_kbuf;
1133 h->info_kbuf[0] = '\0';
1135 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1136 h->info_kbuf[size-1] = '\0';
1139 return h->info_kbuf;
1150 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1152 if (info->pos + len > info->length)
1153 len = info->length - info->pos;
1155 if (info->pos + len < info->offset) {
1160 if (info->pos < info->offset) {
1161 data += (info->offset - info->pos);
1162 len -= (info->offset - info->pos);
1166 memcpy(info->buffer + info->pos, data, len);
1172 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1178 va_start(args, fmt);
1179 len = vsprintf(buf, fmt, args);
1182 mptscsih_copy_mem_info(info, buf, len);
1187 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1189 struct info_str info;
1193 info.offset = offset;
1196 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1197 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1198 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1199 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1201 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1204 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1206 * mptscsih_proc_info - Return information about MPT adapter
1207 * @host: scsi host struct
1208 * @buffer: if write, user data; if read, buffer for user
1209 * @start: returns the buffer address
1210 * @offset: if write, 0; if read, the current offset into the buffer from
1211 * the previous read.
1212 * @length: if write, return length;
1213 * @func: write = 1; read = 0
1215 * (linux scsi_host_template.info routine)
1218 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1219 int length, int func)
1221 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1222 MPT_ADAPTER *ioc = hd->ioc;
1227 * write is not supported
1233 size = mptscsih_host_info(ioc, buffer, offset, length);
1239 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1240 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1242 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1244 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1245 * @SCpnt: Pointer to scsi_cmnd structure
1246 * @done: Pointer SCSI mid-layer IO completion function
1248 * (linux scsi_host_template.queuecommand routine)
1249 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1250 * from a linux scsi_cmnd request and send it to the IOC.
1252 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1255 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1259 SCSIIORequest_t *pScsiReq;
1260 VirtDevice *vdev = SCpnt->device->hostdata;
1269 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1270 lun = SCpnt->device->lun;
1271 SCpnt->scsi_done = done;
1273 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1274 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1276 if (hd->resetPending) {
1277 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1278 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1279 return SCSI_MLQUEUE_HOST_BUSY;
1283 * Put together a MPT SCSI request...
1285 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1286 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1288 return SCSI_MLQUEUE_HOST_BUSY;
1291 pScsiReq = (SCSIIORequest_t *) mf;
1293 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1295 ADD_INDEX_LOG(my_idx);
1297 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1298 * Seems we may receive a buffer (datalen>0) even when there
1299 * will be no data transfer! GRRRRR...
1301 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1302 datalen = SCpnt->request_bufflen;
1303 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1304 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1305 datalen = SCpnt->request_bufflen;
1306 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1309 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1312 /* Default to untagged. Once a target structure has been allocated,
1313 * use the Inquiry data to determine if device supports tagged.
1316 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1317 && (SCpnt->device->tagged_supported)) {
1318 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1320 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1323 /* Use the above information to set up the message frame
1325 pScsiReq->TargetID = (u8) vdev->vtarget->id;
1326 pScsiReq->Bus = vdev->vtarget->channel;
1327 pScsiReq->ChainOffset = 0;
1328 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1329 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1331 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1332 pScsiReq->CDBLength = SCpnt->cmd_len;
1333 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1334 pScsiReq->Reserved = 0;
1335 pScsiReq->MsgFlags = mpt_msg_flags();
1336 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1337 pScsiReq->Control = cpu_to_le32(scsictl);
1340 * Write SCSI CDB into the message
1342 cmd_len = SCpnt->cmd_len;
1343 for (ii=0; ii < cmd_len; ii++)
1344 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1346 for (ii=cmd_len; ii < 16; ii++)
1347 pScsiReq->CDB[ii] = 0;
1350 pScsiReq->DataLength = cpu_to_le32(datalen);
1352 /* SenseBuffer low address */
1353 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1354 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1356 /* Now add the SG list
1357 * Always have a SGE even if null length.
1360 /* Add a NULL SGE */
1361 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1364 /* Add a 32 or 64 bit SGE */
1365 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1369 SCpnt->host_scribble = (unsigned char *)mf;
1370 hd->ScsiLookup[my_idx] = SCpnt;
1372 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1373 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1374 hd->ioc->name, SCpnt, mf, my_idx));
1375 DBG_DUMP_REQUEST_FRAME(mf)
1379 hd->ScsiLookup[my_idx] = NULL;
1380 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1381 mpt_free_msg_frame(hd->ioc, mf);
1382 return SCSI_MLQUEUE_HOST_BUSY;
1385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1387 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1388 * with a SCSI IO request
1389 * @hd: Pointer to the MPT_SCSI_HOST instance
1390 * @req_idx: Index of the SCSI IO request frame.
1392 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1396 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1398 MPT_FRAME_HDR *chain;
1399 unsigned long flags;
1403 /* Get the first chain index and reset
1406 chain_idx = ioc->ReqToChain[req_idx];
1407 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1409 while (chain_idx != MPT_HOST_NO_CHAIN) {
1411 /* Save the next chain buffer index */
1412 next = ioc->ChainToChain[chain_idx];
1414 /* Free this chain buffer and reset
1417 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1419 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1420 + (chain_idx * ioc->req_sz));
1422 spin_lock_irqsave(&ioc->FreeQlock, flags);
1423 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1424 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1426 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1427 ioc->name, chain_idx));
1435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1442 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1443 * Fall through to mpt_HardResetHandler if: not operational, too many
1444 * failed TM requests or handshake failure.
1446 * @ioc: Pointer to MPT_ADAPTER structure
1447 * @type: Task Management type
1448 * @id: Logical Target ID for reset (if appropriate)
1449 * @lun: Logical Unit for reset (if appropriate)
1450 * @ctx2abort: Context for the task to be aborted (if appropriate)
1452 * Remark: Currently invoked from a non-interrupt thread (_bh).
1454 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1457 * Returns 0 for SUCCESS or -1 if FAILED.
1460 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1466 unsigned long flags;
1468 /* If FW is being reloaded currently, return success to
1469 * the calling function.
1476 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1479 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1481 // SJR - CHECKME - Can we avoid this here?
1482 // (mpt_HardResetHandler has this check...)
1483 spin_lock_irqsave(&ioc->diagLock, flags);
1484 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1485 spin_unlock_irqrestore(&ioc->diagLock, flags);
1488 spin_unlock_irqrestore(&ioc->diagLock, flags);
1490 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1491 * If we time out and not bus reset, then we return a FAILED status to the caller.
1492 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1493 * successful. Otherwise, reload the FW.
1495 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1496 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1497 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1498 "Timed out waiting for last TM (%d) to complete! \n",
1499 hd->ioc->name, hd->tmPending));
1501 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1502 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1503 "Timed out waiting for last TM (%d) to complete! \n",
1504 hd->ioc->name, hd->tmPending));
1506 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1507 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1508 "Timed out waiting for last TM (%d) to complete! \n",
1509 hd->ioc->name, hd->tmPending));
1510 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1516 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1517 hd->tmPending |= (1 << type);
1518 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1523 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1525 #ifdef MPT_DEBUG_RESET
1526 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1527 printk(MYIOC_s_WARN_FMT
1528 "TM Handler: IOC Not operational(0x%x)!\n",
1529 hd->ioc->name, ioc_raw_state);
1533 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1534 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1536 /* Isse the Task Mgmt request.
1538 if (hd->hard_resets < -1)
1540 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout);
1542 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1544 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1548 /* Only fall through to the HRH if this is a bus reset
1550 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1551 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1552 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1554 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1558 * Check IOCStatus from TM reply message
1560 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
1563 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1569 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1571 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1572 * @hd: Pointer to MPT_SCSI_HOST structure
1573 * @type: Task Management type
1574 * @id: Logical Target ID for reset (if appropriate)
1575 * @lun: Logical Unit for reset (if appropriate)
1576 * @ctx2abort: Context for the task to be aborted (if appropriate)
1578 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1579 * or a non-interrupt thread. In the former, must not call schedule().
1581 * Not all fields are meaningfull for all task types.
1583 * Returns 0 for SUCCESS, -999 for "no msg frames",
1584 * else other non-zero value returned.
1587 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1590 SCSITaskMgmt_t *pScsiTm;
1594 /* Return Fail to calling function if no message frames available.
1596 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1597 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1601 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1602 hd->ioc->name, mf));
1604 /* Format the Request
1606 pScsiTm = (SCSITaskMgmt_t *) mf;
1607 pScsiTm->TargetID = id;
1608 pScsiTm->Bus = channel;
1609 pScsiTm->ChainOffset = 0;
1610 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1612 pScsiTm->Reserved = 0;
1613 pScsiTm->TaskType = type;
1614 pScsiTm->Reserved1 = 0;
1615 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1616 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1618 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1620 for (ii=0; ii < 7; ii++)
1621 pScsiTm->Reserved2[ii] = 0;
1623 pScsiTm->TaskMsgContext = ctx2abort;
1625 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1626 hd->ioc->name, ctx2abort, type));
1628 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1630 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1631 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1633 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1634 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1636 mpt_free_msg_frame(hd->ioc, mf);
1640 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1641 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1642 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1644 mpt_free_msg_frame(hd->ioc, mf);
1645 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1647 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1654 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1656 switch (ioc->bus_type) {
1667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1669 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1670 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1672 * (linux scsi_host_template.eh_abort_handler routine)
1674 * Returns SUCCESS or FAILED.
1677 mptscsih_abort(struct scsi_cmnd * SCpnt)
1685 ulong sn = SCpnt->serial_number;
1687 /* If we can't locate our host adapter structure, return FAILED status.
1689 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1690 SCpnt->result = DID_RESET << 16;
1691 SCpnt->scsi_done(SCpnt);
1692 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1693 "Can't locate host! (sc=%p)\n",
1698 /* Find this command
1700 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1701 /* Cmd not found in ScsiLookup.
1704 SCpnt->result = DID_RESET << 16;
1705 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1706 "Command not in the active list! (sc=%p)\n",
1707 hd->ioc->name, SCpnt));
1711 if (hd->resetPending) {
1715 if (hd->timeouts < -1)
1718 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1719 hd->ioc->name, SCpnt);
1720 scsi_print_command(SCpnt);
1722 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1723 * (the IO to be ABORT'd)
1725 * NOTE: Since we do not byteswap MsgContext, we do not
1726 * swap it here either. It is an opaque cookie to
1727 * the controller, so it does not matter. -DaveM
1729 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1730 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1732 hd->abortSCpnt = SCpnt;
1734 vdev = SCpnt->device->hostdata;
1735 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1736 vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
1737 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1739 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1740 SCpnt->serial_number == sn) {
1744 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1746 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1751 if(retval != FAILED ) {
1753 hd->tmState = TM_STATE_NONE;
1758 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1760 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1761 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1763 * (linux scsi_host_template.eh_dev_reset_handler routine)
1765 * Returns SUCCESS or FAILED.
1768 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1774 /* If we can't locate our host adapter structure, return FAILED status.
1776 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1777 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1778 "Can't locate host! (sc=%p)\n",
1783 if (hd->resetPending)
1786 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1787 hd->ioc->name, SCpnt);
1788 scsi_print_command(SCpnt);
1790 vdev = SCpnt->device->hostdata;
1791 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1792 vdev->vtarget->channel, vdev->vtarget->id,
1793 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1795 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1797 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1802 if(retval != FAILED ) {
1804 hd->tmState = TM_STATE_NONE;
1809 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1811 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1812 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1814 * (linux scsi_host_template.eh_bus_reset_handler routine)
1816 * Returns SUCCESS or FAILED.
1819 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1825 /* If we can't locate our host adapter structure, return FAILED status.
1827 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1828 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1829 "Can't locate host! (sc=%p)\n",
1834 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1835 hd->ioc->name, SCpnt);
1836 scsi_print_command(SCpnt);
1838 if (hd->timeouts < -1)
1841 vdev = SCpnt->device->hostdata;
1842 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1843 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1845 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1847 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1852 if(retval != FAILED ) {
1854 hd->tmState = TM_STATE_NONE;
1859 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1861 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1862 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1864 * (linux scsi_host_template.eh_host_reset_handler routine)
1866 * Returns SUCCESS or FAILED.
1869 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1872 int status = SUCCESS;
1874 /* If we can't locate the host to reset, then we failed. */
1875 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1876 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1877 "Can't locate host! (sc=%p)\n",
1882 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1883 hd->ioc->name, SCpnt);
1885 /* If our attempts to reset the host failed, then return a failed
1886 * status. The host will be taken off line by the SCSI mid-layer.
1888 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1891 /* Make sure TM pending is cleared and TM state is set to
1895 hd->tmState = TM_STATE_NONE;
1898 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1900 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1905 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1907 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1908 * @hd: Pointer to MPT host structure.
1910 * Returns {SUCCESS,FAILED}.
1913 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1915 unsigned long flags;
1916 int loop_count = 4 * 10; /* Wait 10 seconds */
1917 int status = FAILED;
1920 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1921 if (hd->tmState == TM_STATE_NONE) {
1922 hd->tmState = TM_STATE_IN_PROGRESS;
1924 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1928 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1930 } while (--loop_count);
1935 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1937 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1938 * @hd: Pointer to MPT host structure.
1939 * @timeout: timeout in seconds
1941 * Returns {SUCCESS,FAILED}.
1944 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1946 unsigned long flags;
1947 int loop_count = 4 * timeout;
1948 int status = FAILED;
1951 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1952 if(hd->tmPending == 0) {
1954 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1957 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1959 } while (--loop_count);
1964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1966 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
1970 switch (response_code) {
1971 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
1972 desc = "The task completed.";
1974 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
1975 desc = "The IOC received an invalid frame status.";
1977 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
1978 desc = "The task type is not supported.";
1980 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
1981 desc = "The requested task failed.";
1983 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
1984 desc = "The task completed successfully.";
1986 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
1987 desc = "The LUN request is invalid.";
1989 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
1990 desc = "The task is in the IOC queue and has not been sent to target.";
1996 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
1997 ioc->name, response_code, desc);
2000 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2002 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2003 * @ioc: Pointer to MPT_ADAPTER structure
2004 * @mf: Pointer to SCSI task mgmt request frame
2005 * @mr: Pointer to SCSI task mgmt reply frame
2007 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2008 * of any SCSI task management request.
2009 * This routine is registered with the MPT (base) driver at driver
2010 * load/init time via the mpt_register() API call.
2012 * Returns 1 indicating alloc'd request frame ptr should be freed.
2015 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2017 SCSITaskMgmtReply_t *pScsiTmReply;
2018 SCSITaskMgmt_t *pScsiTmReq;
2020 unsigned long flags;
2024 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2025 ioc->name, mf, mr));
2027 /* Depending on the thread, a timer is activated for
2028 * the TM request. Delete this timer on completion of TM.
2029 * Decrement count of outstanding TM requests.
2031 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2033 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2039 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2043 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2044 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2046 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2047 tmType = pScsiTmReq->TaskType;
2049 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2050 pScsiTmReply->ResponseCode)
2051 mptscsih_taskmgmt_response_code(ioc,
2052 pScsiTmReply->ResponseCode);
2054 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2055 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2056 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2058 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2059 hd->tm_iocstatus = iocstatus;
2060 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2061 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2062 /* Error? (anything non-zero?) */
2065 /* clear flags and continue.
2067 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2068 hd->abortSCpnt = NULL;
2070 /* If an internal command is present
2071 * or the TM failed - reload the FW.
2072 * FC FW may respond FAILED to an ABORT
2074 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2076 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2077 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2078 printk((KERN_WARNING
2079 " Firmware Reload FAILED!!\n"));
2084 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2086 hd->abortSCpnt = NULL;
2091 spin_lock_irqsave(&ioc->FreeQlock, flags);
2093 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2094 hd->tmState = TM_STATE_NONE;
2099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2101 * This is anyones guess quite frankly.
2104 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2105 sector_t capacity, int geom[])
2115 dummy = heads * sectors;
2116 cylinders = capacity;
2117 sector_div(cylinders,dummy);
2120 * Handle extended translation size for logical drives
2123 if ((ulong)capacity >= 0x200000) {
2126 dummy = heads * sectors;
2127 cylinders = capacity;
2128 sector_div(cylinders,dummy);
2134 geom[2] = cylinders;
2136 dprintk((KERN_NOTICE
2137 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2138 sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
2143 /* Search IOC page 3 to determine if this is hidden physical disk
2147 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2152 if (!ioc->raid_data.pIocPg3)
2154 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2155 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2156 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2165 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2168 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2173 if (!ioc->raid_data.pIocPg3)
2175 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2176 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2177 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2178 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2186 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2189 * OS entry point to allow for host driver to free allocated memory
2190 * Called if no device present or device being unloaded
2193 mptscsih_slave_destroy(struct scsi_device *sdev)
2195 struct Scsi_Host *host = sdev->host;
2196 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2197 VirtTarget *vtarget;
2198 VirtDevice *vdevice;
2199 struct scsi_target *starget;
2201 starget = scsi_target(sdev);
2202 vtarget = starget->hostdata;
2203 vdevice = sdev->hostdata;
2205 mptscsih_search_running_cmds(hd, vdevice);
2206 vtarget->num_luns--;
2207 mptscsih_synchronize_cache(hd, vdevice);
2209 sdev->hostdata = NULL;
2212 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2214 * mptscsih_change_queue_depth - This function will set a devices queue depth
2215 * @sdev: per scsi_device pointer
2216 * @qdepth: requested queue depth
2218 * Adding support for new 'change_queue_depth' api.
2221 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2223 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2224 VirtTarget *vtarget;
2225 struct scsi_target *starget;
2229 starget = scsi_target(sdev);
2230 vtarget = starget->hostdata;
2232 if (hd->ioc->bus_type == SPI) {
2233 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2235 else if (sdev->type == TYPE_DISK &&
2236 vtarget->minSyncFactor <= MPT_ULTRA160)
2237 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2239 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2241 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2243 if (qdepth > max_depth)
2248 tagged = MSG_SIMPLE_TAG;
2250 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2251 return sdev->queue_depth;
2255 * OS entry point to adjust the queue_depths on a per-device basis.
2256 * Called once per device the bus scan. Use it to force the queue_depth
2257 * member to 1 if a device does not support Q tags.
2258 * Return non-zero if fails.
2261 mptscsih_slave_configure(struct scsi_device *sdev)
2263 struct Scsi_Host *sh = sdev->host;
2264 VirtTarget *vtarget;
2265 VirtDevice *vdevice;
2266 struct scsi_target *starget;
2267 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2269 starget = scsi_target(sdev);
2270 vtarget = starget->hostdata;
2271 vdevice = sdev->hostdata;
2273 dsprintk((MYIOC_s_INFO_FMT
2274 "device @ %p, channel=%d, id=%d, lun=%d\n",
2275 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2276 if (hd->ioc->bus_type == SPI)
2277 dsprintk((MYIOC_s_INFO_FMT
2278 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2279 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2280 sdev->ppr, sdev->inquiry_len));
2282 if (sdev->id > sh->max_id) {
2283 /* error case, should never happen */
2284 scsi_adjust_queue_depth(sdev, 0, 1);
2285 goto slave_configure_exit;
2288 vdevice->configured_lun = 1;
2289 mptscsih_initTarget(hd, vtarget, sdev);
2290 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2292 dsprintk((MYIOC_s_INFO_FMT
2293 "Queue depth=%d, tflags=%x\n",
2294 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2296 if (hd->ioc->bus_type == SPI)
2297 dsprintk((MYIOC_s_INFO_FMT
2298 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2299 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2300 vtarget->minSyncFactor));
2302 slave_configure_exit:
2304 dsprintk((MYIOC_s_INFO_FMT
2305 "tagged %d, simple %d, ordered %d\n",
2306 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2307 sdev->ordered_tags));
2312 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2314 * Private routines...
2317 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2318 /* Utility function to copy sense data from the scsi_cmnd buffer
2319 * to the FC and SCSI target structures.
2323 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2326 SCSIIORequest_t *pReq;
2327 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2329 /* Get target structure
2331 pReq = (SCSIIORequest_t *) mf;
2332 vdev = sc->device->hostdata;
2338 /* Copy the sense received into the scsi command block. */
2339 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2340 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2341 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2343 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2345 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2346 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2348 MPT_ADAPTER *ioc = hd->ioc;
2350 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2351 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2352 ioc->events[idx].eventContext = ioc->eventContext;
2354 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2355 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2356 (sc->device->channel << 8) || sc->device->id;
2358 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2360 ioc->eventContext++;
2361 if (hd->ioc->pcidev->vendor ==
2362 PCI_VENDOR_ID_IBM) {
2363 mptscsih_issue_sep_command(hd->ioc,
2364 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2365 vdev->vtarget->tflags |=
2366 MPT_TARGET_FLAGS_LED_ON;
2371 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2377 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2382 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2384 for (i = 0; i < hd->ioc->req_depth; i++) {
2385 if (hd->ScsiLookup[i] == sc) {
2393 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2395 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2398 unsigned long flags;
2401 dtmprintk((KERN_WARNING MYNAM
2402 ": IOC %s_reset routed to SCSI host driver!\n",
2403 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2404 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2406 /* If a FW reload request arrives after base installed but
2407 * before all scsi hosts have been attached, then an alt_ioc
2408 * may have a NULL sh pointer.
2410 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2413 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2415 if (reset_phase == MPT_IOC_SETUP_RESET) {
2416 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2419 * 1. Set Hard Reset Pending Flag
2420 * All new commands go to doneQ
2422 hd->resetPending = 1;
2424 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2425 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2427 /* 2. Flush running commands
2428 * Clean ScsiLookup (and associated memory)
2432 /* 2b. Reply to OS all known outstanding I/O commands.
2434 mptscsih_flush_running_cmds(hd);
2436 /* 2c. If there was an internal command that
2437 * has not completed, configuration or io request,
2438 * free these resources.
2441 del_timer(&hd->timer);
2442 mpt_free_msg_frame(ioc, hd->cmdPtr);
2445 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2448 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2450 /* Once a FW reload begins, all new OS commands are
2451 * redirected to the doneQ w/ a reset status.
2452 * Init all control structures.
2455 /* ScsiLookup initialization
2457 for (ii=0; ii < hd->ioc->req_depth; ii++)
2458 hd->ScsiLookup[ii] = NULL;
2460 /* 2. Chain Buffer initialization
2463 /* 4. Renegotiate to all devices, if SPI
2466 /* 5. Enable new commands to be posted
2468 spin_lock_irqsave(&ioc->FreeQlock, flags);
2470 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2471 hd->resetPending = 0;
2472 hd->tmState = TM_STATE_NONE;
2474 /* 6. If there was an internal command,
2475 * wake this process up.
2479 * Wake up the original calling thread
2481 hd->pLocal = &hd->localReply;
2482 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2483 hd->scandv_wait_done = 1;
2484 wake_up(&hd->scandv_waitq);
2488 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2492 return 1; /* currently means nothing really */
2495 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2497 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2500 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2502 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2505 if (ioc->sh == NULL ||
2506 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2510 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2513 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2514 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2515 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2518 case MPI_EVENT_LOGOUT: /* 09 */
2522 case MPI_EVENT_RESCAN: /* 06 */
2526 * CHECKME! Don't think we need to do
2527 * anything for these, but...
2529 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2530 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2532 * CHECKME! Falling thru...
2536 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2539 case MPI_EVENT_NONE: /* 00 */
2540 case MPI_EVENT_LOG_DATA: /* 01 */
2541 case MPI_EVENT_STATE_CHANGE: /* 02 */
2542 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2544 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2548 return 1; /* currently means nothing really */
2551 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2553 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2554 * @hd: Pointer to MPT_SCSI_HOST structure
2555 * @vtarget: per target private data
2556 * @sdev: SCSI device
2558 * NOTE: It's only SAFE to call this routine if data points to
2559 * sane & valid STANDARD INQUIRY data!
2561 * Allocate and initialize memory for this target.
2562 * Save inquiry data.
2566 mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget,
2567 struct scsi_device *sdev)
2569 dinitprintk((MYIOC_s_INFO_FMT "initTarget channel=%d id=%d lun=%d hd=%p\n",
2570 hd->ioc->name, vtarget->channel, vtarget->id,
2573 /* Is LUN supported? If so, upper 2 bits will be 0
2574 * in first byte of inquiry data.
2576 if (sdev->inq_periph_qual != 0)
2579 if (vtarget == NULL)
2582 vtarget->type = sdev->type;
2584 if (hd->ioc->bus_type != SPI)
2587 if ((sdev->type == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2588 /* Treat all Processors as SAF-TE if
2589 * command line option is set */
2590 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2591 mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id);
2592 }else if ((sdev->type == TYPE_PROCESSOR) &&
2593 !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2594 if (sdev->inquiry_len > 49 ) {
2595 if (sdev->inquiry[44] == 'S' &&
2596 sdev->inquiry[45] == 'A' &&
2597 sdev->inquiry[46] == 'F' &&
2598 sdev->inquiry[47] == '-' &&
2599 sdev->inquiry[48] == 'T' &&
2600 sdev->inquiry[49] == 'E' ) {
2601 vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2602 mptscsih_writeIOCPage4(hd, vtarget->channel, vtarget->id);
2606 mptscsih_setTargetNegoParms(hd, vtarget, sdev);
2609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2611 * Update the target negotiation parameters based on the
2612 * the Inquiry data, adapter capabilities, and NVRAM settings.
2616 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,
2617 struct scsi_device *sdev)
2619 SpiCfgData *pspi_data = &hd->ioc->spi_data;
2620 int id = (int) target->id;
2622 u8 width = MPT_NARROW;
2623 u8 factor = MPT_ASYNC;
2628 target->negoFlags = pspi_data->noQas;
2630 /* noQas == 0 => device supports QAS. */
2632 if (sdev->scsi_level < SCSI_2) {
2634 factor = MPT_ULTRA2;
2635 offset = pspi_data->maxSyncOffset;
2636 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2638 if (scsi_device_wide(sdev)) {
2642 if (scsi_device_sync(sdev)) {
2643 factor = pspi_data->minSyncFactor;
2644 if (!scsi_device_dt(sdev))
2645 factor = MPT_ULTRA2;
2647 if (!scsi_device_ius(sdev) &&
2648 !scsi_device_qas(sdev))
2649 factor = MPT_ULTRA160;
2651 factor = MPT_ULTRA320;
2652 if (scsi_device_qas(sdev)) {
2653 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id));
2656 if (sdev->type == TYPE_TAPE &&
2657 scsi_device_ius(sdev))
2658 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2661 offset = pspi_data->maxSyncOffset;
2663 /* If RAID, never disable QAS
2664 * else if non RAID, do not disable
2665 * QAS if bit 1 is set
2666 * bit 1 QAS support, non-raid only
2669 if (target->raidVolume == 1) {
2678 if (!sdev->tagged_supported) {
2679 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2682 /* Update tflags based on NVRAM settings. (SCSI only)
2684 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2685 nvram = pspi_data->nvram[id];
2686 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2689 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2692 /* Ensure factor is set to the
2693 * maximum of: adapter, nvram, inquiry
2696 if (nfactor < pspi_data->minSyncFactor )
2697 nfactor = pspi_data->minSyncFactor;
2699 factor = max(factor, nfactor);
2700 if (factor == MPT_ASYNC)
2711 /* Make sure data is consistent
2713 if ((!width) && (factor < MPT_ULTRA2)) {
2714 factor = MPT_ULTRA2;
2717 /* Save the data to the target structure.
2719 target->minSyncFactor = factor;
2720 target->maxOffset = offset;
2721 target->maxWidth = width;
2723 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2725 /* Disable unused features.
2728 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2731 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2733 if ( factor > MPT_ULTRA320 )
2736 if (noQas && (pspi_data->noQas == 0)) {
2737 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2738 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2740 /* Disable QAS in a mixed configuration case
2743 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2747 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2749 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2751 * SCSI Config Page functionality ...
2754 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2755 /* mptscsih_writeIOCPage4 - write IOC Page 4
2756 * @hd: Pointer to a SCSI Host Structure
2757 * @channel: write IOC Page4 for this Bus
2758 * @id: write IOC Page4 for this ID
2760 * Return: -EAGAIN if unable to obtain a Message Frame
2763 * Remark: We do not wait for a return, write pages sequentially.
2766 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int channel, int id)
2768 MPT_ADAPTER *ioc = hd->ioc;
2770 IOCPage4_t *IOCPage4Ptr;
2778 /* Get a MF for this command.
2780 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
2781 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
2786 /* Set the request and the data pointers.
2787 * Place data at end of MF.
2789 pReq = (Config_t *)mf;
2791 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2792 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
2794 /* Complete the request frame (same for all requests).
2796 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
2798 pReq->ChainOffset = 0;
2799 pReq->Function = MPI_FUNCTION_CONFIG;
2800 pReq->ExtPageLength = 0;
2801 pReq->ExtPageType = 0;
2803 for (ii=0; ii < 8; ii++) {
2804 pReq->Reserved2[ii] = 0;
2807 IOCPage4Ptr = ioc->spi_data.pIocPg4;
2808 dataDma = ioc->spi_data.IocPg4_dma;
2809 ii = IOCPage4Ptr->ActiveSEP++;
2810 IOCPage4Ptr->SEP[ii].SEPTargetID = id;
2811 IOCPage4Ptr->SEP[ii].SEPBus = channel;
2812 pReq->Header = IOCPage4Ptr->Header;
2813 pReq->PageAddress = cpu_to_le32(id | (channel << 8 ));
2815 /* Add a SGE to the config request.
2817 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
2818 (IOCPage4Ptr->Header.PageLength + ii) * 4;
2820 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
2822 dinitprintk((MYIOC_s_INFO_FMT
2823 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d channel=%d id=%d \n",
2824 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, channel, id));
2826 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
2831 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2833 * Bus Scan and Domain Validation functionality ...
2836 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2838 * mptscsih_scandv_complete - Scan and DV callback routine registered
2839 * to Fustion MPT (base) driver.
2841 * @ioc: Pointer to MPT_ADAPTER structure
2842 * @mf: Pointer to original MPT request frame
2843 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2845 * This routine is called from mpt.c::mpt_interrupt() at the completion
2846 * of any SCSI IO request.
2847 * This routine is registered with the Fusion MPT (base) driver at driver
2848 * load/init time via the mpt_register() API call.
2850 * Returns 1 indicating alloc'd request frame ptr should be freed.
2852 * Remark: Sets a completion code and (possibly) saves sense data
2853 * in the IOC member localReply structure.
2854 * Used ONLY for DV and other internal commands.
2857 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2860 SCSIIORequest_t *pReq;
2864 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2867 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2868 printk(MYIOC_s_ERR_FMT
2869 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2870 ioc->name, mf?"BAD":"NULL", (void *) mf);
2874 del_timer(&hd->timer);
2875 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2876 hd->ScsiLookup[req_idx] = NULL;
2877 pReq = (SCSIIORequest_t *) mf;
2879 if (mf != hd->cmdPtr) {
2880 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2881 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2885 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2886 hd->ioc->name, mf, mr, req_idx));
2888 hd->pLocal = &hd->localReply;
2889 hd->pLocal->scsiStatus = 0;
2891 /* If target struct exists, clear sense valid flag.
2894 completionCode = MPT_SCANDV_GOOD;
2896 SCSIIOReply_t *pReply;
2900 pReply = (SCSIIOReply_t *) mr;
2902 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2903 scsi_status = pReply->SCSIStatus;
2905 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
2906 status, pReply->SCSIState, scsi_status,
2907 le32_to_cpu(pReply->IOCLogInfo)));
2911 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2912 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2915 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2916 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2917 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2918 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2919 completionCode = MPT_SCANDV_DID_RESET;
2922 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2923 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2924 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2925 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2926 ConfigReply_t *pr = (ConfigReply_t *)mr;
2927 completionCode = MPT_SCANDV_GOOD;
2928 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2929 hd->pLocal->header.PageLength = pr->Header.PageLength;
2930 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2931 hd->pLocal->header.PageType = pr->Header.PageType;
2933 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2934 /* If the RAID Volume request is successful,
2935 * return GOOD, else indicate that
2936 * some type of error occurred.
2938 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2939 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2940 completionCode = MPT_SCANDV_GOOD;
2942 completionCode = MPT_SCANDV_SOME_ERROR;
2943 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2945 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2949 /* save sense data in global structure
2951 completionCode = MPT_SCANDV_SENSE;
2952 hd->pLocal->scsiStatus = scsi_status;
2953 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2954 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2956 sz = min_t(int, pReq->SenseBufferLength,
2957 SCSI_STD_SENSE_BYTES);
2958 memcpy(hd->pLocal->sense, sense_data, sz);
2960 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
2962 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2963 if (pReq->CDB[0] == INQUIRY)
2964 completionCode = MPT_SCANDV_ISSUE_SENSE;
2966 completionCode = MPT_SCANDV_DID_RESET;
2968 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2969 completionCode = MPT_SCANDV_DID_RESET;
2970 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2971 completionCode = MPT_SCANDV_DID_RESET;
2973 completionCode = MPT_SCANDV_GOOD;
2974 hd->pLocal->scsiStatus = scsi_status;
2978 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2979 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2980 completionCode = MPT_SCANDV_DID_RESET;
2982 completionCode = MPT_SCANDV_SOME_ERROR;
2986 completionCode = MPT_SCANDV_SOME_ERROR;
2989 } /* switch(status) */
2991 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
2993 } /* end of address reply case */
2995 hd->pLocal->completion = completionCode;
2997 /* MF and RF are freed in mpt_interrupt
3000 /* Free Chain buffers (will never chain) in scan or dv */
3001 //mptscsih_freeChainBuffers(ioc, req_idx);
3004 * Wake up the original calling thread
3006 hd->scandv_wait_done = 1;
3007 wake_up(&hd->scandv_waitq);
3012 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3013 /* mptscsih_timer_expired - Call back for timer process.
3014 * Used only for dv functionality.
3015 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3019 mptscsih_timer_expired(unsigned long data)
3021 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3023 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3026 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3028 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3029 /* Desire to issue a task management request here.
3030 * TM requests MUST be single threaded.
3031 * If old eh code and no TM current, issue request.
3032 * If new eh code, do nothing. Wait for OS cmd timeout
3035 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3037 /* Perform a FW reload */
3038 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3039 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3043 /* This should NEVER happen */
3044 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3047 /* No more processing.
3048 * TM call will generate an interrupt for SCSI TM Management.
3049 * The FW will reply to all outstanding commands, callback will finish cleanup.
3050 * Hard reset clean-up will free all resources.
3052 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3058 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3060 * mptscsih_do_cmd - Do internal command.
3061 * @hd: MPT_SCSI_HOST pointer
3062 * @io: INTERNAL_CMD pointer.
3064 * Issue the specified internally generated command and do command
3065 * specific cleanup. For bus scan / DV only.
3066 * NOTES: If command is Inquiry and status is good,
3067 * initialize a target structure, save the data
3069 * Remark: Single threaded access only.
3072 * < 0 if an illegal command or no resources
3076 * > 0 if command complete but some type of completion error.
3079 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3082 SCSIIORequest_t *pScsiReq;
3083 SCSIIORequest_t ReqCopy;
3084 int my_idx, ii, dir;
3088 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3091 in_isr = in_interrupt();
3093 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3099 /* Set command specific information
3104 dir = MPI_SCSIIO_CONTROL_READ;
3110 case TEST_UNIT_READY:
3112 dir = MPI_SCSIIO_CONTROL_READ;
3118 dir = MPI_SCSIIO_CONTROL_READ;
3120 CDB[4] = 1; /*Spin up the disk */
3128 dir = MPI_SCSIIO_CONTROL_READ;
3134 dir = MPI_SCSIIO_CONTROL_READ;
3136 if (io->flags & MPT_ICFLAG_ECHO) {
3142 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3145 CDB[6] = (io->size >> 16) & 0xFF;
3146 CDB[7] = (io->size >> 8) & 0xFF;
3147 CDB[8] = io->size & 0xFF;
3153 dir = MPI_SCSIIO_CONTROL_WRITE;
3155 if (io->flags & MPT_ICFLAG_ECHO) {
3160 CDB[6] = (io->size >> 16) & 0xFF;
3161 CDB[7] = (io->size >> 8) & 0xFF;
3162 CDB[8] = io->size & 0xFF;
3168 dir = MPI_SCSIIO_CONTROL_READ;
3175 dir = MPI_SCSIIO_CONTROL_READ;
3180 case SYNCHRONIZE_CACHE:
3182 dir = MPI_SCSIIO_CONTROL_READ;
3184 // CDB[1] = 0x02; /* set immediate bit */
3193 /* Get and Populate a free Frame
3195 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3196 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3201 pScsiReq = (SCSIIORequest_t *) mf;
3203 /* Get the request index */
3204 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3205 ADD_INDEX_LOG(my_idx); /* for debug */
3207 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3208 pScsiReq->TargetID = io->physDiskNum;
3210 pScsiReq->ChainOffset = 0;
3211 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3213 pScsiReq->TargetID = io->id;
3214 pScsiReq->Bus = io->channel;
3215 pScsiReq->ChainOffset = 0;
3216 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3219 pScsiReq->CDBLength = cmdLen;
3220 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3222 pScsiReq->Reserved = 0;
3224 pScsiReq->MsgFlags = mpt_msg_flags();
3225 /* MsgContext set in mpt_get_msg_fram call */
3227 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3229 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3230 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3232 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3234 if (cmd == REQUEST_SENSE) {
3235 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3236 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3237 hd->ioc->name, cmd));
3240 for (ii=0; ii < 16; ii++)
3241 pScsiReq->CDB[ii] = CDB[ii];
3243 pScsiReq->DataLength = cpu_to_le32(io->size);
3244 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3245 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3247 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3248 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3250 if (dir == MPI_SCSIIO_CONTROL_READ) {
3251 mpt_add_sge((char *) &pScsiReq->SGL,
3252 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3255 mpt_add_sge((char *) &pScsiReq->SGL,
3256 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3260 /* The ISR will free the request frame, but we need
3261 * the information to initialize the target. Duplicate.
3263 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3265 /* Issue this command after:
3268 * Wait until the reply has been received
3269 * ScsiScanDvCtx callback function will
3271 * set scandv_wait_done and call wake_up
3274 hd->timer.expires = jiffies + HZ*cmdTimeout;
3275 hd->scandv_wait_done = 0;
3277 /* Save cmd pointer, for resource free if timeout or
3282 add_timer(&hd->timer);
3283 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3284 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3287 rc = hd->pLocal->completion;
3288 hd->pLocal->skip = 0;
3290 /* Always set fatal error codes in some cases.
3292 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3294 else if (rc == MPT_SCANDV_SOME_ERROR)
3298 /* This should never happen. */
3299 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3306 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3308 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3309 * @hd: Pointer to a SCSI HOST structure
3310 * @vdevice: virtual target device
3312 * Uses the ISR, but with special processing.
3313 * MUST be single-threaded.
3317 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3321 /* Following parameters will not change
3324 iocmd.cmd = SYNCHRONIZE_CACHE;
3326 iocmd.physDiskNum = -1;
3328 iocmd.data_dma = -1;
3330 iocmd.rsvd = iocmd.rsvd2 = 0;
3331 iocmd.channel = vdevice->vtarget->channel;
3332 iocmd.id = vdevice->vtarget->id;
3333 iocmd.lun = vdevice->lun;
3335 if ((vdevice->vtarget->type == TYPE_DISK) &&
3336 (vdevice->configured_lun))
3337 mptscsih_do_cmd(hd, &iocmd);
3340 EXPORT_SYMBOL(mptscsih_remove);
3341 EXPORT_SYMBOL(mptscsih_shutdown);
3343 EXPORT_SYMBOL(mptscsih_suspend);
3344 EXPORT_SYMBOL(mptscsih_resume);
3346 EXPORT_SYMBOL(mptscsih_proc_info);
3347 EXPORT_SYMBOL(mptscsih_info);
3348 EXPORT_SYMBOL(mptscsih_qcmd);
3349 EXPORT_SYMBOL(mptscsih_slave_destroy);
3350 EXPORT_SYMBOL(mptscsih_slave_configure);
3351 EXPORT_SYMBOL(mptscsih_abort);
3352 EXPORT_SYMBOL(mptscsih_dev_reset);
3353 EXPORT_SYMBOL(mptscsih_bus_reset);
3354 EXPORT_SYMBOL(mptscsih_host_reset);
3355 EXPORT_SYMBOL(mptscsih_bios_param);
3356 EXPORT_SYMBOL(mptscsih_io_done);
3357 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3358 EXPORT_SYMBOL(mptscsih_scandv_complete);
3359 EXPORT_SYMBOL(mptscsih_event_process);
3360 EXPORT_SYMBOL(mptscsih_ioc_reset);
3361 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3362 EXPORT_SYMBOL(mptscsih_timer_expired);
3363 EXPORT_SYMBOL(mptscsih_TMHandler);
3365 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/