2 * linux/drivers/message/fusion/mptscsih.c
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2008 LSI Corporation
7 * (mailto:DL-MPTFusionLinux@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/module.h>
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/errno.h>
51 #include <linux/kdev_t.h>
52 #include <linux/blkdev.h>
53 #include <linux/delay.h> /* for mdelay */
54 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
55 #include <linux/reboot.h> /* notifier code */
56 #include <linux/workqueue.h>
58 #include <scsi/scsi.h>
59 #include <scsi/scsi_cmnd.h>
60 #include <scsi/scsi_device.h>
61 #include <scsi/scsi_host.h>
62 #include <scsi/scsi_tcq.h>
63 #include <scsi/scsi_dbg.h>
67 #include "lsi/mpi_log_sas.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT SCSI Host driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptscsih"
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77 MODULE_VERSION(my_VERSION);
79 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
81 * Other private/forward protos...
83 static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i);
84 static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i);
85 static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd);
86 static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd);
87 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
88 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
89 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
91 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
92 SCSIIORequest_t *pReq, int req_idx);
93 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
94 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
95 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
96 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
98 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
100 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
101 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
103 static int mptscsih_get_completion_code(MPT_ADAPTER *ioc,
104 MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
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) SCSI_SENSE_BUFFERSIZE
119 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
121 * mptscsih_getFreeChainBuffer - Function to get a free chain
122 * from the MPT_SCSI_HOST FreeChainQ.
123 * @ioc: Pointer to MPT_ADAPTER structure
124 * @req_idx: Index of the SCSI IO request frame. (output)
126 * return SUCCESS or FAILED
129 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
131 MPT_FRAME_HDR *chainBuf;
136 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
138 spin_lock_irqsave(&ioc->FreeQlock, flags);
139 if (!list_empty(&ioc->FreeChainQ)) {
142 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
143 u.frame.linkage.list);
144 list_del(&chainBuf->u.frame.linkage.list);
145 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
146 chain_idx = offset / ioc->req_sz;
148 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
149 "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
150 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
153 chain_idx = MPT_HOST_NO_CHAIN;
154 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
157 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
159 *retIndex = chain_idx;
161 } /* mptscsih_getFreeChainBuffer() */
163 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
165 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
166 * SCSIIORequest_t Message Frame.
167 * @ioc: Pointer to MPT_ADAPTER structure
168 * @SCpnt: Pointer to scsi_cmnd structure
169 * @pReq: Pointer to SCSIIORequest_t structure
174 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
175 SCSIIORequest_t *pReq, int req_idx)
179 struct scatterlist *sg;
181 int sges_left, sg_done;
182 int chain_idx = MPT_HOST_NO_CHAIN;
184 int numSgeSlots, numSgeThisFrame;
185 u32 sgflags, sgdir, thisxfer = 0;
186 int chain_dma_off = 0;
192 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
193 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
194 sgdir = MPT_TRANSFER_HOST_TO_IOC;
196 sgdir = MPT_TRANSFER_IOC_TO_HOST;
199 psge = (char *) &pReq->SGL;
200 frm_sz = ioc->req_sz;
202 /* Map the data portion, if any.
203 * sges_left = 0 if no data transfer.
205 sges_left = scsi_dma_map(SCpnt);
209 /* Handle the SG case.
211 sg = scsi_sglist(SCpnt);
213 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
216 /* Prior to entering this loop - the following must be set
217 * current MF: sgeOffset (bytes)
218 * chainSge (Null if original MF is not a chain buffer)
219 * sg_done (num SGE done for this MF)
223 numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size);
224 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
226 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir;
228 /* Get first (num - 1) SG elements
229 * Skip any SG entries with a length of 0
230 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
232 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
233 thisxfer = sg_dma_len(sg);
235 sg = sg_next(sg); /* Get next SG element from the OS */
240 v2 = sg_dma_address(sg);
241 ioc->add_sge(psge, sgflags | thisxfer, v2);
243 sg = sg_next(sg); /* Get next SG element from the OS */
244 psge += ioc->SGE_size;
245 sgeOffset += ioc->SGE_size;
249 if (numSgeThisFrame == sges_left) {
250 /* Add last element, end of buffer and end of list flags.
252 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
253 MPT_SGE_FLAGS_END_OF_BUFFER |
254 MPT_SGE_FLAGS_END_OF_LIST;
256 /* Add last SGE and set termination flags.
257 * Note: Last SGE may have a length of 0 - which should be ok.
259 thisxfer = sg_dma_len(sg);
261 v2 = sg_dma_address(sg);
262 ioc->add_sge(psge, sgflags | thisxfer, v2);
263 sgeOffset += ioc->SGE_size;
267 /* The current buffer is a chain buffer,
268 * but there is not another one.
269 * Update the chain element
270 * Offset and Length fields.
272 ioc->add_chain((char *)chainSge, 0, sgeOffset,
273 ioc->ChainBufferDMA + chain_dma_off);
275 /* The current buffer is the original MF
276 * and there is no Chain buffer.
278 pReq->ChainOffset = 0;
279 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
280 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
281 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
282 ioc->RequestNB[req_idx] = RequestNB;
285 /* At least one chain buffer is needed.
286 * Complete the first MF
287 * - last SGE element, set the LastElement bit
288 * - set ChainOffset (words) for orig MF
289 * (OR finish previous MF chain buffer)
290 * - update MFStructPtr ChainIndex
291 * - Populate chain element
296 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n",
297 ioc->name, sg_done));
299 /* Set LAST_ELEMENT flag for last non-chain element
300 * in the buffer. Since psge points at the NEXT
301 * SGE element, go back one SGE element, update the flags
302 * and reset the pointer. (Note: sgflags & thisxfer are already
306 u32 *ptmp = (u32 *) (psge - ioc->SGE_size);
307 sgflags = le32_to_cpu(*ptmp);
308 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
309 *ptmp = cpu_to_le32(sgflags);
313 /* The current buffer is a chain buffer.
314 * chainSge points to the previous Chain Element.
315 * Update its chain element Offset and Length (must
316 * include chain element size) fields.
317 * Old chain element is now complete.
319 u8 nextChain = (u8) (sgeOffset >> 2);
320 sgeOffset += ioc->SGE_size;
321 ioc->add_chain((char *)chainSge, nextChain, sgeOffset,
322 ioc->ChainBufferDMA + chain_dma_off);
324 /* The original MF buffer requires a chain buffer -
326 * Last element in this MF is a chain element.
328 pReq->ChainOffset = (u8) (sgeOffset >> 2);
329 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
330 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
331 ioc->RequestNB[req_idx] = RequestNB;
334 sges_left -= sg_done;
337 /* NOTE: psge points to the beginning of the chain element
338 * in current buffer. Get a chain buffer.
340 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
341 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
342 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
343 ioc->name, pReq->CDB[0], SCpnt));
347 /* Update the tracking arrays.
348 * If chainSge == NULL, update ReqToChain, else ChainToChain
351 ioc->ChainToChain[chain_idx] = newIndex;
353 ioc->ReqToChain[req_idx] = newIndex;
355 chain_idx = newIndex;
356 chain_dma_off = ioc->req_sz * chain_idx;
358 /* Populate the chainSGE for the current buffer.
359 * - Set chain buffer pointer to psge and fill
360 * out the Address and Flags fields.
362 chainSge = (char *) psge;
363 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)",
364 ioc->name, psge, req_idx));
366 /* Start the SGE for the next buffer
368 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
372 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n",
373 ioc->name, psge, chain_idx));
375 /* Start the SGE for the next buffer
382 } /* mptscsih_AddSGE() */
385 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
389 SEPRequest_t *SEPMsg;
391 if (ioc->bus_type != SAS)
394 /* Not supported for hidden raid components
396 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
399 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
400 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
401 ioc->name,__func__));
405 SEPMsg = (SEPRequest_t *)mf;
406 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
407 SEPMsg->Bus = vtarget->channel;
408 SEPMsg->TargetID = vtarget->id;
409 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
410 SEPMsg->SlotStatus = SlotStatus;
411 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
412 "Sending SEP cmd=%x channel=%d id=%d\n",
413 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
414 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
417 #ifdef CONFIG_FUSION_LOGGING
419 * mptscsih_info_scsiio - debug print info on reply frame
420 * @ioc: Pointer to MPT_ADAPTER structure
421 * @sc: original scsi cmnd pointer
422 * @pScsiReply: Pointer to MPT reply frame
424 * MPT_DEBUG_REPLY needs to be enabled to obtain this info
426 * Refer to lsi/mpi.h.
429 mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
436 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
438 switch (ioc_status) {
440 case MPI_IOCSTATUS_SUCCESS:
443 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
444 desc = "invalid bus";
446 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
447 desc = "invalid target_id";
449 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
450 desc = "device not there";
452 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
453 desc = "data overrun";
455 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
456 desc = "data underrun";
458 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
459 desc = "I/O data error";
461 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
462 desc = "protocol error";
464 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
465 desc = "task terminated";
467 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
468 desc = "residual mismatch";
470 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
471 desc = "task management failed";
473 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
474 desc = "IOC terminated";
476 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
477 desc = "ext terminated";
484 switch (pScsiReply->SCSIStatus)
487 case MPI_SCSI_STATUS_SUCCESS:
490 case MPI_SCSI_STATUS_CHECK_CONDITION:
491 desc1 = "check condition";
493 case MPI_SCSI_STATUS_CONDITION_MET:
494 desc1 = "condition met";
496 case MPI_SCSI_STATUS_BUSY:
499 case MPI_SCSI_STATUS_INTERMEDIATE:
500 desc1 = "intermediate";
502 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
503 desc1 = "intermediate condmet";
505 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
506 desc1 = "reservation conflict";
508 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
509 desc1 = "command terminated";
511 case MPI_SCSI_STATUS_TASK_SET_FULL:
512 desc1 = "task set full";
514 case MPI_SCSI_STATUS_ACA_ACTIVE:
515 desc1 = "aca active";
517 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
518 desc1 = "fcpext device logged out";
520 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
521 desc1 = "fcpext no link";
523 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
524 desc1 = "fcpext unassigned";
531 scsi_print_command(sc);
532 printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
533 ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
534 printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
535 "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
537 printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
538 "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
539 le32_to_cpu(pScsiReply->TransferCount), sc->result);
540 printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
541 "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
542 ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
543 pScsiReply->SCSIState);
545 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
546 skey = sc->sense_buffer[2] & 0x0F;
547 asc = sc->sense_buffer[12];
548 ascq = sc->sense_buffer[13];
550 printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "
551 "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);
555 * Look for + dump FCP ResponseInfo[]!
557 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
558 pScsiReply->ResponseInfo)
559 printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",
560 ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));
564 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
566 * mptscsih_io_done - Main SCSI IO callback routine registered to
567 * Fusion MPT (base) driver
568 * @ioc: Pointer to MPT_ADAPTER structure
569 * @mf: Pointer to original MPT request frame
570 * @r: Pointer to MPT reply frame (NULL if TurboReply)
572 * This routine is called from mpt.c::mpt_interrupt() at the completion
573 * of any SCSI IO request.
574 * This routine is registered with the Fusion MPT (base) driver at driver
575 * load/init time via the mpt_register() API call.
577 * Returns 1 indicating alloc'd request frame ptr should be freed.
580 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
582 struct scsi_cmnd *sc;
584 SCSIIORequest_t *pScsiReq;
585 SCSIIOReply_t *pScsiReply;
586 u16 req_idx, req_idx_MR;
590 hd = shost_priv(ioc->sh);
591 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
592 req_idx_MR = (mr != NULL) ?
593 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
594 if ((req_idx != req_idx_MR) ||
595 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
596 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
598 printk (MYIOC_s_ERR_FMT
599 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
600 ioc->name, req_idx, req_idx_MR, mf, mr,
601 mptscsih_get_scsi_lookup(ioc, req_idx_MR));
605 sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);
607 MPIHeader_t *hdr = (MPIHeader_t *)mf;
609 /* Remark: writeSDP1 will use the ScsiDoneCtx
610 * If a SCSI I/O cmd, device disabled by OS and
611 * completion done. Cannot touch sc struct. Just free mem.
613 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
614 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
617 mptscsih_freeChainBuffers(ioc, req_idx);
621 if ((unsigned char *)mf != sc->host_scribble) {
622 mptscsih_freeChainBuffers(ioc, req_idx);
626 sc->host_scribble = NULL;
627 sc->result = DID_OK << 16; /* Set default reply as OK */
628 pScsiReq = (SCSIIORequest_t *) mf;
629 pScsiReply = (SCSIIOReply_t *) mr;
631 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
632 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
633 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
634 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
636 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
637 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
638 ioc->name, mf, mr, sc, req_idx));
641 if (pScsiReply == NULL) {
642 /* special context reply handling */
647 u8 scsi_state, scsi_status;
650 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
651 scsi_state = pScsiReply->SCSIState;
652 scsi_status = pScsiReply->SCSIStatus;
653 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
654 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
655 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
658 * if we get a data underrun indication, yet no data was
659 * transferred and the SCSI status indicates that the
660 * command was never started, change the data underrun
663 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
664 (scsi_status == MPI_SCSI_STATUS_BUSY ||
665 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
666 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
667 status = MPI_IOCSTATUS_SUCCESS;
670 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
671 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
674 * Look for + dump FCP ResponseInfo[]!
676 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
677 pScsiReply->ResponseInfo) {
678 printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
679 "FCP_ResponseInfo=%08xh\n", ioc->name,
680 sc->device->host->host_no, sc->device->channel,
681 sc->device->id, sc->device->lun,
682 le32_to_cpu(pScsiReply->ResponseInfo));
686 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
688 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
689 * But not: DID_BUS_BUSY lest one risk
690 * killing interrupt handler:-(
692 sc->result = SAM_STAT_BUSY;
695 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
696 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
697 sc->result = DID_BAD_TARGET << 16;
700 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
701 /* Spoof to SCSI Selection Timeout! */
702 if (ioc->bus_type != FC)
703 sc->result = DID_NO_CONNECT << 16;
704 /* else fibre, just stall until rescan event */
706 sc->result = DID_REQUEUE << 16;
708 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
709 hd->sel_timeout[pScsiReq->TargetID]++;
711 vdevice = sc->device->hostdata;
714 vtarget = vdevice->vtarget;
715 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
716 mptscsih_issue_sep_command(ioc, vtarget,
717 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
718 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
722 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
723 if ( ioc->bus_type == SAS ) {
724 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
725 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
726 if ((log_info & SAS_LOGINFO_MASK)
727 == SAS_LOGINFO_NEXUS_LOSS) {
728 sc->result = (DID_BUS_BUSY << 16);
732 } else if (ioc->bus_type == FC) {
734 * The FC IOC may kill a request for variety of
735 * reasons, some of which may be recovered by a
736 * retry, some which are unlikely to be
737 * recovered. Return DID_ERROR instead of
738 * DID_RESET to permit retry of the command,
739 * just not an infinite number of them
741 sc->result = DID_ERROR << 16;
746 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
749 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
750 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
751 /* Linux handles an unsolicited DID_RESET better
752 * than an unsolicited DID_ABORT.
754 sc->result = DID_RESET << 16;
758 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
759 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
760 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
761 sc->result=DID_SOFT_ERROR << 16;
762 else /* Sufficient data transfer occurred */
763 sc->result = (DID_OK << 16) | scsi_status;
764 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
765 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
766 ioc->name, sc->result, sc->device->channel, sc->device->id));
769 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
771 * Do upfront check for valid SenseData and give it
774 sc->result = (DID_OK << 16) | scsi_status;
775 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
776 /* Have already saved the status and sense data
780 if (xfer_cnt < sc->underflow) {
781 if (scsi_status == SAM_STAT_BUSY)
782 sc->result = SAM_STAT_BUSY;
784 sc->result = DID_SOFT_ERROR << 16;
786 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
789 sc->result = DID_SOFT_ERROR << 16;
791 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
792 /* Not real sure here either... */
793 sc->result = DID_RESET << 16;
798 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
799 " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
800 ioc->name, sc->underflow));
801 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
802 " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
806 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
807 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
811 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
812 scsi_set_resid(sc, 0);
813 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
814 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
815 sc->result = (DID_OK << 16) | scsi_status;
816 if (scsi_state == 0) {
818 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
820 * If running against circa 200003dd 909 MPT f/w,
821 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
822 * (QUEUE_FULL) returned from device! --> get 0x0000?128
823 * and with SenseBytes set to 0.
825 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
826 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
829 else if (scsi_state &
830 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
835 sc->result = DID_SOFT_ERROR << 16;
837 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
838 /* Not real sure here either... */
839 sc->result = DID_RESET << 16;
841 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
842 /* Device Inq. data indicates that it supports
843 * QTags, but rejects QTag messages.
844 * This command completed OK.
846 * Not real sure here either so do nothing... */
849 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
850 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
853 * Reservation Conflict, Busy,
854 * Command Terminated, CHECK
858 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
859 sc->result = DID_SOFT_ERROR << 16;
862 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
863 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
864 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
865 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
866 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
867 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
868 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
869 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
870 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
875 sc->result = DID_SOFT_ERROR << 16;
878 } /* switch(status) */
880 #ifdef CONFIG_FUSION_LOGGING
881 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
882 mptscsih_info_scsiio(ioc, sc, pScsiReply);
885 } /* end of address reply case */
887 /* Unmap the DMA buffers, if any. */
890 sc->scsi_done(sc); /* Issue the command callback */
892 /* Free Chain buffers */
893 mptscsih_freeChainBuffers(ioc, req_idx);
898 * mptscsih_flush_running_cmds - For each command found, search
899 * Scsi_Host instance taskQ and reply to OS.
900 * Called only if recovering from a FW reload.
901 * @hd: Pointer to a SCSI HOST structure
905 * Must be called while new I/Os are being queued.
908 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
910 MPT_ADAPTER *ioc = hd->ioc;
911 struct scsi_cmnd *sc;
912 SCSIIORequest_t *mf = NULL;
916 for (ii= 0; ii < ioc->req_depth; ii++) {
917 sc = mptscsih_getclear_scsi_lookup(ioc, ii);
920 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
925 mptscsih_freeChainBuffers(ioc, ii);
926 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
927 if ((unsigned char *)mf != sc->host_scribble)
930 sc->result = DID_RESET << 16;
931 sc->host_scribble = NULL;
932 sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT
933 "completing cmds: fw_channel %d, fw_id %d, sc=%p,"
934 " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii);
940 * mptscsih_search_running_cmds - Delete any commands associated
941 * with the specified target and lun. Function called only
942 * when a lun is disable by mid-layer.
943 * Do NOT access the referenced scsi_cmnd structure or
944 * members. Will cause either a paging or NULL ptr error.
945 * (BUT, BUT, BUT, the code does reference it! - mdr)
946 * @hd: Pointer to a SCSI HOST structure
947 * @vdevice: per device private data
951 * Called from slave_destroy.
954 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
956 SCSIIORequest_t *mf = NULL;
958 struct scsi_cmnd *sc;
960 MPT_ADAPTER *ioc = hd->ioc;
963 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
964 for (ii = 0; ii < ioc->req_depth; ii++) {
965 if ((sc = ioc->ScsiLookup[ii]) != NULL) {
967 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii);
970 /* If the device is a hidden raid component, then its
971 * expected that the mf->function will be RAID_SCSI_IO
973 if (vdevice->vtarget->tflags &
974 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
975 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
978 int_to_scsilun(vdevice->lun, &lun);
979 if ((mf->Bus != vdevice->vtarget->channel) ||
980 (mf->TargetID != vdevice->vtarget->id) ||
981 memcmp(lun.scsi_lun, mf->LUN, 8))
984 if ((unsigned char *)mf != sc->host_scribble)
986 ioc->ScsiLookup[ii] = NULL;
987 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
988 mptscsih_freeChainBuffers(ioc, ii);
989 mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf);
991 sc->host_scribble = NULL;
992 sc->result = DID_NO_CONNECT << 16;
993 sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d,"
994 "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel,
995 vdevice->vtarget->id, sc, mf, ii);
997 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1000 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1004 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1006 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1008 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1009 * from a SCSI target device.
1010 * @sc: Pointer to scsi_cmnd structure
1011 * @pScsiReply: Pointer to SCSIIOReply_t
1012 * @pScsiReq: Pointer to original SCSI request
1014 * This routine periodically reports QUEUE_FULL status returned from a
1015 * SCSI target device. It reports this to the console via kernel
1016 * printk() API call, not more than once every 10 seconds.
1019 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1021 long time = jiffies;
1025 if (sc->device == NULL)
1027 if (sc->device->host == NULL)
1029 if ((hd = shost_priv(sc->device->host)) == NULL)
1032 if (time - hd->last_queue_full > 10 * HZ) {
1033 dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1034 ioc->name, 0, sc->device->id, sc->device->lun));
1035 hd->last_queue_full = time;
1039 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1041 * mptscsih_remove - Removed scsi devices
1042 * @pdev: Pointer to pci_dev structure
1047 mptscsih_remove(struct pci_dev *pdev)
1049 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1050 struct Scsi_Host *host = ioc->sh;
1059 scsi_remove_host(host);
1061 if((hd = shost_priv(host)) == NULL)
1064 mptscsih_shutdown(pdev);
1068 if (ioc->ScsiLookup != NULL) {
1069 sz1 = ioc->req_depth * sizeof(void *);
1070 kfree(ioc->ScsiLookup);
1071 ioc->ScsiLookup = NULL;
1074 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1075 "Free'd ScsiLookup (%d) memory\n",
1078 kfree(hd->info_kbuf);
1080 /* NULL the Scsi_Host pointer
1084 scsi_host_put(host);
1090 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1092 * mptscsih_shutdown - reboot notifier
1096 mptscsih_shutdown(struct pci_dev *pdev)
1101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1103 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1108 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1110 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1112 scsi_block_requests(ioc->sh);
1113 flush_scheduled_work();
1114 mptscsih_shutdown(pdev);
1115 return mpt_suspend(pdev,state);
1118 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1120 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1125 mptscsih_resume(struct pci_dev *pdev)
1127 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1130 rc = mpt_resume(pdev);
1131 scsi_unblock_requests(ioc->sh);
1137 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1139 * mptscsih_info - Return information about MPT adapter
1140 * @SChost: Pointer to Scsi_Host structure
1142 * (linux scsi_host_template.info routine)
1144 * Returns pointer to buffer where information was written.
1147 mptscsih_info(struct Scsi_Host *SChost)
1152 h = shost_priv(SChost);
1155 if (h->info_kbuf == NULL)
1156 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1157 return h->info_kbuf;
1158 h->info_kbuf[0] = '\0';
1160 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1161 h->info_kbuf[size-1] = '\0';
1164 return h->info_kbuf;
1175 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1177 if (info->pos + len > info->length)
1178 len = info->length - info->pos;
1180 if (info->pos + len < info->offset) {
1185 if (info->pos < info->offset) {
1186 data += (info->offset - info->pos);
1187 len -= (info->offset - info->pos);
1191 memcpy(info->buffer + info->pos, data, len);
1197 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1203 va_start(args, fmt);
1204 len = vsprintf(buf, fmt, args);
1207 mptscsih_copy_mem_info(info, buf, len);
1212 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1214 struct info_str info;
1218 info.offset = offset;
1221 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1222 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1223 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1224 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1226 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1229 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1231 * mptscsih_proc_info - Return information about MPT adapter
1232 * @host: scsi host struct
1233 * @buffer: if write, user data; if read, buffer for user
1234 * @start: returns the buffer address
1235 * @offset: if write, 0; if read, the current offset into the buffer from
1236 * the previous read.
1237 * @length: if write, return length;
1238 * @func: write = 1; read = 0
1240 * (linux scsi_host_template.info routine)
1243 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1244 int length, int func)
1246 MPT_SCSI_HOST *hd = shost_priv(host);
1247 MPT_ADAPTER *ioc = hd->ioc;
1252 * write is not supported
1258 size = mptscsih_host_info(ioc, buffer, offset, length);
1264 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1265 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1269 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1270 * @SCpnt: Pointer to scsi_cmnd structure
1271 * @done: Pointer SCSI mid-layer IO completion function
1273 * (linux scsi_host_template.queuecommand routine)
1274 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1275 * from a linux scsi_cmnd request and send it to the IOC.
1277 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1280 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1284 SCSIIORequest_t *pScsiReq;
1285 VirtDevice *vdevice = SCpnt->device->hostdata;
1295 hd = shost_priv(SCpnt->device->host);
1297 lun = SCpnt->device->lun;
1298 SCpnt->scsi_done = done;
1300 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1301 ioc->name, SCpnt, done));
1303 if (hd->resetPending) {
1304 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1306 return SCSI_MLQUEUE_HOST_BUSY;
1310 * Put together a MPT SCSI request...
1312 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
1313 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1315 return SCSI_MLQUEUE_HOST_BUSY;
1318 pScsiReq = (SCSIIORequest_t *) mf;
1320 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1322 ADD_INDEX_LOG(my_idx);
1324 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1325 * Seems we may receive a buffer (datalen>0) even when there
1326 * will be no data transfer! GRRRRR...
1328 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1329 datalen = scsi_bufflen(SCpnt);
1330 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1331 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1332 datalen = scsi_bufflen(SCpnt);
1333 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1336 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1339 /* Default to untagged. Once a target structure has been allocated,
1340 * use the Inquiry data to determine if device supports tagged.
1343 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1344 && (SCpnt->device->tagged_supported)) {
1345 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1347 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1350 /* Use the above information to set up the message frame
1352 pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1353 pScsiReq->Bus = vdevice->vtarget->channel;
1354 pScsiReq->ChainOffset = 0;
1355 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1356 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1358 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1359 pScsiReq->CDBLength = SCpnt->cmd_len;
1360 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1361 pScsiReq->Reserved = 0;
1362 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
1363 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1364 pScsiReq->Control = cpu_to_le32(scsictl);
1367 * Write SCSI CDB into the message
1369 cmd_len = SCpnt->cmd_len;
1370 for (ii=0; ii < cmd_len; ii++)
1371 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1373 for (ii=cmd_len; ii < 16; ii++)
1374 pScsiReq->CDB[ii] = 0;
1377 pScsiReq->DataLength = cpu_to_le32(datalen);
1379 /* SenseBuffer low address */
1380 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1381 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1383 /* Now add the SG list
1384 * Always have a SGE even if null length.
1387 /* Add a NULL SGE */
1388 ioc->add_sge((char *)&pScsiReq->SGL,
1389 MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1392 /* Add a 32 or 64 bit SGE */
1393 if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1397 SCpnt->host_scribble = (unsigned char *)mf;
1398 mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1400 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1401 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1402 ioc->name, SCpnt, mf, my_idx));
1403 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1407 mptscsih_freeChainBuffers(ioc, my_idx);
1408 mpt_free_msg_frame(ioc, mf);
1409 return SCSI_MLQUEUE_HOST_BUSY;
1412 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1414 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1415 * with a SCSI IO request
1416 * @hd: Pointer to the MPT_SCSI_HOST instance
1417 * @req_idx: Index of the SCSI IO request frame.
1419 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1423 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1425 MPT_FRAME_HDR *chain;
1426 unsigned long flags;
1430 /* Get the first chain index and reset
1433 chain_idx = ioc->ReqToChain[req_idx];
1434 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1436 while (chain_idx != MPT_HOST_NO_CHAIN) {
1438 /* Save the next chain buffer index */
1439 next = ioc->ChainToChain[chain_idx];
1441 /* Free this chain buffer and reset
1444 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1446 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1447 + (chain_idx * ioc->req_sz));
1449 spin_lock_irqsave(&ioc->FreeQlock, flags);
1450 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1451 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1453 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1454 ioc->name, chain_idx));
1462 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1467 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1469 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1470 * @hd: Pointer to MPT SCSI HOST structure
1471 * @type: Task Management type
1472 * @channel: channel number for task management
1473 * @id: Logical Target ID for reset (if appropriate)
1474 * @lun: Logical Unit for reset (if appropriate)
1475 * @ctx2abort: Context for the task to be aborted (if appropriate)
1476 * @timeout: timeout for task management control
1478 * Fall through to mpt_HardResetHandler if: not operational, too many
1479 * failed TM requests or handshake failure.
1481 * Remark: Currently invoked from a non-interrupt thread (_bh).
1483 * Note: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1486 * Returns 0 for SUCCESS, or %FAILED.
1489 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1494 unsigned long flags;
1497 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
1499 // SJR - CHECKME - Can we avoid this here?
1500 // (mpt_HardResetHandler has this check...)
1501 spin_lock_irqsave(&ioc->diagLock, flags);
1502 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1503 spin_unlock_irqrestore(&ioc->diagLock, flags);
1506 spin_unlock_irqrestore(&ioc->diagLock, flags);
1508 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1509 * If we time out and not bus reset, then we return a FAILED status
1511 * The call to mptscsih_tm_pending_wait() will set the pending flag
1513 * successful. Otherwise, reload the FW.
1515 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1516 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1517 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
1518 "Timed out waiting for last TM (%d) to complete! \n",
1519 ioc->name, hd->tmPending));
1521 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1522 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
1523 "reset: Timed out waiting for last TM (%d) "
1524 "to complete! \n", ioc->name,
1527 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1528 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
1529 "Timed out waiting for last TM (%d) to complete! \n",
1530 ioc->name, hd->tmPending));
1534 spin_lock_irqsave(&ioc->FreeQlock, flags);
1535 hd->tmPending |= (1 << type);
1536 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1539 ioc_raw_state = mpt_GetIocState(ioc, 0);
1541 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1542 printk(MYIOC_s_WARN_FMT
1543 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1544 ioc->name, type, ioc_raw_state);
1545 printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
1546 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1547 printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
1548 "FAILED!!\n", ioc->name);
1552 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1553 printk(MYIOC_s_WARN_FMT
1554 "TM Handler for type=%x: ioc_state: "
1555 "DOORBELL_ACTIVE (0x%x)!\n",
1556 ioc->name, type, ioc_raw_state);
1560 /* Isse the Task Mgmt request.
1562 if (hd->hard_resets < -1)
1565 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1566 ctx2abort, timeout);
1568 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1571 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
1574 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1575 "TMHandler rc = %d!\n", ioc->name, rc));
1581 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1583 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1584 * @hd: Pointer to MPT_SCSI_HOST structure
1585 * @type: Task Management type
1586 * @channel: channel number for task management
1587 * @id: Logical Target ID for reset (if appropriate)
1588 * @lun: Logical Unit for reset (if appropriate)
1589 * @ctx2abort: Context for the task to be aborted (if appropriate)
1590 * @timeout: timeout for task management control
1592 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1593 * or a non-interrupt thread. In the former, must not call schedule().
1595 * Not all fields are meaningfull for all task types.
1597 * Returns 0 for SUCCESS, or FAILED.
1601 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1604 SCSITaskMgmt_t *pScsiTm;
1607 MPT_ADAPTER *ioc = hd->ioc;
1609 /* Return Fail to calling function if no message frames available.
1611 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
1612 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1616 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
1619 /* Format the Request
1621 pScsiTm = (SCSITaskMgmt_t *) mf;
1622 pScsiTm->TargetID = id;
1623 pScsiTm->Bus = channel;
1624 pScsiTm->ChainOffset = 0;
1625 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1627 pScsiTm->Reserved = 0;
1628 pScsiTm->TaskType = type;
1629 pScsiTm->Reserved1 = 0;
1630 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1631 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1633 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1635 for (ii=0; ii < 7; ii++)
1636 pScsiTm->Reserved2[ii] = 0;
1638 pScsiTm->TaskMsgContext = ctx2abort;
1640 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1641 "type=%d\n", ioc->name, ctx2abort, type));
1643 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1645 if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1646 (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1647 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
1649 retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
1650 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1652 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
1653 " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd,
1659 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1660 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1661 " (hd %p, ioc %p, mf %p) \n", ioc->name, hd,
1663 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
1665 retval = mpt_HardResetHandler(ioc, CAN_SLEEP);
1666 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
1667 ioc->name, retval));
1672 * Handle success case, see if theres a non-zero ioc_status.
1674 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1675 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1676 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1686 * Free task management mf, and corresponding tm flags
1688 mpt_free_msg_frame(ioc, mf);
1690 hd->tmState = TM_STATE_NONE;
1695 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1697 switch (ioc->bus_type) {
1707 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1709 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1710 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1712 * (linux scsi_host_template.eh_abort_handler routine)
1714 * Returns SUCCESS or FAILED.
1717 mptscsih_abort(struct scsi_cmnd * SCpnt)
1724 VirtDevice *vdevice;
1725 ulong sn = SCpnt->serial_number;
1728 /* If we can't locate our host adapter structure, return FAILED status.
1730 if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
1731 SCpnt->result = DID_RESET << 16;
1732 SCpnt->scsi_done(SCpnt);
1733 printk(KERN_ERR MYNAM ": task abort: "
1734 "can't locate host! (sc=%p)\n", SCpnt);
1739 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1741 scsi_print_command(SCpnt);
1743 vdevice = SCpnt->device->hostdata;
1744 if (!vdevice || !vdevice->vtarget) {
1745 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1746 "task abort: device has been deleted (sc=%p)\n",
1748 SCpnt->result = DID_NO_CONNECT << 16;
1749 SCpnt->scsi_done(SCpnt);
1754 /* Task aborts are not supported for hidden raid components.
1756 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1757 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1758 "task abort: hidden raid component (sc=%p)\n",
1760 SCpnt->result = DID_RESET << 16;
1765 /* Find this command
1767 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
1768 /* Cmd not found in ScsiLookup.
1771 SCpnt->result = DID_RESET << 16;
1772 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
1773 "Command not in the active list! (sc=%p)\n", ioc->name,
1779 if (hd->resetPending) {
1784 if (hd->timeouts < -1)
1787 if (mpt_fwfault_debug)
1788 mpt_halt_firmware(ioc);
1790 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1791 * (the IO to be ABORT'd)
1793 * NOTE: Since we do not byteswap MsgContext, we do not
1794 * swap it here either. It is an opaque cookie to
1795 * the controller, so it does not matter. -DaveM
1797 mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
1798 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1800 hd->abortSCpnt = SCpnt;
1802 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1803 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1804 ctx2abort, mptscsih_get_tm_timeout(ioc));
1806 if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx &&
1807 SCpnt->serial_number == sn)
1811 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
1812 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1820 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1822 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1823 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1825 * (linux scsi_host_template.eh_dev_reset_handler routine)
1827 * Returns SUCCESS or FAILED.
1830 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1834 VirtDevice *vdevice;
1837 /* If we can't locate our host adapter structure, return FAILED status.
1839 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1840 printk(KERN_ERR MYNAM ": target reset: "
1841 "Can't locate host! (sc=%p)\n", SCpnt);
1846 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1848 scsi_print_command(SCpnt);
1850 if (hd->resetPending) {
1855 vdevice = SCpnt->device->hostdata;
1856 if (!vdevice || !vdevice->vtarget) {
1861 /* Target reset to hidden raid component is not supported
1863 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1868 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1869 vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
1870 mptscsih_get_tm_timeout(ioc));
1873 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1874 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1883 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1885 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1886 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1888 * (linux scsi_host_template.eh_bus_reset_handler routine)
1890 * Returns SUCCESS or FAILED.
1893 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1897 VirtDevice *vdevice;
1900 /* If we can't locate our host adapter structure, return FAILED status.
1902 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1903 printk(KERN_ERR MYNAM ": bus reset: "
1904 "Can't locate host! (sc=%p)\n", SCpnt);
1909 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1911 scsi_print_command(SCpnt);
1913 if (hd->timeouts < -1)
1916 vdevice = SCpnt->device->hostdata;
1917 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1918 vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
1920 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1921 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1929 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1931 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1932 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1934 * (linux scsi_host_template.eh_host_reset_handler routine)
1936 * Returns SUCCESS or FAILED.
1939 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1945 /* If we can't locate the host to reset, then we failed. */
1946 if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1947 printk(KERN_ERR MYNAM ": host reset: "
1948 "Can't locate host! (sc=%p)\n", SCpnt);
1952 /* make sure we have no outstanding commands at this stage */
1953 mptscsih_flush_running_cmds(hd);
1956 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
1959 /* If our attempts to reset the host failed, then return a failed
1960 * status. The host will be taken off line by the SCSI mid-layer.
1962 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) {
1965 /* Make sure TM pending is cleared and TM state is set to
1970 hd->tmState = TM_STATE_NONE;
1973 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
1974 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1979 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1981 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1982 * @hd: Pointer to MPT host structure.
1984 * Returns {SUCCESS,FAILED}.
1987 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1989 unsigned long flags;
1990 int loop_count = 4 * 10; /* Wait 10 seconds */
1991 int status = FAILED;
1992 MPT_ADAPTER *ioc = hd->ioc;
1995 spin_lock_irqsave(&ioc->FreeQlock, flags);
1996 if (hd->tmState == TM_STATE_NONE) {
1997 hd->tmState = TM_STATE_IN_PROGRESS;
1999 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2003 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2005 } while (--loop_count);
2010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2012 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2013 * @hd: Pointer to MPT host structure.
2014 * @timeout: timeout value
2016 * Returns {SUCCESS,FAILED}.
2019 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2021 unsigned long flags;
2022 int loop_count = 4 * timeout;
2023 int status = FAILED;
2024 MPT_ADAPTER *ioc = hd->ioc;
2027 spin_lock_irqsave(&ioc->FreeQlock, flags);
2028 if(hd->tmPending == 0) {
2030 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2033 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2035 } while (--loop_count);
2040 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2042 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2046 switch (response_code) {
2047 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2048 desc = "The task completed.";
2050 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2051 desc = "The IOC received an invalid frame status.";
2053 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2054 desc = "The task type is not supported.";
2056 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2057 desc = "The requested task failed.";
2059 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2060 desc = "The task completed successfully.";
2062 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2063 desc = "The LUN request is invalid.";
2065 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2066 desc = "The task is in the IOC queue and has not been sent to target.";
2072 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2073 ioc->name, response_code, desc);
2076 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2078 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2079 * @ioc: Pointer to MPT_ADAPTER structure
2080 * @mf: Pointer to SCSI task mgmt request frame
2081 * @mr: Pointer to SCSI task mgmt reply frame
2083 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2084 * of any SCSI task management request.
2085 * This routine is registered with the MPT (base) driver at driver
2086 * load/init time via the mpt_register() API call.
2088 * Returns 1 indicating alloc'd request frame ptr should be freed.
2091 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2093 SCSITaskMgmtReply_t *pScsiTmReply;
2094 SCSITaskMgmt_t *pScsiTmReq;
2096 unsigned long flags;
2099 u32 termination_count;
2101 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2102 ioc->name, mf, mr));
2104 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2105 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2110 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2111 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2115 hd = shost_priv(ioc->sh);
2116 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2117 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2118 tmType = pScsiTmReq->TaskType;
2119 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2120 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2122 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2123 pScsiTmReply->ResponseCode)
2124 mptscsih_taskmgmt_response_code(ioc,
2125 pScsiTmReply->ResponseCode);
2126 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
2128 #ifdef CONFIG_FUSION_LOGGING
2129 if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
2130 (ioc->debug_level & MPT_DEBUG_TM ))
2131 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2132 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2133 "term_cmnds=%d\n", __func__, ioc->id, pScsiTmReply->Bus,
2134 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2135 le16_to_cpu(pScsiTmReply->IOCStatus),
2136 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2137 le32_to_cpu(pScsiTmReply->TerminationCount));
2140 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
2141 hd->abortSCpnt = NULL;
2145 /* Error? (anything non-zero?) */
2147 /* clear flags and continue.
2151 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2152 if (termination_count == 1)
2153 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2154 hd->abortSCpnt = NULL;
2157 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2159 /* If an internal command is present
2160 * or the TM failed - reload the FW.
2161 * FC FW may respond FAILED to an ABORT
2163 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2165 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2166 printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
2169 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2175 spin_lock_irqsave(&ioc->FreeQlock, flags);
2177 hd->tmState = TM_STATE_NONE;
2178 hd->tm_iocstatus = iocstatus;
2179 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2184 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2186 * This is anyones guess quite frankly.
2189 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2190 sector_t capacity, int geom[])
2200 dummy = heads * sectors;
2201 cylinders = capacity;
2202 sector_div(cylinders,dummy);
2205 * Handle extended translation size for logical drives
2208 if ((ulong)capacity >= 0x200000) {
2211 dummy = heads * sectors;
2212 cylinders = capacity;
2213 sector_div(cylinders,dummy);
2219 geom[2] = cylinders;
2224 /* Search IOC page 3 to determine if this is hidden physical disk
2228 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2230 struct inactive_raid_component_info *component_info;
2234 if (!ioc->raid_data.pIocPg3)
2236 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2237 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2238 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2245 * Check inactive list for matching phys disks
2247 if (list_empty(&ioc->raid_data.inactive_list))
2250 mutex_lock(&ioc->raid_data.inactive_list_mutex);
2251 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2253 if ((component_info->d.PhysDiskID == id) &&
2254 (component_info->d.PhysDiskBus == channel))
2257 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
2262 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2265 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2267 struct inactive_raid_component_info *component_info;
2271 if (!ioc->raid_data.pIocPg3)
2273 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2274 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2275 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2276 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2282 * Check inactive list for matching phys disks
2284 if (list_empty(&ioc->raid_data.inactive_list))
2287 mutex_lock(&ioc->raid_data.inactive_list_mutex);
2288 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2290 if ((component_info->d.PhysDiskID == id) &&
2291 (component_info->d.PhysDiskBus == channel))
2292 rc = component_info->d.PhysDiskNum;
2294 mutex_unlock(&ioc->raid_data.inactive_list_mutex);
2299 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2302 * OS entry point to allow for host driver to free allocated memory
2303 * Called if no device present or device being unloaded
2306 mptscsih_slave_destroy(struct scsi_device *sdev)
2308 struct Scsi_Host *host = sdev->host;
2309 MPT_SCSI_HOST *hd = shost_priv(host);
2310 VirtTarget *vtarget;
2311 VirtDevice *vdevice;
2312 struct scsi_target *starget;
2314 starget = scsi_target(sdev);
2315 vtarget = starget->hostdata;
2316 vdevice = sdev->hostdata;
2318 mptscsih_search_running_cmds(hd, vdevice);
2319 vtarget->num_luns--;
2320 mptscsih_synchronize_cache(hd, vdevice);
2322 sdev->hostdata = NULL;
2325 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2327 * mptscsih_change_queue_depth - This function will set a devices queue depth
2328 * @sdev: per scsi_device pointer
2329 * @qdepth: requested queue depth
2331 * Adding support for new 'change_queue_depth' api.
2334 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2336 MPT_SCSI_HOST *hd = shost_priv(sdev->host);
2337 VirtTarget *vtarget;
2338 struct scsi_target *starget;
2341 MPT_ADAPTER *ioc = hd->ioc;
2343 starget = scsi_target(sdev);
2344 vtarget = starget->hostdata;
2346 if (ioc->bus_type == SPI) {
2347 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2349 else if (sdev->type == TYPE_DISK &&
2350 vtarget->minSyncFactor <= MPT_ULTRA160)
2351 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2353 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2355 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2357 if (qdepth > max_depth)
2362 tagged = MSG_SIMPLE_TAG;
2364 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2365 return sdev->queue_depth;
2369 * OS entry point to adjust the queue_depths on a per-device basis.
2370 * Called once per device the bus scan. Use it to force the queue_depth
2371 * member to 1 if a device does not support Q tags.
2372 * Return non-zero if fails.
2375 mptscsih_slave_configure(struct scsi_device *sdev)
2377 struct Scsi_Host *sh = sdev->host;
2378 VirtTarget *vtarget;
2379 VirtDevice *vdevice;
2380 struct scsi_target *starget;
2381 MPT_SCSI_HOST *hd = shost_priv(sh);
2382 MPT_ADAPTER *ioc = hd->ioc;
2384 starget = scsi_target(sdev);
2385 vtarget = starget->hostdata;
2386 vdevice = sdev->hostdata;
2388 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2389 "device @ %p, channel=%d, id=%d, lun=%d\n",
2390 ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2391 if (ioc->bus_type == SPI)
2392 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2393 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2394 ioc->name, sdev->sdtr, sdev->wdtr,
2395 sdev->ppr, sdev->inquiry_len));
2397 vdevice->configured_lun = 1;
2398 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2400 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2401 "Queue depth=%d, tflags=%x\n",
2402 ioc->name, sdev->queue_depth, vtarget->tflags));
2404 if (ioc->bus_type == SPI)
2405 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2406 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2407 ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2408 vtarget->minSyncFactor));
2410 dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2411 "tagged %d, simple %d, ordered %d\n",
2412 ioc->name,sdev->tagged_supported, sdev->simple_tags,
2413 sdev->ordered_tags));
2418 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2420 * Private routines...
2423 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2424 /* Utility function to copy sense data from the scsi_cmnd buffer
2425 * to the FC and SCSI target structures.
2429 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2431 VirtDevice *vdevice;
2432 SCSIIORequest_t *pReq;
2433 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2434 MPT_ADAPTER *ioc = hd->ioc;
2436 /* Get target structure
2438 pReq = (SCSIIORequest_t *) mf;
2439 vdevice = sc->device->hostdata;
2445 /* Copy the sense received into the scsi command block. */
2446 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2447 sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2448 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2450 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2452 if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2453 if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
2456 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2457 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2458 ioc->events[idx].eventContext = ioc->eventContext;
2460 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2461 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2462 (sc->device->channel << 8) | sc->device->id;
2464 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2466 ioc->eventContext++;
2467 if (ioc->pcidev->vendor ==
2468 PCI_VENDOR_ID_IBM) {
2469 mptscsih_issue_sep_command(ioc,
2470 vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2471 vdevice->vtarget->tflags |=
2472 MPT_TARGET_FLAGS_LED_ON;
2477 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2483 * mptscsih_get_scsi_lookup
2484 * @ioc: Pointer to MPT_ADAPTER structure
2485 * @i: index into the array
2487 * retrieves scmd entry from ScsiLookup[] array list
2489 * Returns the scsi_cmd pointer
2491 static struct scsi_cmnd *
2492 mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2494 unsigned long flags;
2495 struct scsi_cmnd *scmd;
2497 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2498 scmd = ioc->ScsiLookup[i];
2499 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2505 * mptscsih_getclear_scsi_lookup
2506 * @ioc: Pointer to MPT_ADAPTER structure
2507 * @i: index into the array
2509 * retrieves and clears scmd entry from ScsiLookup[] array list
2511 * Returns the scsi_cmd pointer
2513 static struct scsi_cmnd *
2514 mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2516 unsigned long flags;
2517 struct scsi_cmnd *scmd;
2519 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2520 scmd = ioc->ScsiLookup[i];
2521 ioc->ScsiLookup[i] = NULL;
2522 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2528 * mptscsih_set_scsi_lookup
2530 * writes a scmd entry into the ScsiLookup[] array list
2532 * @ioc: Pointer to MPT_ADAPTER structure
2533 * @i: index into the array
2534 * @scmd: scsi_cmnd pointer
2538 mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2540 unsigned long flags;
2542 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2543 ioc->ScsiLookup[i] = scmd;
2544 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2548 * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
2549 * @ioc: Pointer to MPT_ADAPTER structure
2550 * @sc: scsi_cmnd pointer
2553 SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2555 unsigned long flags;
2558 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2559 for (i = 0; i < ioc->req_depth; i++) {
2560 if (ioc->ScsiLookup[i] == sc) {
2567 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2573 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2577 if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
2580 hd = shost_priv(ioc->sh);
2581 switch (reset_phase) {
2582 case MPT_IOC_SETUP_RESET:
2583 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2584 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
2585 hd->resetPending = 1;
2587 case MPT_IOC_PRE_RESET:
2588 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2589 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
2590 hd->resetPending = 0;
2591 mptscsih_flush_running_cmds(hd);
2593 case MPT_IOC_POST_RESET:
2594 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2595 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
2596 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
2597 ioc->internal_cmds.status |=
2598 MPT_MGMT_STATUS_DID_IOCRESET;
2599 complete(&ioc->internal_cmds.done);
2605 return 1; /* currently means nothing really */
2608 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2610 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2613 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2615 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2616 "MPT event (=%02Xh) routed to SCSI host driver!\n",
2619 if (ioc->sh == NULL ||
2620 ((hd = shost_priv(ioc->sh)) == NULL))
2624 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2627 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2628 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2629 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2632 case MPI_EVENT_LOGOUT: /* 09 */
2636 case MPI_EVENT_RESCAN: /* 06 */
2640 * CHECKME! Don't think we need to do
2641 * anything for these, but...
2643 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2644 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2646 * CHECKME! Falling thru...
2650 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2653 case MPI_EVENT_NONE: /* 00 */
2654 case MPI_EVENT_LOG_DATA: /* 01 */
2655 case MPI_EVENT_STATE_CHANGE: /* 02 */
2656 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2658 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2659 ": Ignoring event (=%02Xh)\n",
2664 return 1; /* currently means nothing really */
2667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2669 * Bus Scan and Domain Validation functionality ...
2672 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2674 * mptscsih_scandv_complete - Scan and DV callback routine registered
2675 * to Fustion MPT (base) driver.
2677 * @ioc: Pointer to MPT_ADAPTER structure
2678 * @mf: Pointer to original MPT request frame
2679 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2681 * This routine is called from mpt.c::mpt_interrupt() at the completion
2682 * of any SCSI IO request.
2683 * This routine is registered with the Fusion MPT (base) driver at driver
2684 * load/init time via the mpt_register() API call.
2686 * Returns 1 indicating alloc'd request frame ptr should be freed.
2688 * Remark: Sets a completion code and (possibly) saves sense data
2689 * in the IOC member localReply structure.
2690 * Used ONLY for DV and other internal commands.
2693 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2694 MPT_FRAME_HDR *reply)
2696 SCSIIORequest_t *pReq;
2697 SCSIIOReply_t *pReply;
2703 ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2704 ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
2708 pReply = (SCSIIOReply_t *) reply;
2709 pReq = (SCSIIORequest_t *) req;
2710 ioc->internal_cmds.completion_code =
2711 mptscsih_get_completion_code(ioc, req, reply);
2712 ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2713 memcpy(ioc->internal_cmds.reply, reply,
2714 min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
2715 cmd = reply->u.hdr.Function;
2716 if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
2717 (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
2718 (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
2719 req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
2720 sense_data = ((u8 *)ioc->sense_buf_pool +
2721 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2722 sz = min_t(int, pReq->SenseBufferLength,
2723 MPT_SENSE_BUFFER_ALLOC);
2724 memcpy(ioc->internal_cmds.sense, sense_data, sz);
2727 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
2729 ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2730 complete(&ioc->internal_cmds.done);
2734 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2735 /* mptscsih_timer_expired - Call back for timer process.
2736 * Used only for dv functionality.
2737 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2741 mptscsih_timer_expired(unsigned long data)
2743 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2744 MPT_ADAPTER *ioc = hd->ioc;
2746 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr));
2749 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2751 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2752 /* Desire to issue a task management request here.
2753 * TM requests MUST be single threaded.
2754 * If old eh code and no TM current, issue request.
2755 * If new eh code, do nothing. Wait for OS cmd timeout
2759 /* Perform a FW reload */
2760 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2761 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
2765 /* This should NEVER happen */
2766 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name);
2769 /* No more processing.
2770 * TM call will generate an interrupt for SCSI TM Management.
2771 * The FW will reply to all outstanding commands, callback will finish cleanup.
2772 * Hard reset clean-up will free all resources.
2774 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name));
2780 * mptscsih_get_completion_code -
2781 * @ioc: Pointer to MPT_ADAPTER structure
2787 mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2788 MPT_FRAME_HDR *reply)
2790 SCSIIOReply_t *pReply;
2791 MpiRaidActionReply_t *pr;
2794 int completion_code;
2796 pReply = (SCSIIOReply_t *)reply;
2797 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2798 scsi_status = pReply->SCSIStatus;
2800 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2801 "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh,"
2802 "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState,
2803 scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
2807 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2808 completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
2811 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2812 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2813 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2814 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2815 completion_code = MPT_SCANDV_DID_RESET;
2818 case MPI_IOCSTATUS_BUSY:
2819 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
2820 completion_code = MPT_SCANDV_BUSY;
2823 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2824 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2825 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2826 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2827 completion_code = MPT_SCANDV_GOOD;
2828 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2829 pr = (MpiRaidActionReply_t *)reply;
2830 if (le16_to_cpu(pr->ActionStatus) ==
2831 MPI_RAID_ACTION_ASTATUS_SUCCESS)
2832 completion_code = MPT_SCANDV_GOOD;
2834 completion_code = MPT_SCANDV_SOME_ERROR;
2835 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
2836 completion_code = MPT_SCANDV_SENSE;
2837 else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2838 if (req->u.scsireq.CDB[0] == INQUIRY)
2839 completion_code = MPT_SCANDV_ISSUE_SENSE;
2841 completion_code = MPT_SCANDV_DID_RESET;
2842 } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2843 completion_code = MPT_SCANDV_DID_RESET;
2844 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2845 completion_code = MPT_SCANDV_DID_RESET;
2846 else if (scsi_status == MPI_SCSI_STATUS_BUSY)
2847 completion_code = MPT_SCANDV_BUSY;
2849 completion_code = MPT_SCANDV_GOOD;
2852 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2853 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2854 completion_code = MPT_SCANDV_DID_RESET;
2856 completion_code = MPT_SCANDV_SOME_ERROR;
2859 completion_code = MPT_SCANDV_SOME_ERROR;
2862 } /* switch(status) */
2864 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2865 " completionCode set to %08xh\n", ioc->name, completion_code));
2866 return completion_code;
2869 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2871 * mptscsih_do_cmd - Do internal command.
2872 * @hd: MPT_SCSI_HOST pointer
2873 * @io: INTERNAL_CMD pointer.
2875 * Issue the specified internally generated command and do command
2876 * specific cleanup. For bus scan / DV only.
2877 * NOTES: If command is Inquiry and status is good,
2878 * initialize a target structure, save the data
2880 * Remark: Single threaded access only.
2883 * < 0 if an illegal command or no resources
2887 * > 0 if command complete but some type of completion error.
2890 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2893 SCSIIORequest_t *pScsiReq;
2894 int my_idx, ii, dir;
2897 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2899 MPT_ADAPTER *ioc = hd->ioc;
2901 unsigned long timeleft;
2902 unsigned long flags;
2904 mutex_lock(&ioc->internal_cmds.mutex);
2906 /* Set command specific information
2911 dir = MPI_SCSIIO_CONTROL_READ;
2917 case TEST_UNIT_READY:
2919 dir = MPI_SCSIIO_CONTROL_READ;
2925 dir = MPI_SCSIIO_CONTROL_READ;
2927 CDB[4] = 1; /*Spin up the disk */
2935 dir = MPI_SCSIIO_CONTROL_READ;
2941 dir = MPI_SCSIIO_CONTROL_READ;
2943 if (io->flags & MPT_ICFLAG_ECHO) {
2949 if (io->flags & MPT_ICFLAG_BUF_CAP) {
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_WRITE;
2962 if (io->flags & MPT_ICFLAG_ECHO) {
2967 CDB[6] = (io->size >> 16) & 0xFF;
2968 CDB[7] = (io->size >> 8) & 0xFF;
2969 CDB[8] = io->size & 0xFF;
2975 dir = MPI_SCSIIO_CONTROL_READ;
2982 dir = MPI_SCSIIO_CONTROL_READ;
2987 case SYNCHRONIZE_CACHE:
2989 dir = MPI_SCSIIO_CONTROL_READ;
2991 // CDB[1] = 0x02; /* set immediate bit */
3001 /* Get and Populate a free Frame
3002 * MsgContext set in mpt_get_msg_frame call
3004 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
3005 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
3006 ioc->name, __func__));
3007 ret = MPT_SCANDV_BUSY;
3011 pScsiReq = (SCSIIORequest_t *) mf;
3013 /* Get the request index */
3014 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3015 ADD_INDEX_LOG(my_idx); /* for debug */
3017 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3018 pScsiReq->TargetID = io->physDiskNum;
3020 pScsiReq->ChainOffset = 0;
3021 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3023 pScsiReq->TargetID = io->id;
3024 pScsiReq->Bus = io->channel;
3025 pScsiReq->ChainOffset = 0;
3026 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3029 pScsiReq->CDBLength = cmdLen;
3030 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3032 pScsiReq->Reserved = 0;
3034 pScsiReq->MsgFlags = mpt_msg_flags(ioc);
3035 /* MsgContext set in mpt_get_msg_fram call */
3037 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3039 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3040 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3042 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3044 if (cmd == REQUEST_SENSE) {
3045 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3046 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3047 "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd));
3050 for (ii = 0; ii < 16; ii++)
3051 pScsiReq->CDB[ii] = CDB[ii];
3053 pScsiReq->DataLength = cpu_to_le32(io->size);
3054 pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
3055 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3057 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3058 "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n",
3059 ioc->name, __func__, cmd, io->channel, io->id, io->lun));
3061 if (dir == MPI_SCSIIO_CONTROL_READ)
3062 ioc->add_sge((char *) &pScsiReq->SGL,
3063 MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
3065 ioc->add_sge((char *) &pScsiReq->SGL,
3066 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
3068 INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
3069 mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
3070 timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
3072 if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
3073 ret = MPT_SCANDV_DID_RESET;
3074 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3075 "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__,
3077 if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
3078 mpt_free_msg_frame(ioc, mf);
3082 printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",
3083 ioc->name, __func__);
3084 mpt_HardResetHandler(ioc, CAN_SLEEP);
3085 mpt_free_msg_frame(ioc, mf);
3090 ret = ioc->internal_cmds.completion_code;
3091 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
3092 ioc->name, __func__, ret));
3095 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
3096 mutex_unlock(&ioc->internal_cmds.mutex);
3100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3102 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3103 * @hd: Pointer to a SCSI HOST structure
3104 * @vdevice: virtual target device
3106 * Uses the ISR, but with special processing.
3107 * MUST be single-threaded.
3111 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3115 /* Ignore hidden raid components, this is handled when the command
3116 * is sent to the volume
3118 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3121 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3122 !vdevice->configured_lun)
3125 /* Following parameters will not change
3128 iocmd.cmd = SYNCHRONIZE_CACHE;
3130 iocmd.physDiskNum = -1;
3132 iocmd.data_dma = -1;
3134 iocmd.rsvd = iocmd.rsvd2 = 0;
3135 iocmd.channel = vdevice->vtarget->channel;
3136 iocmd.id = vdevice->vtarget->id;
3137 iocmd.lun = vdevice->lun;
3139 mptscsih_do_cmd(hd, &iocmd);
3143 mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
3146 struct Scsi_Host *host = class_to_shost(dev);
3147 MPT_SCSI_HOST *hd = shost_priv(host);
3148 MPT_ADAPTER *ioc = hd->ioc;
3150 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3151 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3152 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3153 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3154 ioc->facts.FWVersion.Word & 0x000000FF);
3156 static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
3159 mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
3162 struct Scsi_Host *host = class_to_shost(dev);
3163 MPT_SCSI_HOST *hd = shost_priv(host);
3164 MPT_ADAPTER *ioc = hd->ioc;
3166 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3167 (ioc->biosVersion & 0xFF000000) >> 24,
3168 (ioc->biosVersion & 0x00FF0000) >> 16,
3169 (ioc->biosVersion & 0x0000FF00) >> 8,
3170 ioc->biosVersion & 0x000000FF);
3172 static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
3175 mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
3178 struct Scsi_Host *host = class_to_shost(dev);
3179 MPT_SCSI_HOST *hd = shost_priv(host);
3180 MPT_ADAPTER *ioc = hd->ioc;
3182 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3184 static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
3187 mptscsih_version_product_show(struct device *dev,
3188 struct device_attribute *attr,
3191 struct Scsi_Host *host = class_to_shost(dev);
3192 MPT_SCSI_HOST *hd = shost_priv(host);
3193 MPT_ADAPTER *ioc = hd->ioc;
3195 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3197 static DEVICE_ATTR(version_product, S_IRUGO,
3198 mptscsih_version_product_show, NULL);
3201 mptscsih_version_nvdata_persistent_show(struct device *dev,
3202 struct device_attribute *attr,
3205 struct Scsi_Host *host = class_to_shost(dev);
3206 MPT_SCSI_HOST *hd = shost_priv(host);
3207 MPT_ADAPTER *ioc = hd->ioc;
3209 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3210 ioc->nvdata_version_persistent);
3212 static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
3213 mptscsih_version_nvdata_persistent_show, NULL);
3216 mptscsih_version_nvdata_default_show(struct device *dev,
3217 struct device_attribute *attr, char *buf)
3219 struct Scsi_Host *host = class_to_shost(dev);
3220 MPT_SCSI_HOST *hd = shost_priv(host);
3221 MPT_ADAPTER *ioc = hd->ioc;
3223 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3225 static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
3226 mptscsih_version_nvdata_default_show, NULL);
3229 mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
3232 struct Scsi_Host *host = class_to_shost(dev);
3233 MPT_SCSI_HOST *hd = shost_priv(host);
3234 MPT_ADAPTER *ioc = hd->ioc;
3236 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3238 static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
3241 mptscsih_board_assembly_show(struct device *dev,
3242 struct device_attribute *attr, char *buf)
3244 struct Scsi_Host *host = class_to_shost(dev);
3245 MPT_SCSI_HOST *hd = shost_priv(host);
3246 MPT_ADAPTER *ioc = hd->ioc;
3248 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3250 static DEVICE_ATTR(board_assembly, S_IRUGO,
3251 mptscsih_board_assembly_show, NULL);
3254 mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
3257 struct Scsi_Host *host = class_to_shost(dev);
3258 MPT_SCSI_HOST *hd = shost_priv(host);
3259 MPT_ADAPTER *ioc = hd->ioc;
3261 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3263 static DEVICE_ATTR(board_tracer, S_IRUGO,
3264 mptscsih_board_tracer_show, NULL);
3267 mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
3270 struct Scsi_Host *host = class_to_shost(dev);
3271 MPT_SCSI_HOST *hd = shost_priv(host);
3272 MPT_ADAPTER *ioc = hd->ioc;
3274 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3276 static DEVICE_ATTR(io_delay, S_IRUGO,
3277 mptscsih_io_delay_show, NULL);
3280 mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
3283 struct Scsi_Host *host = class_to_shost(dev);
3284 MPT_SCSI_HOST *hd = shost_priv(host);
3285 MPT_ADAPTER *ioc = hd->ioc;
3287 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3289 static DEVICE_ATTR(device_delay, S_IRUGO,
3290 mptscsih_device_delay_show, NULL);
3293 mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
3296 struct Scsi_Host *host = class_to_shost(dev);
3297 MPT_SCSI_HOST *hd = shost_priv(host);
3298 MPT_ADAPTER *ioc = hd->ioc;
3300 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3303 mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
3304 const char *buf, size_t count)
3306 struct Scsi_Host *host = class_to_shost(dev);
3307 MPT_SCSI_HOST *hd = shost_priv(host);
3308 MPT_ADAPTER *ioc = hd->ioc;
3311 if (sscanf(buf, "%x", &val) != 1)
3314 ioc->debug_level = val;
3315 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3316 ioc->name, ioc->debug_level);
3319 static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3320 mptscsih_debug_level_show, mptscsih_debug_level_store);
3322 struct device_attribute *mptscsih_host_attrs[] = {
3323 &dev_attr_version_fw,
3324 &dev_attr_version_bios,
3325 &dev_attr_version_mpi,
3326 &dev_attr_version_product,
3327 &dev_attr_version_nvdata_persistent,
3328 &dev_attr_version_nvdata_default,
3329 &dev_attr_board_name,
3330 &dev_attr_board_assembly,
3331 &dev_attr_board_tracer,
3333 &dev_attr_device_delay,
3334 &dev_attr_debug_level,
3338 EXPORT_SYMBOL(mptscsih_host_attrs);
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 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/