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-2007 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 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
84 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
85 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
87 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
88 SCSIIORequest_t *pReq, int req_idx);
89 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
90 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
91 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
92 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
93 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
95 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
97 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
98 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
100 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
101 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
102 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
104 void mptscsih_remove(struct pci_dev *);
105 void mptscsih_shutdown(struct pci_dev *);
107 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
108 int mptscsih_resume(struct pci_dev *pdev);
111 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
113 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
115 * mptscsih_add_sge - Place a simple SGE at address pAddr.
116 * @pAddr: virtual address for SGE
117 * @flagslength: SGE flags and data transfer length
118 * @dma_addr: Physical address
120 * This routine places a MPT request frame back on the MPT adapter's
124 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
126 if (sizeof(dma_addr_t) == sizeof(u64)) {
127 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
128 u32 tmp = dma_addr & 0xFFFFFFFF;
130 pSge->FlagsLength = cpu_to_le32(flagslength);
131 pSge->Address.Low = cpu_to_le32(tmp);
132 tmp = (u32) ((u64)dma_addr >> 32);
133 pSge->Address.High = cpu_to_le32(tmp);
136 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
137 pSge->FlagsLength = cpu_to_le32(flagslength);
138 pSge->Address = cpu_to_le32(dma_addr);
140 } /* mptscsih_add_sge() */
142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
144 * mptscsih_add_chain - Place a chain SGE at address pAddr.
145 * @pAddr: virtual address for SGE
146 * @next: nextChainOffset value (u32's)
147 * @length: length of next SGL segment
148 * @dma_addr: Physical address
150 * This routine places a MPT request frame back on the MPT adapter's
154 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
156 if (sizeof(dma_addr_t) == sizeof(u64)) {
157 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
158 u32 tmp = dma_addr & 0xFFFFFFFF;
160 pChain->Length = cpu_to_le16(length);
161 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
163 pChain->NextChainOffset = next;
165 pChain->Address.Low = cpu_to_le32(tmp);
166 tmp = (u32) ((u64)dma_addr >> 32);
167 pChain->Address.High = cpu_to_le32(tmp);
169 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
170 pChain->Length = cpu_to_le16(length);
171 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
172 pChain->NextChainOffset = next;
173 pChain->Address = cpu_to_le32(dma_addr);
175 } /* mptscsih_add_chain() */
177 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
179 * mptscsih_getFreeChainBuffer - Function to get a free chain
180 * from the MPT_SCSI_HOST FreeChainQ.
181 * @ioc: Pointer to MPT_ADAPTER structure
182 * @req_idx: Index of the SCSI IO request frame. (output)
184 * return SUCCESS or FAILED
187 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
189 MPT_FRAME_HDR *chainBuf;
194 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
196 spin_lock_irqsave(&ioc->FreeQlock, flags);
197 if (!list_empty(&ioc->FreeChainQ)) {
200 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
201 u.frame.linkage.list);
202 list_del(&chainBuf->u.frame.linkage.list);
203 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
204 chain_idx = offset / ioc->req_sz;
206 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
207 "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
208 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
211 chain_idx = MPT_HOST_NO_CHAIN;
212 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
215 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
217 *retIndex = chain_idx;
219 } /* mptscsih_getFreeChainBuffer() */
221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
223 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
224 * SCSIIORequest_t Message Frame.
225 * @ioc: Pointer to MPT_ADAPTER structure
226 * @SCpnt: Pointer to scsi_cmnd structure
227 * @pReq: Pointer to SCSIIORequest_t structure
232 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
233 SCSIIORequest_t *pReq, int req_idx)
237 struct scatterlist *sg;
239 int sges_left, sg_done;
240 int chain_idx = MPT_HOST_NO_CHAIN;
242 int numSgeSlots, numSgeThisFrame;
243 u32 sgflags, sgdir, thisxfer = 0;
244 int chain_dma_off = 0;
250 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
251 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
252 sgdir = MPT_TRANSFER_HOST_TO_IOC;
254 sgdir = MPT_TRANSFER_IOC_TO_HOST;
257 psge = (char *) &pReq->SGL;
258 frm_sz = ioc->req_sz;
260 /* Map the data portion, if any.
261 * sges_left = 0 if no data transfer.
263 sges_left = scsi_dma_map(SCpnt);
267 /* Handle the SG case.
269 sg = scsi_sglist(SCpnt);
271 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
274 /* Prior to entering this loop - the following must be set
275 * current MF: sgeOffset (bytes)
276 * chainSge (Null if original MF is not a chain buffer)
277 * sg_done (num SGE done for this MF)
281 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
282 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
284 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
286 /* Get first (num - 1) SG elements
287 * Skip any SG entries with a length of 0
288 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
290 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
291 thisxfer = sg_dma_len(sg);
293 sg ++; /* Get next SG element from the OS */
298 v2 = sg_dma_address(sg);
299 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
301 sg++; /* Get next SG element from the OS */
302 psge += (sizeof(u32) + sizeof(dma_addr_t));
303 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
307 if (numSgeThisFrame == sges_left) {
308 /* Add last element, end of buffer and end of list flags.
310 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
311 MPT_SGE_FLAGS_END_OF_BUFFER |
312 MPT_SGE_FLAGS_END_OF_LIST;
314 /* Add last SGE and set termination flags.
315 * Note: Last SGE may have a length of 0 - which should be ok.
317 thisxfer = sg_dma_len(sg);
319 v2 = sg_dma_address(sg);
320 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
323 psge += (sizeof(u32) + sizeof(dma_addr_t));
325 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
329 /* The current buffer is a chain buffer,
330 * but there is not another one.
331 * Update the chain element
332 * Offset and Length fields.
334 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
336 /* The current buffer is the original MF
337 * and there is no Chain buffer.
339 pReq->ChainOffset = 0;
340 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
341 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
342 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
343 ioc->RequestNB[req_idx] = RequestNB;
346 /* At least one chain buffer is needed.
347 * Complete the first MF
348 * - last SGE element, set the LastElement bit
349 * - set ChainOffset (words) for orig MF
350 * (OR finish previous MF chain buffer)
351 * - update MFStructPtr ChainIndex
352 * - Populate chain element
357 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n",
358 ioc->name, sg_done));
360 /* Set LAST_ELEMENT flag for last non-chain element
361 * in the buffer. Since psge points at the NEXT
362 * SGE element, go back one SGE element, update the flags
363 * and reset the pointer. (Note: sgflags & thisxfer are already
367 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
368 sgflags = le32_to_cpu(*ptmp);
369 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
370 *ptmp = cpu_to_le32(sgflags);
374 /* The current buffer is a chain buffer.
375 * chainSge points to the previous Chain Element.
376 * Update its chain element Offset and Length (must
377 * include chain element size) fields.
378 * Old chain element is now complete.
380 u8 nextChain = (u8) (sgeOffset >> 2);
381 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
382 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
384 /* The original MF buffer requires a chain buffer -
386 * Last element in this MF is a chain element.
388 pReq->ChainOffset = (u8) (sgeOffset >> 2);
389 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
390 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
391 ioc->RequestNB[req_idx] = RequestNB;
394 sges_left -= sg_done;
397 /* NOTE: psge points to the beginning of the chain element
398 * in current buffer. Get a chain buffer.
400 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
401 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
402 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
403 ioc->name, pReq->CDB[0], SCpnt));
407 /* Update the tracking arrays.
408 * If chainSge == NULL, update ReqToChain, else ChainToChain
411 ioc->ChainToChain[chain_idx] = newIndex;
413 ioc->ReqToChain[req_idx] = newIndex;
415 chain_idx = newIndex;
416 chain_dma_off = ioc->req_sz * chain_idx;
418 /* Populate the chainSGE for the current buffer.
419 * - Set chain buffer pointer to psge and fill
420 * out the Address and Flags fields.
422 chainSge = (char *) psge;
423 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)",
424 ioc->name, psge, req_idx));
426 /* Start the SGE for the next buffer
428 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
432 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n",
433 ioc->name, psge, chain_idx));
435 /* Start the SGE for the next buffer
442 } /* mptscsih_AddSGE() */
445 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
449 SEPRequest_t *SEPMsg;
451 if (ioc->bus_type != SAS)
454 /* Not supported for hidden raid components
456 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
459 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
460 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
461 ioc->name,__FUNCTION__));
465 SEPMsg = (SEPRequest_t *)mf;
466 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
467 SEPMsg->Bus = vtarget->channel;
468 SEPMsg->TargetID = vtarget->id;
469 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
470 SEPMsg->SlotStatus = SlotStatus;
471 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
472 "Sending SEP cmd=%x channel=%d id=%d\n",
473 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
474 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
477 #ifdef CONFIG_FUSION_LOGGING
479 * mptscsih_info_scsiio - debug print info on reply frame
480 * @ioc: Pointer to MPT_ADAPTER structure
481 * @sc: original scsi cmnd pointer
482 * @pScsiReply: Pointer to MPT reply frame
484 * MPT_DEBUG_REPLY needs to be enabled to obtain this info
486 * Refer to lsi/mpi.h.
489 mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
496 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
498 switch (ioc_status) {
500 case MPI_IOCSTATUS_SUCCESS:
503 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
504 desc = "invalid bus";
506 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
507 desc = "invalid target_id";
509 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
510 desc = "device not there";
512 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
513 desc = "data overrun";
515 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
516 desc = "data underrun";
518 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
519 desc = "I/O data error";
521 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
522 desc = "protocol error";
524 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
525 desc = "task terminated";
527 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
528 desc = "residual mismatch";
530 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
531 desc = "task management failed";
533 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
534 desc = "IOC terminated";
536 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
537 desc = "ext terminated";
544 switch (pScsiReply->SCSIStatus)
547 case MPI_SCSI_STATUS_SUCCESS:
550 case MPI_SCSI_STATUS_CHECK_CONDITION:
551 desc1 = "check condition";
553 case MPI_SCSI_STATUS_CONDITION_MET:
554 desc1 = "condition met";
556 case MPI_SCSI_STATUS_BUSY:
559 case MPI_SCSI_STATUS_INTERMEDIATE:
560 desc1 = "intermediate";
562 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
563 desc1 = "intermediate condmet";
565 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
566 desc1 = "reservation conflict";
568 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
569 desc1 = "command terminated";
571 case MPI_SCSI_STATUS_TASK_SET_FULL:
572 desc1 = "task set full";
574 case MPI_SCSI_STATUS_ACA_ACTIVE:
575 desc1 = "aca active";
577 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
578 desc1 = "fcpext device logged out";
580 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
581 desc1 = "fcpext no link";
583 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
584 desc1 = "fcpext unassigned";
591 scsi_print_command(sc);
592 printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",
593 ioc->name, pScsiReply->Bus, pScsiReply->TargetID);
594 printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "
595 "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,
597 printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "
598 "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),
599 le32_to_cpu(pScsiReply->TransferCount), sc->result);
600 printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "
601 "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
602 ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,
603 pScsiReply->SCSIState);
605 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
606 skey = sc->sense_buffer[2] & 0x0F;
607 asc = sc->sense_buffer[12];
608 ascq = sc->sense_buffer[13];
610 printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "
611 "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);
615 * Look for + dump FCP ResponseInfo[]!
617 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
618 pScsiReply->ResponseInfo)
619 printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",
620 ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));
624 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
626 * mptscsih_io_done - Main SCSI IO callback routine registered to
627 * Fusion MPT (base) driver
628 * @ioc: Pointer to MPT_ADAPTER structure
629 * @mf: Pointer to original MPT request frame
630 * @r: Pointer to MPT reply frame (NULL if TurboReply)
632 * This routine is called from mpt.c::mpt_interrupt() at the completion
633 * of any SCSI IO request.
634 * This routine is registered with the Fusion MPT (base) driver at driver
635 * load/init time via the mpt_register() API call.
637 * Returns 1 indicating alloc'd request frame ptr should be freed.
640 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
642 struct scsi_cmnd *sc;
644 SCSIIORequest_t *pScsiReq;
645 SCSIIOReply_t *pScsiReply;
646 u16 req_idx, req_idx_MR;
650 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
652 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
653 req_idx_MR = (mr != NULL) ?
654 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
655 if ((req_idx != req_idx_MR) ||
656 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
657 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
659 printk (MYIOC_s_ERR_FMT
660 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
661 ioc->name, req_idx, req_idx_MR, mf, mr,
662 hd->ScsiLookup[req_idx_MR]);
666 sc = hd->ScsiLookup[req_idx];
667 hd->ScsiLookup[req_idx] = NULL;
669 MPIHeader_t *hdr = (MPIHeader_t *)mf;
671 /* Remark: writeSDP1 will use the ScsiDoneCtx
672 * If a SCSI I/O cmd, device disabled by OS and
673 * completion done. Cannot touch sc struct. Just free mem.
675 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
676 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
679 mptscsih_freeChainBuffers(ioc, req_idx);
683 if ((unsigned char *)mf != sc->host_scribble) {
684 mptscsih_freeChainBuffers(ioc, req_idx);
688 sc->host_scribble = NULL;
689 sc->result = DID_OK << 16; /* Set default reply as OK */
690 pScsiReq = (SCSIIORequest_t *) mf;
691 pScsiReply = (SCSIIOReply_t *) mr;
693 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
694 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
695 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
696 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
698 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
699 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
700 ioc->name, mf, mr, sc, req_idx));
703 if (pScsiReply == NULL) {
704 /* special context reply handling */
709 u8 scsi_state, scsi_status;
712 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
713 scsi_state = pScsiReply->SCSIState;
714 scsi_status = pScsiReply->SCSIStatus;
715 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
716 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
717 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
720 * if we get a data underrun indication, yet no data was
721 * transferred and the SCSI status indicates that the
722 * command was never started, change the data underrun
725 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
726 (scsi_status == MPI_SCSI_STATUS_BUSY ||
727 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
728 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
729 status = MPI_IOCSTATUS_SUCCESS;
732 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
733 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
736 * Look for + dump FCP ResponseInfo[]!
738 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
739 pScsiReply->ResponseInfo) {
740 printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "
741 "FCP_ResponseInfo=%08xh\n", ioc->name,
742 sc->device->host->host_no, sc->device->channel,
743 sc->device->id, sc->device->lun,
744 le32_to_cpu(pScsiReply->ResponseInfo));
748 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
750 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
751 * But not: DID_BUS_BUSY lest one risk
752 * killing interrupt handler:-(
754 sc->result = SAM_STAT_BUSY;
757 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
758 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
759 sc->result = DID_BAD_TARGET << 16;
762 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
763 /* Spoof to SCSI Selection Timeout! */
764 if (ioc->bus_type != FC)
765 sc->result = DID_NO_CONNECT << 16;
766 /* else fibre, just stall until rescan event */
768 sc->result = DID_REQUEUE << 16;
770 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
771 hd->sel_timeout[pScsiReq->TargetID]++;
773 vdevice = sc->device->hostdata;
776 vtarget = vdevice->vtarget;
777 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
778 mptscsih_issue_sep_command(ioc, vtarget,
779 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
780 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
784 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
785 if ( ioc->bus_type == SAS ) {
786 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
787 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
788 if ((log_info & SAS_LOGINFO_MASK)
789 == SAS_LOGINFO_NEXUS_LOSS) {
790 sc->result = (DID_BUS_BUSY << 16);
794 } else if (ioc->bus_type == FC) {
796 * The FC IOC may kill a request for variety of
797 * reasons, some of which may be recovered by a
798 * retry, some which are unlikely to be
799 * recovered. Return DID_ERROR instead of
800 * DID_RESET to permit retry of the command,
801 * just not an infinite number of them
803 sc->result = DID_ERROR << 16;
808 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
811 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
812 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
813 /* Linux handles an unsolicited DID_RESET better
814 * than an unsolicited DID_ABORT.
816 sc->result = DID_RESET << 16;
820 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
821 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
822 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
823 sc->result=DID_SOFT_ERROR << 16;
824 else /* Sufficient data transfer occurred */
825 sc->result = (DID_OK << 16) | scsi_status;
826 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
827 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
828 ioc->name, sc->result, sc->device->channel, sc->device->id));
831 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
833 * Do upfront check for valid SenseData and give it
836 sc->result = (DID_OK << 16) | scsi_status;
837 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
838 /* Have already saved the status and sense data
842 if (xfer_cnt < sc->underflow) {
843 if (scsi_status == SAM_STAT_BUSY)
844 sc->result = SAM_STAT_BUSY;
846 sc->result = DID_SOFT_ERROR << 16;
848 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
851 sc->result = DID_SOFT_ERROR << 16;
853 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
854 /* Not real sure here either... */
855 sc->result = DID_RESET << 16;
860 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
861 " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
862 ioc->name, sc->underflow));
863 dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT
864 " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));
868 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
869 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
873 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
874 scsi_set_resid(sc, 0);
875 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
876 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
877 sc->result = (DID_OK << 16) | scsi_status;
878 if (scsi_state == 0) {
880 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
882 * If running against circa 200003dd 909 MPT f/w,
883 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
884 * (QUEUE_FULL) returned from device! --> get 0x0000?128
885 * and with SenseBytes set to 0.
887 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
888 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
891 else if (scsi_state &
892 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
897 sc->result = DID_SOFT_ERROR << 16;
899 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
900 /* Not real sure here either... */
901 sc->result = DID_RESET << 16;
903 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
904 /* Device Inq. data indicates that it supports
905 * QTags, but rejects QTag messages.
906 * This command completed OK.
908 * Not real sure here either so do nothing... */
911 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
912 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
915 * Reservation Conflict, Busy,
916 * Command Terminated, CHECK
920 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
921 sc->result = DID_SOFT_ERROR << 16;
924 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
925 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
926 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
927 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
928 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
929 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
930 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
931 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
932 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
937 sc->result = DID_SOFT_ERROR << 16;
940 } /* switch(status) */
942 #ifdef CONFIG_FUSION_LOGGING
943 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
944 mptscsih_info_scsiio(ioc, sc, pScsiReply);
947 } /* end of address reply case */
949 /* Unmap the DMA buffers, if any. */
952 sc->scsi_done(sc); /* Issue the command callback */
954 /* Free Chain buffers */
955 mptscsih_freeChainBuffers(ioc, req_idx);
960 * mptscsih_flush_running_cmds - For each command found, search
961 * Scsi_Host instance taskQ and reply to OS.
962 * Called only if recovering from a FW reload.
963 * @hd: Pointer to a SCSI HOST structure
967 * Must be called while new I/Os are being queued.
970 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
972 MPT_ADAPTER *ioc = hd->ioc;
973 struct scsi_cmnd *SCpnt;
976 int max = ioc->req_depth;
978 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush_ScsiLookup called\n", ioc->name));
979 for (ii= 0; ii < max; ii++) {
980 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
985 /* Null ScsiLookup index
987 hd->ScsiLookup[ii] = NULL;
989 mf = MPT_INDEX_2_MFPTR(ioc, ii);
990 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": flush: ScsiDone (mf=%p,sc=%p)\n",
991 ioc->name, mf, SCpnt));
993 /* Free Chain buffers */
994 mptscsih_freeChainBuffers(ioc, ii);
996 /* Free Message frames */
997 mpt_free_msg_frame(ioc, mf);
999 if ((unsigned char *)mf != SCpnt->host_scribble)
1002 /* Set status, free OS resources (SG DMA buffers)
1005 scsi_dma_unmap(SCpnt);
1007 SCpnt->result = DID_RESET << 16;
1008 SCpnt->host_scribble = NULL;
1010 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1018 * mptscsih_search_running_cmds - Delete any commands associated
1019 * with the specified target and lun. Function called only
1020 * when a lun is disable by mid-layer.
1021 * Do NOT access the referenced scsi_cmnd structure or
1022 * members. Will cause either a paging or NULL ptr error.
1023 * (BUT, BUT, BUT, the code does reference it! - mdr)
1024 * @hd: Pointer to a SCSI HOST structure
1025 * @vdevice: per device private data
1029 * Called from slave_destroy.
1032 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1034 SCSIIORequest_t *mf = NULL;
1036 int max = hd->ioc->req_depth;
1037 struct scsi_cmnd *sc;
1038 struct scsi_lun lun;
1040 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT ": search_running channel %d id %d lun %d max %d\n",
1041 hd->ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
1043 for (ii=0; ii < max; ii++) {
1044 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1046 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1049 /* If the device is a hidden raid component, then its
1050 * expected that the mf->function will be RAID_SCSI_IO
1052 if (vdevice->vtarget->tflags &
1053 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
1054 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
1057 int_to_scsilun(vdevice->lun, &lun);
1058 if ((mf->Bus != vdevice->vtarget->channel) ||
1059 (mf->TargetID != vdevice->vtarget->id) ||
1060 memcmp(lun.scsi_lun, mf->LUN, 8))
1065 hd->ScsiLookup[ii] = NULL;
1066 mptscsih_freeChainBuffers(hd->ioc, ii);
1067 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1068 if ((unsigned char *)mf != sc->host_scribble)
1071 sc->host_scribble = NULL;
1072 sc->result = DID_NO_CONNECT << 16;
1073 sdev_printk(MYIOC_s_INFO_FMT, sc->device, "completing cmds: fw_channel %d,"
1074 "fw_id %d, sc=%p, mf = %p, idx=%x\n", hd->ioc->name, vdevice->vtarget->channel,
1075 vdevice->vtarget->id, sc, mf, ii);
1082 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1084 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1086 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1087 * from a SCSI target device.
1088 * @sc: Pointer to scsi_cmnd structure
1089 * @pScsiReply: Pointer to SCSIIOReply_t
1090 * @pScsiReq: Pointer to original SCSI request
1092 * This routine periodically reports QUEUE_FULL status returned from a
1093 * SCSI target device. It reports this to the console via kernel
1094 * printk() API call, not more than once every 10 seconds.
1097 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1099 long time = jiffies;
1102 if (sc->device == NULL)
1104 if (sc->device->host == NULL)
1106 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1109 if (time - hd->last_queue_full > 10 * HZ) {
1110 dprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1111 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1112 hd->last_queue_full = time;
1116 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1118 * mptscsih_remove - Removed scsi devices
1119 * @pdev: Pointer to pci_dev structure
1124 mptscsih_remove(struct pci_dev *pdev)
1126 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1127 struct Scsi_Host *host = ioc->sh;
1136 scsi_remove_host(host);
1138 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1141 mptscsih_shutdown(pdev);
1145 if (hd->ScsiLookup != NULL) {
1146 sz1 = hd->ioc->req_depth * sizeof(void *);
1147 kfree(hd->ScsiLookup);
1148 hd->ScsiLookup = NULL;
1151 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
1152 "Free'd ScsiLookup (%d) memory\n",
1153 hd->ioc->name, sz1));
1155 kfree(hd->info_kbuf);
1157 /* NULL the Scsi_Host pointer
1161 scsi_host_put(host);
1167 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1169 * mptscsih_shutdown - reboot notifier
1173 mptscsih_shutdown(struct pci_dev *pdev)
1175 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1176 struct Scsi_Host *host = ioc->sh;
1182 hd = (MPT_SCSI_HOST *)host->hostdata;
1187 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1189 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1194 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1196 mptscsih_shutdown(pdev);
1197 return mpt_suspend(pdev,state);
1200 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1202 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1207 mptscsih_resume(struct pci_dev *pdev)
1209 return mpt_resume(pdev);
1214 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1216 * mptscsih_info - Return information about MPT adapter
1217 * @SChost: Pointer to Scsi_Host structure
1219 * (linux scsi_host_template.info routine)
1221 * Returns pointer to buffer where information was written.
1224 mptscsih_info(struct Scsi_Host *SChost)
1229 h = (MPT_SCSI_HOST *)SChost->hostdata;
1232 if (h->info_kbuf == NULL)
1233 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1234 return h->info_kbuf;
1235 h->info_kbuf[0] = '\0';
1237 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1238 h->info_kbuf[size-1] = '\0';
1241 return h->info_kbuf;
1252 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1254 if (info->pos + len > info->length)
1255 len = info->length - info->pos;
1257 if (info->pos + len < info->offset) {
1262 if (info->pos < info->offset) {
1263 data += (info->offset - info->pos);
1264 len -= (info->offset - info->pos);
1268 memcpy(info->buffer + info->pos, data, len);
1274 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1280 va_start(args, fmt);
1281 len = vsprintf(buf, fmt, args);
1284 mptscsih_copy_mem_info(info, buf, len);
1289 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1291 struct info_str info;
1295 info.offset = offset;
1298 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1299 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1300 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1301 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1303 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1306 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1308 * mptscsih_proc_info - Return information about MPT adapter
1309 * @host: scsi host struct
1310 * @buffer: if write, user data; if read, buffer for user
1311 * @start: returns the buffer address
1312 * @offset: if write, 0; if read, the current offset into the buffer from
1313 * the previous read.
1314 * @length: if write, return length;
1315 * @func: write = 1; read = 0
1317 * (linux scsi_host_template.info routine)
1320 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1321 int length, int func)
1323 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1324 MPT_ADAPTER *ioc = hd->ioc;
1329 * write is not supported
1335 size = mptscsih_host_info(ioc, buffer, offset, length);
1341 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1342 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1344 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1346 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1347 * @SCpnt: Pointer to scsi_cmnd structure
1348 * @done: Pointer SCSI mid-layer IO completion function
1350 * (linux scsi_host_template.queuecommand routine)
1351 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1352 * from a linux scsi_cmnd request and send it to the IOC.
1354 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1357 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1361 SCSIIORequest_t *pScsiReq;
1362 VirtDevice *vdevice = SCpnt->device->hostdata;
1372 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1374 lun = SCpnt->device->lun;
1375 SCpnt->scsi_done = done;
1377 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1378 ioc->name, SCpnt, done));
1380 if (hd->resetPending) {
1381 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1383 return SCSI_MLQUEUE_HOST_BUSY;
1387 * Put together a MPT SCSI request...
1389 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1390 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1392 return SCSI_MLQUEUE_HOST_BUSY;
1395 pScsiReq = (SCSIIORequest_t *) mf;
1397 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1399 ADD_INDEX_LOG(my_idx);
1401 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1402 * Seems we may receive a buffer (datalen>0) even when there
1403 * will be no data transfer! GRRRRR...
1405 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1406 datalen = scsi_bufflen(SCpnt);
1407 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1408 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1409 datalen = scsi_bufflen(SCpnt);
1410 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1413 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1416 /* Default to untagged. Once a target structure has been allocated,
1417 * use the Inquiry data to determine if device supports tagged.
1420 && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1421 && (SCpnt->device->tagged_supported)) {
1422 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1424 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1427 /* Use the above information to set up the message frame
1429 pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1430 pScsiReq->Bus = vdevice->vtarget->channel;
1431 pScsiReq->ChainOffset = 0;
1432 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1433 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1435 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1436 pScsiReq->CDBLength = SCpnt->cmd_len;
1437 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1438 pScsiReq->Reserved = 0;
1439 pScsiReq->MsgFlags = mpt_msg_flags();
1440 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1441 pScsiReq->Control = cpu_to_le32(scsictl);
1444 * Write SCSI CDB into the message
1446 cmd_len = SCpnt->cmd_len;
1447 for (ii=0; ii < cmd_len; ii++)
1448 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1450 for (ii=cmd_len; ii < 16; ii++)
1451 pScsiReq->CDB[ii] = 0;
1454 pScsiReq->DataLength = cpu_to_le32(datalen);
1456 /* SenseBuffer low address */
1457 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1458 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1460 /* Now add the SG list
1461 * Always have a SGE even if null length.
1464 /* Add a NULL SGE */
1465 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1468 /* Add a 32 or 64 bit SGE */
1469 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1473 SCpnt->host_scribble = (unsigned char *)mf;
1474 hd->ScsiLookup[my_idx] = SCpnt;
1476 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1477 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1478 ioc->name, SCpnt, mf, my_idx));
1479 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1483 hd->ScsiLookup[my_idx] = NULL;
1484 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1485 mpt_free_msg_frame(hd->ioc, mf);
1486 return SCSI_MLQUEUE_HOST_BUSY;
1489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1491 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1492 * with a SCSI IO request
1493 * @hd: Pointer to the MPT_SCSI_HOST instance
1494 * @req_idx: Index of the SCSI IO request frame.
1496 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1500 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1502 MPT_FRAME_HDR *chain;
1503 unsigned long flags;
1507 /* Get the first chain index and reset
1510 chain_idx = ioc->ReqToChain[req_idx];
1511 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1513 while (chain_idx != MPT_HOST_NO_CHAIN) {
1515 /* Save the next chain buffer index */
1516 next = ioc->ChainToChain[chain_idx];
1518 /* Free this chain buffer and reset
1521 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1523 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1524 + (chain_idx * ioc->req_sz));
1526 spin_lock_irqsave(&ioc->FreeQlock, flags);
1527 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1528 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1530 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1531 ioc->name, chain_idx));
1539 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1544 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1546 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1547 * @hd: Pointer to MPT SCSI HOST structure
1548 * @type: Task Management type
1549 * @channel: channel number for task management
1550 * @id: Logical Target ID for reset (if appropriate)
1551 * @lun: Logical Unit for reset (if appropriate)
1552 * @ctx2abort: Context for the task to be aborted (if appropriate)
1553 * @timeout: timeout for task management control
1555 * Fall through to mpt_HardResetHandler if: not operational, too many
1556 * failed TM requests or handshake failure.
1558 * Remark: Currently invoked from a non-interrupt thread (_bh).
1560 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1563 * Returns 0 for SUCCESS, or %FAILED.
1566 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1571 unsigned long flags;
1574 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
1576 // SJR - CHECKME - Can we avoid this here?
1577 // (mpt_HardResetHandler has this check...)
1578 spin_lock_irqsave(&ioc->diagLock, flags);
1579 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1580 spin_unlock_irqrestore(&ioc->diagLock, flags);
1583 spin_unlock_irqrestore(&ioc->diagLock, flags);
1585 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1586 * If we time out and not bus reset, then we return a FAILED status
1588 * The call to mptscsih_tm_pending_wait() will set the pending flag
1590 * successful. Otherwise, reload the FW.
1592 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1593 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1594 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: "
1595 "Timed out waiting for last TM (%d) to complete! \n",
1596 ioc->name, hd->tmPending));
1598 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1599 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target "
1600 "reset: Timed out waiting for last TM (%d) "
1601 "to complete! \n", ioc->name,
1604 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1605 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: "
1606 "Timed out waiting for last TM (%d) to complete! \n",
1607 ioc->name, hd->tmPending));
1611 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1612 hd->tmPending |= (1 << type);
1613 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1616 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1618 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1619 printk(MYIOC_s_WARN_FMT
1620 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1621 ioc->name, type, ioc_raw_state);
1622 printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name);
1623 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1624 printk(MYIOC_s_WARN_FMT "TMHandler: HardReset "
1625 "FAILED!!\n", ioc->name);
1629 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1630 printk(MYIOC_s_WARN_FMT
1631 "TM Handler for type=%x: ioc_state: "
1632 "DOORBELL_ACTIVE (0x%x)!\n",
1633 ioc->name, type, ioc_raw_state);
1637 /* Isse the Task Mgmt request.
1639 if (hd->hard_resets < -1)
1642 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1643 ctx2abort, timeout);
1645 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1648 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
1651 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1652 "TMHandler rc = %d!\n", ioc->name, rc));
1658 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1660 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1661 * @hd: Pointer to MPT_SCSI_HOST structure
1662 * @type: Task Management type
1663 * @channel: channel number for task management
1664 * @id: Logical Target ID for reset (if appropriate)
1665 * @lun: Logical Unit for reset (if appropriate)
1666 * @ctx2abort: Context for the task to be aborted (if appropriate)
1667 * @timeout: timeout for task management control
1669 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1670 * or a non-interrupt thread. In the former, must not call schedule().
1672 * Not all fields are meaningfull for all task types.
1674 * Returns 0 for SUCCESS, or FAILED.
1678 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1681 SCSITaskMgmt_t *pScsiTm;
1685 /* Return Fail to calling function if no message frames available.
1687 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1688 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1692 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
1693 hd->ioc->name, mf));
1695 /* Format the Request
1697 pScsiTm = (SCSITaskMgmt_t *) mf;
1698 pScsiTm->TargetID = id;
1699 pScsiTm->Bus = channel;
1700 pScsiTm->ChainOffset = 0;
1701 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1703 pScsiTm->Reserved = 0;
1704 pScsiTm->TaskType = type;
1705 pScsiTm->Reserved1 = 0;
1706 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1707 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1709 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1711 for (ii=0; ii < 7; ii++)
1712 pScsiTm->Reserved2[ii] = 0;
1714 pScsiTm->TaskMsgContext = ctx2abort;
1716 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1717 "type=%d\n", hd->ioc->name, ctx2abort, type));
1719 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1721 if ((hd->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1722 (hd->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1723 mpt_put_msg_frame_hi_pri(hd->ioc->TaskCtx, hd->ioc, mf);
1725 retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1726 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1728 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
1729 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1730 hd->ioc, mf, retval));
1735 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1736 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1737 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1739 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
1741 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1742 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
1743 hd->ioc->name, retval));
1748 * Handle success case, see if theres a non-zero ioc_status.
1750 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1751 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1752 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1762 * Free task managment mf, and corresponding tm flags
1764 mpt_free_msg_frame(hd->ioc, mf);
1766 hd->tmState = TM_STATE_NONE;
1771 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1773 switch (ioc->bus_type) {
1784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1786 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1787 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1789 * (linux scsi_host_template.eh_abort_handler routine)
1791 * Returns SUCCESS or FAILED.
1794 mptscsih_abort(struct scsi_cmnd * SCpnt)
1801 VirtDevice *vdevice;
1802 ulong sn = SCpnt->serial_number;
1805 /* If we can't locate our host adapter structure, return FAILED status.
1807 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1808 SCpnt->result = DID_RESET << 16;
1809 SCpnt->scsi_done(SCpnt);
1810 printk(KERN_ERR MYNAM ": task abort: "
1811 "can't locate host! (sc=%p)\n", SCpnt);
1816 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1818 scsi_print_command(SCpnt);
1820 vdevice = SCpnt->device->hostdata;
1821 if (!vdevice || !vdevice->vtarget) {
1822 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1823 "task abort: device has been deleted (sc=%p)\n",
1825 SCpnt->result = DID_NO_CONNECT << 16;
1826 SCpnt->scsi_done(SCpnt);
1831 /* Task aborts are not supported for hidden raid components.
1833 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1834 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1835 "task abort: hidden raid component (sc=%p)\n",
1837 SCpnt->result = DID_RESET << 16;
1842 /* Find this command
1844 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1845 /* Cmd not found in ScsiLookup.
1848 SCpnt->result = DID_RESET << 16;
1849 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
1850 "Command not in the active list! (sc=%p)\n", ioc->name,
1856 if (hd->resetPending) {
1861 if (hd->timeouts < -1)
1864 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1865 * (the IO to be ABORT'd)
1867 * NOTE: Since we do not byteswap MsgContext, we do not
1868 * swap it here either. It is an opaque cookie to
1869 * the controller, so it does not matter. -DaveM
1871 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1872 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1874 hd->abortSCpnt = SCpnt;
1876 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1877 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1878 ctx2abort, mptscsih_get_tm_timeout(ioc));
1880 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1881 SCpnt->serial_number == sn)
1885 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
1886 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1894 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1896 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1897 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1899 * (linux scsi_host_template.eh_dev_reset_handler routine)
1901 * Returns SUCCESS or FAILED.
1904 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1908 VirtDevice *vdevice;
1911 /* If we can't locate our host adapter structure, return FAILED status.
1913 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1914 printk(KERN_ERR MYNAM ": target reset: "
1915 "Can't locate host! (sc=%p)\n", SCpnt);
1920 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1922 scsi_print_command(SCpnt);
1924 if (hd->resetPending) {
1929 vdevice = SCpnt->device->hostdata;
1930 if (!vdevice || !vdevice->vtarget) {
1935 /* Target reset to hidden raid component is not supported
1937 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1942 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1943 vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
1944 mptscsih_get_tm_timeout(ioc));
1947 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1948 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1957 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1959 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1960 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1962 * (linux scsi_host_template.eh_bus_reset_handler routine)
1964 * Returns SUCCESS or FAILED.
1967 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1971 VirtDevice *vdevice;
1974 /* If we can't locate our host adapter structure, return FAILED status.
1976 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1977 printk(KERN_ERR MYNAM ": bus reset: "
1978 "Can't locate host! (sc=%p)\n", SCpnt);
1983 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1985 scsi_print_command(SCpnt);
1987 if (hd->timeouts < -1)
1990 vdevice = SCpnt->device->hostdata;
1991 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1992 vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
1994 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1995 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
2003 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2005 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
2006 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
2008 * (linux scsi_host_template.eh_host_reset_handler routine)
2010 * Returns SUCCESS or FAILED.
2013 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
2019 /* If we can't locate the host to reset, then we failed. */
2020 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2021 printk(KERN_ERR MYNAM ": host reset: "
2022 "Can't locate host! (sc=%p)\n", SCpnt);
2027 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
2030 /* If our attempts to reset the host failed, then return a failed
2031 * status. The host will be taken off line by the SCSI mid-layer.
2033 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
2036 /* Make sure TM pending is cleared and TM state is set to
2041 hd->tmState = TM_STATE_NONE;
2044 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
2045 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
2050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2052 * mptscsih_tm_pending_wait - wait for pending task management request to complete
2053 * @hd: Pointer to MPT host structure.
2055 * Returns {SUCCESS,FAILED}.
2058 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
2060 unsigned long flags;
2061 int loop_count = 4 * 10; /* Wait 10 seconds */
2062 int status = FAILED;
2065 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2066 if (hd->tmState == TM_STATE_NONE) {
2067 hd->tmState = TM_STATE_IN_PROGRESS;
2069 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2073 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2075 } while (--loop_count);
2080 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2082 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2083 * @hd: Pointer to MPT host structure.
2084 * @timeout: timeout value
2086 * Returns {SUCCESS,FAILED}.
2089 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2091 unsigned long flags;
2092 int loop_count = 4 * timeout;
2093 int status = FAILED;
2096 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2097 if(hd->tmPending == 0) {
2099 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2102 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2104 } while (--loop_count);
2109 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2111 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2115 switch (response_code) {
2116 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2117 desc = "The task completed.";
2119 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2120 desc = "The IOC received an invalid frame status.";
2122 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2123 desc = "The task type is not supported.";
2125 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2126 desc = "The requested task failed.";
2128 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2129 desc = "The task completed successfully.";
2131 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2132 desc = "The LUN request is invalid.";
2134 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2135 desc = "The task is in the IOC queue and has not been sent to target.";
2141 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2142 ioc->name, response_code, desc);
2145 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2147 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2148 * @ioc: Pointer to MPT_ADAPTER structure
2149 * @mf: Pointer to SCSI task mgmt request frame
2150 * @mr: Pointer to SCSI task mgmt reply frame
2152 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2153 * of any SCSI task management request.
2154 * This routine is registered with the MPT (base) driver at driver
2155 * load/init time via the mpt_register() API call.
2157 * Returns 1 indicating alloc'd request frame ptr should be freed.
2160 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2162 SCSITaskMgmtReply_t *pScsiTmReply;
2163 SCSITaskMgmt_t *pScsiTmReq;
2165 unsigned long flags;
2168 u32 termination_count;
2170 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2171 ioc->name, mf, mr));
2173 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2174 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2179 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2180 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2184 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2185 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2186 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2187 tmType = pScsiTmReq->TaskType;
2188 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2189 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2191 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2192 pScsiTmReply->ResponseCode)
2193 mptscsih_taskmgmt_response_code(ioc,
2194 pScsiTmReply->ResponseCode);
2195 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
2197 #ifdef CONFIG_FUSION_LOGGING
2198 if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
2199 (ioc->debug_level & MPT_DEBUG_TM ))
2200 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2201 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2202 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2203 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2204 le16_to_cpu(pScsiTmReply->IOCStatus),
2205 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2206 le32_to_cpu(pScsiTmReply->TerminationCount));
2209 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
2210 hd->abortSCpnt = NULL;
2214 /* Error? (anything non-zero?) */
2216 /* clear flags and continue.
2220 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2221 if (termination_count == 1)
2222 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2223 hd->abortSCpnt = NULL;
2226 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2228 /* If an internal command is present
2229 * or the TM failed - reload the FW.
2230 * FC FW may respond FAILED to an ABORT
2232 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2234 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2235 printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name);
2238 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2244 spin_lock_irqsave(&ioc->FreeQlock, flags);
2246 hd->tmState = TM_STATE_NONE;
2247 hd->tm_iocstatus = iocstatus;
2248 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2253 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2255 * This is anyones guess quite frankly.
2258 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2259 sector_t capacity, int geom[])
2269 dummy = heads * sectors;
2270 cylinders = capacity;
2271 sector_div(cylinders,dummy);
2274 * Handle extended translation size for logical drives
2277 if ((ulong)capacity >= 0x200000) {
2280 dummy = heads * sectors;
2281 cylinders = capacity;
2282 sector_div(cylinders,dummy);
2288 geom[2] = cylinders;
2293 /* Search IOC page 3 to determine if this is hidden physical disk
2297 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2299 struct inactive_raid_component_info *component_info;
2303 if (!ioc->raid_data.pIocPg3)
2305 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2306 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2307 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2314 * Check inactive list for matching phys disks
2316 if (list_empty(&ioc->raid_data.inactive_list))
2319 down(&ioc->raid_data.inactive_list_mutex);
2320 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2322 if ((component_info->d.PhysDiskID == id) &&
2323 (component_info->d.PhysDiskBus == channel))
2326 up(&ioc->raid_data.inactive_list_mutex);
2331 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2334 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2336 struct inactive_raid_component_info *component_info;
2340 if (!ioc->raid_data.pIocPg3)
2342 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2343 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2344 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2345 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2351 * Check inactive list for matching phys disks
2353 if (list_empty(&ioc->raid_data.inactive_list))
2356 down(&ioc->raid_data.inactive_list_mutex);
2357 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2359 if ((component_info->d.PhysDiskID == id) &&
2360 (component_info->d.PhysDiskBus == channel))
2361 rc = component_info->d.PhysDiskNum;
2363 up(&ioc->raid_data.inactive_list_mutex);
2368 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2371 * OS entry point to allow for host driver to free allocated memory
2372 * Called if no device present or device being unloaded
2375 mptscsih_slave_destroy(struct scsi_device *sdev)
2377 struct Scsi_Host *host = sdev->host;
2378 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2379 VirtTarget *vtarget;
2380 VirtDevice *vdevice;
2381 struct scsi_target *starget;
2383 starget = scsi_target(sdev);
2384 vtarget = starget->hostdata;
2385 vdevice = sdev->hostdata;
2387 mptscsih_search_running_cmds(hd, vdevice);
2388 vtarget->num_luns--;
2389 mptscsih_synchronize_cache(hd, vdevice);
2391 sdev->hostdata = NULL;
2394 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2396 * mptscsih_change_queue_depth - This function will set a devices queue depth
2397 * @sdev: per scsi_device pointer
2398 * @qdepth: requested queue depth
2400 * Adding support for new 'change_queue_depth' api.
2403 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2405 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2406 VirtTarget *vtarget;
2407 struct scsi_target *starget;
2411 starget = scsi_target(sdev);
2412 vtarget = starget->hostdata;
2414 if (hd->ioc->bus_type == SPI) {
2415 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2417 else if (sdev->type == TYPE_DISK &&
2418 vtarget->minSyncFactor <= MPT_ULTRA160)
2419 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2421 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2423 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2425 if (qdepth > max_depth)
2430 tagged = MSG_SIMPLE_TAG;
2432 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2433 return sdev->queue_depth;
2437 * OS entry point to adjust the queue_depths on a per-device basis.
2438 * Called once per device the bus scan. Use it to force the queue_depth
2439 * member to 1 if a device does not support Q tags.
2440 * Return non-zero if fails.
2443 mptscsih_slave_configure(struct scsi_device *sdev)
2445 struct Scsi_Host *sh = sdev->host;
2446 VirtTarget *vtarget;
2447 VirtDevice *vdevice;
2448 struct scsi_target *starget;
2449 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2451 starget = scsi_target(sdev);
2452 vtarget = starget->hostdata;
2453 vdevice = sdev->hostdata;
2455 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2456 "device @ %p, channel=%d, id=%d, lun=%d\n",
2457 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2458 if (hd->ioc->bus_type == SPI)
2459 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2460 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2461 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2462 sdev->ppr, sdev->inquiry_len));
2464 if (sdev->id > sh->max_id) {
2465 /* error case, should never happen */
2466 scsi_adjust_queue_depth(sdev, 0, 1);
2467 goto slave_configure_exit;
2470 vdevice->configured_lun = 1;
2471 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2473 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2474 "Queue depth=%d, tflags=%x\n",
2475 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2477 if (hd->ioc->bus_type == SPI)
2478 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2479 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2480 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2481 vtarget->minSyncFactor));
2483 slave_configure_exit:
2485 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2486 "tagged %d, simple %d, ordered %d\n",
2487 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2488 sdev->ordered_tags));
2493 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2495 * Private routines...
2498 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2499 /* Utility function to copy sense data from the scsi_cmnd buffer
2500 * to the FC and SCSI target structures.
2504 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2506 VirtDevice *vdevice;
2507 SCSIIORequest_t *pReq;
2508 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2510 /* Get target structure
2512 pReq = (SCSIIORequest_t *) mf;
2513 vdevice = sc->device->hostdata;
2519 /* Copy the sense received into the scsi command block. */
2520 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2521 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2522 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2524 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2526 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2527 if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
2529 MPT_ADAPTER *ioc = hd->ioc;
2531 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2532 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2533 ioc->events[idx].eventContext = ioc->eventContext;
2535 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2536 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2537 (sc->device->channel << 8) | sc->device->id;
2539 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2541 ioc->eventContext++;
2542 if (hd->ioc->pcidev->vendor ==
2543 PCI_VENDOR_ID_IBM) {
2544 mptscsih_issue_sep_command(hd->ioc,
2545 vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2546 vdevice->vtarget->tflags |=
2547 MPT_TARGET_FLAGS_LED_ON;
2552 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2558 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2563 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2565 for (i = 0; i < hd->ioc->req_depth; i++) {
2566 if (hd->ScsiLookup[i] == sc) {
2574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2576 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2579 unsigned long flags;
2582 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2583 ": IOC %s_reset routed to SCSI host driver!\n",
2584 ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2585 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2587 /* If a FW reload request arrives after base installed but
2588 * before all scsi hosts have been attached, then an alt_ioc
2589 * may have a NULL sh pointer.
2591 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2594 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2596 if (reset_phase == MPT_IOC_SETUP_RESET) {
2597 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
2600 * 1. Set Hard Reset Pending Flag
2601 * All new commands go to doneQ
2603 hd->resetPending = 1;
2605 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2606 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
2608 /* 2. Flush running commands
2609 * Clean ScsiLookup (and associated memory)
2613 /* 2b. Reply to OS all known outstanding I/O commands.
2615 mptscsih_flush_running_cmds(hd);
2617 /* 2c. If there was an internal command that
2618 * has not completed, configuration or io request,
2619 * free these resources.
2622 del_timer(&hd->timer);
2623 mpt_free_msg_frame(ioc, hd->cmdPtr);
2626 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
2629 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
2631 /* Once a FW reload begins, all new OS commands are
2632 * redirected to the doneQ w/ a reset status.
2633 * Init all control structures.
2636 /* ScsiLookup initialization
2638 for (ii=0; ii < hd->ioc->req_depth; ii++)
2639 hd->ScsiLookup[ii] = NULL;
2641 /* 2. Chain Buffer initialization
2644 /* 4. Renegotiate to all devices, if SPI
2647 /* 5. Enable new commands to be posted
2649 spin_lock_irqsave(&ioc->FreeQlock, flags);
2651 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2652 hd->resetPending = 0;
2653 hd->tmState = TM_STATE_NONE;
2655 /* 6. If there was an internal command,
2656 * wake this process up.
2660 * Wake up the original calling thread
2662 hd->pLocal = &hd->localReply;
2663 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2664 hd->scandv_wait_done = 1;
2665 wake_up(&hd->scandv_waitq);
2669 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
2673 return 1; /* currently means nothing really */
2676 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2678 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2681 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2683 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2686 if (ioc->sh == NULL ||
2687 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2691 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2694 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2695 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2696 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2699 case MPI_EVENT_LOGOUT: /* 09 */
2703 case MPI_EVENT_RESCAN: /* 06 */
2707 * CHECKME! Don't think we need to do
2708 * anything for these, but...
2710 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2711 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2713 * CHECKME! Falling thru...
2717 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2720 case MPI_EVENT_NONE: /* 00 */
2721 case MPI_EVENT_LOG_DATA: /* 01 */
2722 case MPI_EVENT_STATE_CHANGE: /* 02 */
2723 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2725 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n",
2730 return 1; /* currently means nothing really */
2733 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2735 * Bus Scan and Domain Validation functionality ...
2738 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2740 * mptscsih_scandv_complete - Scan and DV callback routine registered
2741 * to Fustion MPT (base) driver.
2743 * @ioc: Pointer to MPT_ADAPTER structure
2744 * @mf: Pointer to original MPT request frame
2745 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2747 * This routine is called from mpt.c::mpt_interrupt() at the completion
2748 * of any SCSI IO request.
2749 * This routine is registered with the Fusion MPT (base) driver at driver
2750 * load/init time via the mpt_register() API call.
2752 * Returns 1 indicating alloc'd request frame ptr should be freed.
2754 * Remark: Sets a completion code and (possibly) saves sense data
2755 * in the IOC member localReply structure.
2756 * Used ONLY for DV and other internal commands.
2759 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2762 SCSIIORequest_t *pReq;
2766 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2769 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2770 printk(MYIOC_s_ERR_FMT
2771 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2772 ioc->name, mf?"BAD":"NULL", (void *) mf);
2776 del_timer(&hd->timer);
2777 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2778 hd->ScsiLookup[req_idx] = NULL;
2779 pReq = (SCSIIORequest_t *) mf;
2781 if (mf != hd->cmdPtr) {
2782 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2783 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2787 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2788 hd->ioc->name, mf, mr, req_idx));
2790 hd->pLocal = &hd->localReply;
2791 hd->pLocal->scsiStatus = 0;
2793 /* If target struct exists, clear sense valid flag.
2796 completionCode = MPT_SCANDV_GOOD;
2798 SCSIIOReply_t *pReply;
2802 pReply = (SCSIIOReply_t *) mr;
2804 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2805 scsi_status = pReply->SCSIStatus;
2810 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2811 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2814 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2815 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2816 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2817 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2818 completionCode = MPT_SCANDV_DID_RESET;
2821 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2822 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2823 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2824 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2825 ConfigReply_t *pr = (ConfigReply_t *)mr;
2826 completionCode = MPT_SCANDV_GOOD;
2827 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2828 hd->pLocal->header.PageLength = pr->Header.PageLength;
2829 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2830 hd->pLocal->header.PageType = pr->Header.PageType;
2832 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2833 /* If the RAID Volume request is successful,
2834 * return GOOD, else indicate that
2835 * some type of error occurred.
2837 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2838 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2839 completionCode = MPT_SCANDV_GOOD;
2841 completionCode = MPT_SCANDV_SOME_ERROR;
2842 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2844 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2848 /* save sense data in global structure
2850 completionCode = MPT_SCANDV_SENSE;
2851 hd->pLocal->scsiStatus = scsi_status;
2852 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2853 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2855 sz = min_t(int, pReq->SenseBufferLength,
2856 SCSI_STD_SENSE_BYTES);
2857 memcpy(hd->pLocal->sense, sense_data, sz);
2859 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n",
2860 ioc->name, sense_data));
2861 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2862 if (pReq->CDB[0] == INQUIRY)
2863 completionCode = MPT_SCANDV_ISSUE_SENSE;
2865 completionCode = MPT_SCANDV_DID_RESET;
2867 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2868 completionCode = MPT_SCANDV_DID_RESET;
2869 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2870 completionCode = MPT_SCANDV_DID_RESET;
2872 completionCode = MPT_SCANDV_GOOD;
2873 hd->pLocal->scsiStatus = scsi_status;
2877 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2878 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2879 completionCode = MPT_SCANDV_DID_RESET;
2881 completionCode = MPT_SCANDV_SOME_ERROR;
2885 completionCode = MPT_SCANDV_SOME_ERROR;
2888 } /* switch(status) */
2890 } /* end of address reply case */
2892 hd->pLocal->completion = completionCode;
2894 /* MF and RF are freed in mpt_interrupt
2897 /* Free Chain buffers (will never chain) in scan or dv */
2898 //mptscsih_freeChainBuffers(ioc, req_idx);
2901 * Wake up the original calling thread
2903 hd->scandv_wait_done = 1;
2904 wake_up(&hd->scandv_waitq);
2909 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2910 /* mptscsih_timer_expired - Call back for timer process.
2911 * Used only for dv functionality.
2912 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2916 mptscsih_timer_expired(unsigned long data)
2918 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2920 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2923 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2925 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2926 /* Desire to issue a task management request here.
2927 * TM requests MUST be single threaded.
2928 * If old eh code and no TM current, issue request.
2929 * If new eh code, do nothing. Wait for OS cmd timeout
2933 /* Perform a FW reload */
2934 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2935 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2939 /* This should NEVER happen */
2940 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2943 /* No more processing.
2944 * TM call will generate an interrupt for SCSI TM Management.
2945 * The FW will reply to all outstanding commands, callback will finish cleanup.
2946 * Hard reset clean-up will free all resources.
2948 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name));
2954 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2956 * mptscsih_do_cmd - Do internal command.
2957 * @hd: MPT_SCSI_HOST pointer
2958 * @io: INTERNAL_CMD pointer.
2960 * Issue the specified internally generated command and do command
2961 * specific cleanup. For bus scan / DV only.
2962 * NOTES: If command is Inquiry and status is good,
2963 * initialize a target structure, save the data
2965 * Remark: Single threaded access only.
2968 * < 0 if an illegal command or no resources
2972 * > 0 if command complete but some type of completion error.
2975 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2978 SCSIIORequest_t *pScsiReq;
2979 SCSIIORequest_t ReqCopy;
2980 int my_idx, ii, dir;
2984 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2987 in_isr = in_interrupt();
2989 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2995 /* Set command specific information
3000 dir = MPI_SCSIIO_CONTROL_READ;
3006 case TEST_UNIT_READY:
3008 dir = MPI_SCSIIO_CONTROL_READ;
3014 dir = MPI_SCSIIO_CONTROL_READ;
3016 CDB[4] = 1; /*Spin up the disk */
3024 dir = MPI_SCSIIO_CONTROL_READ;
3030 dir = MPI_SCSIIO_CONTROL_READ;
3032 if (io->flags & MPT_ICFLAG_ECHO) {
3038 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3041 CDB[6] = (io->size >> 16) & 0xFF;
3042 CDB[7] = (io->size >> 8) & 0xFF;
3043 CDB[8] = io->size & 0xFF;
3049 dir = MPI_SCSIIO_CONTROL_WRITE;
3051 if (io->flags & MPT_ICFLAG_ECHO) {
3056 CDB[6] = (io->size >> 16) & 0xFF;
3057 CDB[7] = (io->size >> 8) & 0xFF;
3058 CDB[8] = io->size & 0xFF;
3064 dir = MPI_SCSIIO_CONTROL_READ;
3071 dir = MPI_SCSIIO_CONTROL_READ;
3076 case SYNCHRONIZE_CACHE:
3078 dir = MPI_SCSIIO_CONTROL_READ;
3080 // CDB[1] = 0x02; /* set immediate bit */
3089 /* Get and Populate a free Frame
3091 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3092 dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n",
3097 pScsiReq = (SCSIIORequest_t *) mf;
3099 /* Get the request index */
3100 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3101 ADD_INDEX_LOG(my_idx); /* for debug */
3103 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3104 pScsiReq->TargetID = io->physDiskNum;
3106 pScsiReq->ChainOffset = 0;
3107 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3109 pScsiReq->TargetID = io->id;
3110 pScsiReq->Bus = io->channel;
3111 pScsiReq->ChainOffset = 0;
3112 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3115 pScsiReq->CDBLength = cmdLen;
3116 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3118 pScsiReq->Reserved = 0;
3120 pScsiReq->MsgFlags = mpt_msg_flags();
3121 /* MsgContext set in mpt_get_msg_fram call */
3123 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3125 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3126 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3128 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3130 if (cmd == REQUEST_SENSE) {
3131 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3132 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
3133 hd->ioc->name, cmd));
3136 for (ii=0; ii < 16; ii++)
3137 pScsiReq->CDB[ii] = CDB[ii];
3139 pScsiReq->DataLength = cpu_to_le32(io->size);
3140 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3141 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3143 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3144 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3146 if (dir == MPI_SCSIIO_CONTROL_READ) {
3147 mpt_add_sge((char *) &pScsiReq->SGL,
3148 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3151 mpt_add_sge((char *) &pScsiReq->SGL,
3152 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3156 /* The ISR will free the request frame, but we need
3157 * the information to initialize the target. Duplicate.
3159 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3161 /* Issue this command after:
3164 * Wait until the reply has been received
3165 * ScsiScanDvCtx callback function will
3167 * set scandv_wait_done and call wake_up
3170 hd->timer.expires = jiffies + HZ*cmdTimeout;
3171 hd->scandv_wait_done = 0;
3173 /* Save cmd pointer, for resource free if timeout or
3178 add_timer(&hd->timer);
3179 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3180 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3183 rc = hd->pLocal->completion;
3184 hd->pLocal->skip = 0;
3186 /* Always set fatal error codes in some cases.
3188 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3190 else if (rc == MPT_SCANDV_SOME_ERROR)
3194 /* This should never happen. */
3195 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
3202 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3204 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3205 * @hd: Pointer to a SCSI HOST structure
3206 * @vdevice: virtual target device
3208 * Uses the ISR, but with special processing.
3209 * MUST be single-threaded.
3213 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3217 /* Ignore hidden raid components, this is handled when the command
3218 * is sent to the volume
3220 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3223 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3224 !vdevice->configured_lun)
3227 /* Following parameters will not change
3230 iocmd.cmd = SYNCHRONIZE_CACHE;
3232 iocmd.physDiskNum = -1;
3234 iocmd.data_dma = -1;
3236 iocmd.rsvd = iocmd.rsvd2 = 0;
3237 iocmd.channel = vdevice->vtarget->channel;
3238 iocmd.id = vdevice->vtarget->id;
3239 iocmd.lun = vdevice->lun;
3241 mptscsih_do_cmd(hd, &iocmd);
3245 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
3247 struct Scsi_Host *host = class_to_shost(cdev);
3248 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3249 MPT_ADAPTER *ioc = hd->ioc;
3251 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3252 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3253 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3254 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3255 ioc->facts.FWVersion.Word & 0x000000FF);
3257 static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
3260 mptscsih_version_bios_show(struct class_device *cdev, char *buf)
3262 struct Scsi_Host *host = class_to_shost(cdev);
3263 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3264 MPT_ADAPTER *ioc = hd->ioc;
3266 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3267 (ioc->biosVersion & 0xFF000000) >> 24,
3268 (ioc->biosVersion & 0x00FF0000) >> 16,
3269 (ioc->biosVersion & 0x0000FF00) >> 8,
3270 ioc->biosVersion & 0x000000FF);
3272 static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
3275 mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
3277 struct Scsi_Host *host = class_to_shost(cdev);
3278 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3279 MPT_ADAPTER *ioc = hd->ioc;
3281 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3283 static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
3286 mptscsih_version_product_show(struct class_device *cdev, char *buf)
3288 struct Scsi_Host *host = class_to_shost(cdev);
3289 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3290 MPT_ADAPTER *ioc = hd->ioc;
3292 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3294 static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
3295 mptscsih_version_product_show, NULL);
3298 mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
3300 struct Scsi_Host *host = class_to_shost(cdev);
3301 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3302 MPT_ADAPTER *ioc = hd->ioc;
3304 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3305 ioc->nvdata_version_persistent);
3307 static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
3308 mptscsih_version_nvdata_persistent_show, NULL);
3311 mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
3313 struct Scsi_Host *host = class_to_shost(cdev);
3314 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3315 MPT_ADAPTER *ioc = hd->ioc;
3317 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3319 static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
3320 mptscsih_version_nvdata_default_show, NULL);
3323 mptscsih_board_name_show(struct class_device *cdev, char *buf)
3325 struct Scsi_Host *host = class_to_shost(cdev);
3326 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3327 MPT_ADAPTER *ioc = hd->ioc;
3329 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3331 static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
3334 mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
3336 struct Scsi_Host *host = class_to_shost(cdev);
3337 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3338 MPT_ADAPTER *ioc = hd->ioc;
3340 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3342 static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
3343 mptscsih_board_assembly_show, NULL);
3346 mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
3348 struct Scsi_Host *host = class_to_shost(cdev);
3349 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3350 MPT_ADAPTER *ioc = hd->ioc;
3352 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3354 static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
3355 mptscsih_board_tracer_show, NULL);
3358 mptscsih_io_delay_show(struct class_device *cdev, char *buf)
3360 struct Scsi_Host *host = class_to_shost(cdev);
3361 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3362 MPT_ADAPTER *ioc = hd->ioc;
3364 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3366 static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
3367 mptscsih_io_delay_show, NULL);
3370 mptscsih_device_delay_show(struct class_device *cdev, char *buf)
3372 struct Scsi_Host *host = class_to_shost(cdev);
3373 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3374 MPT_ADAPTER *ioc = hd->ioc;
3376 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3378 static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
3379 mptscsih_device_delay_show, NULL);
3382 mptscsih_debug_level_show(struct class_device *cdev, char *buf)
3384 struct Scsi_Host *host = class_to_shost(cdev);
3385 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3386 MPT_ADAPTER *ioc = hd->ioc;
3388 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3391 mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
3394 struct Scsi_Host *host = class_to_shost(cdev);
3395 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3396 MPT_ADAPTER *ioc = hd->ioc;
3399 if (sscanf(buf, "%x", &val) != 1)
3402 ioc->debug_level = val;
3403 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3404 ioc->name, ioc->debug_level);
3407 static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3408 mptscsih_debug_level_show, mptscsih_debug_level_store);
3410 struct class_device_attribute *mptscsih_host_attrs[] = {
3411 &class_device_attr_version_fw,
3412 &class_device_attr_version_bios,
3413 &class_device_attr_version_mpi,
3414 &class_device_attr_version_product,
3415 &class_device_attr_version_nvdata_persistent,
3416 &class_device_attr_version_nvdata_default,
3417 &class_device_attr_board_name,
3418 &class_device_attr_board_assembly,
3419 &class_device_attr_board_tracer,
3420 &class_device_attr_io_delay,
3421 &class_device_attr_device_delay,
3422 &class_device_attr_debug_level,
3425 EXPORT_SYMBOL(mptscsih_host_attrs);
3427 EXPORT_SYMBOL(mptscsih_remove);
3428 EXPORT_SYMBOL(mptscsih_shutdown);
3430 EXPORT_SYMBOL(mptscsih_suspend);
3431 EXPORT_SYMBOL(mptscsih_resume);
3433 EXPORT_SYMBOL(mptscsih_proc_info);
3434 EXPORT_SYMBOL(mptscsih_info);
3435 EXPORT_SYMBOL(mptscsih_qcmd);
3436 EXPORT_SYMBOL(mptscsih_slave_destroy);
3437 EXPORT_SYMBOL(mptscsih_slave_configure);
3438 EXPORT_SYMBOL(mptscsih_abort);
3439 EXPORT_SYMBOL(mptscsih_dev_reset);
3440 EXPORT_SYMBOL(mptscsih_bus_reset);
3441 EXPORT_SYMBOL(mptscsih_host_reset);
3442 EXPORT_SYMBOL(mptscsih_bios_param);
3443 EXPORT_SYMBOL(mptscsih_io_done);
3444 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3445 EXPORT_SYMBOL(mptscsih_scandv_complete);
3446 EXPORT_SYMBOL(mptscsih_event_process);
3447 EXPORT_SYMBOL(mptscsih_ioc_reset);
3448 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3449 EXPORT_SYMBOL(mptscsih_timer_expired);
3450 EXPORT_SYMBOL(mptscsih_TMHandler);
3452 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/