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 "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
207 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
210 chain_idx = MPT_HOST_NO_CHAIN;
211 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n",
214 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
216 *retIndex = chain_idx;
218 } /* mptscsih_getFreeChainBuffer() */
220 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
222 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
223 * SCSIIORequest_t Message Frame.
224 * @ioc: Pointer to MPT_ADAPTER structure
225 * @SCpnt: Pointer to scsi_cmnd structure
226 * @pReq: Pointer to SCSIIORequest_t structure
231 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
232 SCSIIORequest_t *pReq, int req_idx)
236 struct scatterlist *sg;
238 int sges_left, sg_done;
239 int chain_idx = MPT_HOST_NO_CHAIN;
241 int numSgeSlots, numSgeThisFrame;
242 u32 sgflags, sgdir, thisxfer = 0;
243 int chain_dma_off = 0;
249 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
250 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
251 sgdir = MPT_TRANSFER_HOST_TO_IOC;
253 sgdir = MPT_TRANSFER_IOC_TO_HOST;
256 psge = (char *) &pReq->SGL;
257 frm_sz = ioc->req_sz;
259 /* Map the data portion, if any.
260 * sges_left = 0 if no data transfer.
262 sges_left = scsi_dma_map(SCpnt);
266 /* Handle the SG case.
268 sg = scsi_sglist(SCpnt);
270 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
273 /* Prior to entering this loop - the following must be set
274 * current MF: sgeOffset (bytes)
275 * chainSge (Null if original MF is not a chain buffer)
276 * sg_done (num SGE done for this MF)
280 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
281 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
283 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
285 /* Get first (num - 1) SG elements
286 * Skip any SG entries with a length of 0
287 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
289 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
290 thisxfer = sg_dma_len(sg);
292 sg ++; /* Get next SG element from the OS */
297 v2 = sg_dma_address(sg);
298 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
300 sg++; /* Get next SG element from the OS */
301 psge += (sizeof(u32) + sizeof(dma_addr_t));
302 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
306 if (numSgeThisFrame == sges_left) {
307 /* Add last element, end of buffer and end of list flags.
309 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
310 MPT_SGE_FLAGS_END_OF_BUFFER |
311 MPT_SGE_FLAGS_END_OF_LIST;
313 /* Add last SGE and set termination flags.
314 * Note: Last SGE may have a length of 0 - which should be ok.
316 thisxfer = sg_dma_len(sg);
318 v2 = sg_dma_address(sg);
319 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
322 psge += (sizeof(u32) + sizeof(dma_addr_t));
324 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
328 /* The current buffer is a chain buffer,
329 * but there is not another one.
330 * Update the chain element
331 * Offset and Length fields.
333 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
335 /* The current buffer is the original MF
336 * and there is no Chain buffer.
338 pReq->ChainOffset = 0;
339 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
340 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT
341 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
342 ioc->RequestNB[req_idx] = RequestNB;
345 /* At least one chain buffer is needed.
346 * Complete the first MF
347 * - last SGE element, set the LastElement bit
348 * - set ChainOffset (words) for orig MF
349 * (OR finish previous MF chain buffer)
350 * - update MFStructPtr ChainIndex
351 * - Populate chain element
356 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n",
357 ioc->name, sg_done));
359 /* Set LAST_ELEMENT flag for last non-chain element
360 * in the buffer. Since psge points at the NEXT
361 * SGE element, go back one SGE element, update the flags
362 * and reset the pointer. (Note: sgflags & thisxfer are already
366 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
367 sgflags = le32_to_cpu(*ptmp);
368 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
369 *ptmp = cpu_to_le32(sgflags);
373 /* The current buffer is a chain buffer.
374 * chainSge points to the previous Chain Element.
375 * Update its chain element Offset and Length (must
376 * include chain element size) fields.
377 * Old chain element is now complete.
379 u8 nextChain = (u8) (sgeOffset >> 2);
380 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
381 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
383 /* The original MF buffer requires a chain buffer -
385 * Last element in this MF is a chain element.
387 pReq->ChainOffset = (u8) (sgeOffset >> 2);
388 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
389 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
390 ioc->RequestNB[req_idx] = RequestNB;
393 sges_left -= sg_done;
396 /* NOTE: psge points to the beginning of the chain element
397 * in current buffer. Get a chain buffer.
399 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
400 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
401 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
402 ioc->name, pReq->CDB[0], SCpnt));
406 /* Update the tracking arrays.
407 * If chainSge == NULL, update ReqToChain, else ChainToChain
410 ioc->ChainToChain[chain_idx] = newIndex;
412 ioc->ReqToChain[req_idx] = newIndex;
414 chain_idx = newIndex;
415 chain_dma_off = ioc->req_sz * chain_idx;
417 /* Populate the chainSGE for the current buffer.
418 * - Set chain buffer pointer to psge and fill
419 * out the Address and Flags fields.
421 chainSge = (char *) psge;
422 dsgprintk(ioc, printk(KERN_DEBUG " Current buff @ %p (index 0x%x)",
425 /* Start the SGE for the next buffer
427 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
431 dsgprintk(ioc, printk(KERN_DEBUG " Chain buff @ %p (index 0x%x)\n",
434 /* Start the SGE for the next buffer
441 } /* mptscsih_AddSGE() */
444 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
448 SEPRequest_t *SEPMsg;
450 if (ioc->bus_type != SAS)
453 /* Not supported for hidden raid components
455 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
458 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
459 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
460 ioc->name,__FUNCTION__));
464 SEPMsg = (SEPRequest_t *)mf;
465 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
466 SEPMsg->Bus = vtarget->channel;
467 SEPMsg->TargetID = vtarget->id;
468 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
469 SEPMsg->SlotStatus = SlotStatus;
470 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
471 "Sending SEP cmd=%x channel=%d id=%d\n",
472 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
473 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
476 #ifdef CONFIG_FUSION_LOGGING
478 * mptscsih_info_scsiio - debug print info on reply frame
479 * @ioc: Pointer to MPT_ADAPTER structure
480 * @sc: original scsi cmnd pointer
481 * @pScsiReply: Pointer to MPT reply frame
483 * MPT_DEBUG_REPLY needs to be enabled to obtain this info
485 * Refer to lsi/mpi.h.
488 mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
495 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
497 switch (ioc_status) {
499 case MPI_IOCSTATUS_SUCCESS:
502 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
503 desc = "invalid bus";
505 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
506 desc = "invalid target_id";
508 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
509 desc = "device not there";
511 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
512 desc = "data overrun";
514 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
515 desc = "data underrun";
517 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
518 desc = "I/O data error";
520 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
521 desc = "protocol error";
523 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
524 desc = "task terminated";
526 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
527 desc = "residual mismatch";
529 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
530 desc = "task management failed";
532 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
533 desc = "IOC terminated";
535 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
536 desc = "ext terminated";
543 switch (pScsiReply->SCSIStatus)
546 case MPI_SCSI_STATUS_SUCCESS:
549 case MPI_SCSI_STATUS_CHECK_CONDITION:
550 desc1 = "check condition";
552 case MPI_SCSI_STATUS_CONDITION_MET:
553 desc1 = "condition met";
555 case MPI_SCSI_STATUS_BUSY:
558 case MPI_SCSI_STATUS_INTERMEDIATE:
559 desc1 = "intermediate";
561 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
562 desc1 = "intermediate condmet";
564 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
565 desc1 = "reservation conflict";
567 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
568 desc1 = "command terminated";
570 case MPI_SCSI_STATUS_TASK_SET_FULL:
571 desc1 = "task set full";
573 case MPI_SCSI_STATUS_ACA_ACTIVE:
574 desc1 = "aca active";
576 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
577 desc1 = "fcpext device logged out";
579 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
580 desc1 = "fcpext no link";
582 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
583 desc1 = "fcpext unassigned";
590 scsi_print_command(sc);
591 printk(KERN_DEBUG "\tfw_channel = %d, fw_id = %d\n",
592 pScsiReply->Bus, pScsiReply->TargetID);
593 printk(KERN_DEBUG "\trequest_len = %d, underflow = %d, resid = %d\n",
594 scsi_bufflen(sc), sc->underflow, scsi_get_resid(sc));
595 printk(KERN_DEBUG "\ttag = %d, transfer_count = %d, sc->result = %08X\n",
596 le16_to_cpu(pScsiReply->TaskTag),
597 le32_to_cpu(pScsiReply->TransferCount), sc->result);
599 printk(KERN_DEBUG "\tiocstatus = %s (0x%04x), "
600 "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",
602 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(KERN_DEBUG "\t[sense_key,asc,ascq]: "
611 "[0x%02x,0x%02x,0x%02x]\n",
616 * Look for + dump FCP ResponseInfo[]!
618 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
619 pScsiReply->ResponseInfo)
620 printk(KERN_DEBUG "response_info = %08xh\n",
621 le32_to_cpu(pScsiReply->ResponseInfo));
625 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
627 * mptscsih_io_done - Main SCSI IO callback routine registered to
628 * Fusion MPT (base) driver
629 * @ioc: Pointer to MPT_ADAPTER structure
630 * @mf: Pointer to original MPT request frame
631 * @r: Pointer to MPT reply frame (NULL if TurboReply)
633 * This routine is called from mpt.c::mpt_interrupt() at the completion
634 * of any SCSI IO request.
635 * This routine is registered with the Fusion MPT (base) driver at driver
636 * load/init time via the mpt_register() API call.
638 * Returns 1 indicating alloc'd request frame ptr should be freed.
641 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
643 struct scsi_cmnd *sc;
645 SCSIIORequest_t *pScsiReq;
646 SCSIIOReply_t *pScsiReply;
647 u16 req_idx, req_idx_MR;
651 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
653 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
654 req_idx_MR = (mr != NULL) ?
655 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
656 if ((req_idx != req_idx_MR) ||
657 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
658 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
660 printk (MYIOC_s_ERR_FMT
661 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
662 ioc->name, req_idx, req_idx_MR, mf, mr,
663 hd->ScsiLookup[req_idx_MR]);
667 sc = hd->ScsiLookup[req_idx];
668 hd->ScsiLookup[req_idx] = NULL;
670 MPIHeader_t *hdr = (MPIHeader_t *)mf;
672 /* Remark: writeSDP1 will use the ScsiDoneCtx
673 * If a SCSI I/O cmd, device disabled by OS and
674 * completion done. Cannot touch sc struct. Just free mem.
676 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
677 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
680 mptscsih_freeChainBuffers(ioc, req_idx);
684 if ((unsigned char *)mf != sc->host_scribble) {
685 mptscsih_freeChainBuffers(ioc, req_idx);
689 sc->host_scribble = NULL;
690 sc->result = DID_OK << 16; /* Set default reply as OK */
691 pScsiReq = (SCSIIORequest_t *) mf;
692 pScsiReply = (SCSIIOReply_t *) mr;
694 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
695 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
696 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
697 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
699 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT
700 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
701 ioc->name, mf, mr, sc, req_idx));
704 if (pScsiReply == NULL) {
705 /* special context reply handling */
710 u8 scsi_state, scsi_status;
713 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
714 scsi_state = pScsiReply->SCSIState;
715 scsi_status = pScsiReply->SCSIStatus;
716 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
717 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
718 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
721 * if we get a data underrun indication, yet no data was
722 * transferred and the SCSI status indicates that the
723 * command was never started, change the data underrun
726 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
727 (scsi_status == MPI_SCSI_STATUS_BUSY ||
728 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
729 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
730 status = MPI_IOCSTATUS_SUCCESS;
733 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
734 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
737 * Look for + dump FCP ResponseInfo[]!
739 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
740 pScsiReply->ResponseInfo) {
741 printk(KERN_NOTICE "[%d:%d:%d:%d] "
742 "FCP_ResponseInfo=%08xh\n",
743 sc->device->host->host_no, sc->device->channel,
744 sc->device->id, sc->device->lun,
745 le32_to_cpu(pScsiReply->ResponseInfo));
749 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
751 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
752 * But not: DID_BUS_BUSY lest one risk
753 * killing interrupt handler:-(
755 sc->result = SAM_STAT_BUSY;
758 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
759 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
760 sc->result = DID_BAD_TARGET << 16;
763 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
764 /* Spoof to SCSI Selection Timeout! */
765 if (ioc->bus_type != FC)
766 sc->result = DID_NO_CONNECT << 16;
767 /* else fibre, just stall until rescan event */
769 sc->result = DID_REQUEUE << 16;
771 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
772 hd->sel_timeout[pScsiReq->TargetID]++;
774 vdev = sc->device->hostdata;
777 vtarget = vdev->vtarget;
778 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
779 mptscsih_issue_sep_command(ioc, vtarget,
780 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
781 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
785 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
786 if ( ioc->bus_type == SAS ) {
787 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
788 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
789 if ((log_info & SAS_LOGINFO_MASK)
790 == SAS_LOGINFO_NEXUS_LOSS) {
791 sc->result = (DID_BUS_BUSY << 16);
795 } else if (ioc->bus_type == FC) {
797 * The FC IOC may kill a request for variety of
798 * reasons, some of which may be recovered by a
799 * retry, some which are unlikely to be
800 * recovered. Return DID_ERROR instead of
801 * DID_RESET to permit retry of the command,
802 * just not an infinite number of them
804 sc->result = DID_ERROR << 16;
809 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
812 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
813 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
814 /* Linux handles an unsolicited DID_RESET better
815 * than an unsolicited DID_ABORT.
817 sc->result = DID_RESET << 16;
821 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
822 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
823 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
824 sc->result=DID_SOFT_ERROR << 16;
825 else /* Sufficient data transfer occurred */
826 sc->result = (DID_OK << 16) | scsi_status;
827 dreplyprintk(ioc, printk(KERN_DEBUG
828 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
829 sc->result, sc->device->channel, sc->device->id));
832 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
834 * Do upfront check for valid SenseData and give it
837 sc->result = (DID_OK << 16) | scsi_status;
838 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
839 /* Have already saved the status and sense data
843 if (xfer_cnt < sc->underflow) {
844 if (scsi_status == SAM_STAT_BUSY)
845 sc->result = SAM_STAT_BUSY;
847 sc->result = DID_SOFT_ERROR << 16;
849 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
852 sc->result = DID_SOFT_ERROR << 16;
854 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
855 /* Not real sure here either... */
856 sc->result = DID_RESET << 16;
861 dreplyprintk(ioc, printk(KERN_DEBUG " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
863 dreplyprintk(ioc, printk(KERN_DEBUG " ActBytesXferd=%02xh\n", xfer_cnt));
867 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
868 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
872 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
873 scsi_set_resid(sc, 0);
874 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
875 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
876 sc->result = (DID_OK << 16) | scsi_status;
877 if (scsi_state == 0) {
879 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
881 * If running against circa 200003dd 909 MPT f/w,
882 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
883 * (QUEUE_FULL) returned from device! --> get 0x0000?128
884 * and with SenseBytes set to 0.
886 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
887 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
890 else if (scsi_state &
891 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
896 sc->result = DID_SOFT_ERROR << 16;
898 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
899 /* Not real sure here either... */
900 sc->result = DID_RESET << 16;
902 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
903 /* Device Inq. data indicates that it supports
904 * QTags, but rejects QTag messages.
905 * This command completed OK.
907 * Not real sure here either so do nothing... */
910 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
911 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
914 * Reservation Conflict, Busy,
915 * Command Terminated, CHECK
919 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
920 sc->result = DID_SOFT_ERROR << 16;
923 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
924 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
925 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
926 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
927 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
928 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
929 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
930 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
931 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
936 sc->result = DID_SOFT_ERROR << 16;
939 } /* switch(status) */
941 #ifdef CONFIG_FUSION_LOGGING
942 if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY))
943 mptscsih_info_scsiio(ioc, sc, pScsiReply);
946 } /* end of address reply case */
948 /* Unmap the DMA buffers, if any. */
951 sc->scsi_done(sc); /* Issue the command callback */
953 /* Free Chain buffers */
954 mptscsih_freeChainBuffers(ioc, req_idx);
959 * mptscsih_flush_running_cmds - For each command found, search
960 * Scsi_Host instance taskQ and reply to OS.
961 * Called only if recovering from a FW reload.
962 * @hd: Pointer to a SCSI HOST structure
966 * Must be called while new I/Os are being queued.
969 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
971 MPT_ADAPTER *ioc = hd->ioc;
972 struct scsi_cmnd *SCpnt;
975 int max = ioc->req_depth;
977 dprintk(ioc, printk(KERN_DEBUG MYNAM ": flush_ScsiLookup called\n"));
978 for (ii= 0; ii < max; ii++) {
979 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
984 /* Null ScsiLookup index
986 hd->ScsiLookup[ii] = NULL;
988 mf = MPT_INDEX_2_MFPTR(ioc, ii);
989 dmfprintk(ioc, printk(KERN_DEBUG MYNAM ": flush: ScsiDone (mf=%p,sc=%p)\n",
992 /* Free Chain buffers */
993 mptscsih_freeChainBuffers(ioc, ii);
995 /* Free Message frames */
996 mpt_free_msg_frame(ioc, mf);
998 if ((unsigned char *)mf != SCpnt->host_scribble)
1001 /* Set status, free OS resources (SG DMA buffers)
1004 scsi_dma_unmap(SCpnt);
1006 SCpnt->result = DID_RESET << 16;
1007 SCpnt->host_scribble = NULL;
1009 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1017 * mptscsih_search_running_cmds - Delete any commands associated
1018 * with the specified target and lun. Function called only
1019 * when a lun is disable by mid-layer.
1020 * Do NOT access the referenced scsi_cmnd structure or
1021 * members. Will cause either a paging or NULL ptr error.
1022 * (BUT, BUT, BUT, the code does reference it! - mdr)
1023 * @hd: Pointer to a SCSI HOST structure
1024 * @vdevice: per device private data
1028 * Called from slave_destroy.
1031 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1033 SCSIIORequest_t *mf = NULL;
1035 int max = hd->ioc->req_depth;
1036 struct scsi_cmnd *sc;
1037 struct scsi_lun lun;
1039 dsprintk(hd->ioc, printk(KERN_DEBUG MYNAM ": search_running channel %d id %d lun %d max %d\n",
1040 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
1042 for (ii=0; ii < max; ii++) {
1043 if ((sc = hd->ScsiLookup[ii]) != NULL) {
1045 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1048 /* If the device is a hidden raid component, then its
1049 * expected that the mf->function will be RAID_SCSI_IO
1051 if (vdevice->vtarget->tflags &
1052 MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function !=
1053 MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)
1056 int_to_scsilun(vdevice->lun, &lun);
1057 if ((mf->Bus != vdevice->vtarget->channel) ||
1058 (mf->TargetID != vdevice->vtarget->id) ||
1059 memcmp(lun.scsi_lun, mf->LUN, 8))
1064 hd->ScsiLookup[ii] = NULL;
1065 mptscsih_freeChainBuffers(hd->ioc, ii);
1066 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1067 if ((unsigned char *)mf != sc->host_scribble)
1070 sc->host_scribble = NULL;
1071 sc->result = DID_NO_CONNECT << 16;
1072 sdev_printk(KERN_INFO, sc->device, "completing cmds: fw_channel %d,"
1073 "fw_id %d, sc=%p, mf = %p, idx=%x\n", vdevice->vtarget->channel,
1074 vdevice->vtarget->id, sc, mf, ii);
1081 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1083 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1085 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1086 * from a SCSI target device.
1087 * @sc: Pointer to scsi_cmnd structure
1088 * @pScsiReply: Pointer to SCSIIOReply_t
1089 * @pScsiReq: Pointer to original SCSI request
1091 * This routine periodically reports QUEUE_FULL status returned from a
1092 * SCSI target device. It reports this to the console via kernel
1093 * printk() API call, not more than once every 10 seconds.
1096 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1098 long time = jiffies;
1101 if (sc->device == NULL)
1103 if (sc->device->host == NULL)
1105 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1108 if (time - hd->last_queue_full > 10 * HZ) {
1109 dprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1110 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1111 hd->last_queue_full = time;
1115 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1117 * mptscsih_remove - Removed scsi devices
1118 * @pdev: Pointer to pci_dev structure
1123 mptscsih_remove(struct pci_dev *pdev)
1125 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1126 struct Scsi_Host *host = ioc->sh;
1135 scsi_remove_host(host);
1137 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1140 mptscsih_shutdown(pdev);
1144 if (hd->ScsiLookup != NULL) {
1145 sz1 = hd->ioc->req_depth * sizeof(void *);
1146 kfree(hd->ScsiLookup);
1147 hd->ScsiLookup = NULL;
1150 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
1151 "Free'd ScsiLookup (%d) memory\n",
1152 hd->ioc->name, sz1));
1154 kfree(hd->info_kbuf);
1156 /* NULL the Scsi_Host pointer
1160 scsi_host_put(host);
1166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1168 * mptscsih_shutdown - reboot notifier
1172 mptscsih_shutdown(struct pci_dev *pdev)
1174 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1175 struct Scsi_Host *host = ioc->sh;
1181 hd = (MPT_SCSI_HOST *)host->hostdata;
1186 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1188 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1193 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1195 mptscsih_shutdown(pdev);
1196 return mpt_suspend(pdev,state);
1199 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1201 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1206 mptscsih_resume(struct pci_dev *pdev)
1208 return mpt_resume(pdev);
1213 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1215 * mptscsih_info - Return information about MPT adapter
1216 * @SChost: Pointer to Scsi_Host structure
1218 * (linux scsi_host_template.info routine)
1220 * Returns pointer to buffer where information was written.
1223 mptscsih_info(struct Scsi_Host *SChost)
1228 h = (MPT_SCSI_HOST *)SChost->hostdata;
1231 if (h->info_kbuf == NULL)
1232 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1233 return h->info_kbuf;
1234 h->info_kbuf[0] = '\0';
1236 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1237 h->info_kbuf[size-1] = '\0';
1240 return h->info_kbuf;
1251 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1253 if (info->pos + len > info->length)
1254 len = info->length - info->pos;
1256 if (info->pos + len < info->offset) {
1261 if (info->pos < info->offset) {
1262 data += (info->offset - info->pos);
1263 len -= (info->offset - info->pos);
1267 memcpy(info->buffer + info->pos, data, len);
1273 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1279 va_start(args, fmt);
1280 len = vsprintf(buf, fmt, args);
1283 mptscsih_copy_mem_info(info, buf, len);
1288 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1290 struct info_str info;
1294 info.offset = offset;
1297 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1298 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1299 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1300 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1302 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1305 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1307 * mptscsih_proc_info - Return information about MPT adapter
1308 * @host: scsi host struct
1309 * @buffer: if write, user data; if read, buffer for user
1310 * @start: returns the buffer address
1311 * @offset: if write, 0; if read, the current offset into the buffer from
1312 * the previous read.
1313 * @length: if write, return length;
1314 * @func: write = 1; read = 0
1316 * (linux scsi_host_template.info routine)
1319 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1320 int length, int func)
1322 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1323 MPT_ADAPTER *ioc = hd->ioc;
1328 * write is not supported
1334 size = mptscsih_host_info(ioc, buffer, offset, length);
1340 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1341 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1343 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1345 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1346 * @SCpnt: Pointer to scsi_cmnd structure
1347 * @done: Pointer SCSI mid-layer IO completion function
1349 * (linux scsi_host_template.queuecommand routine)
1350 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1351 * from a linux scsi_cmnd request and send it to the IOC.
1353 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1356 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1360 SCSIIORequest_t *pScsiReq;
1361 VirtDevice *vdev = SCpnt->device->hostdata;
1371 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1373 lun = SCpnt->device->lun;
1374 SCpnt->scsi_done = done;
1376 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n",
1377 ioc->name, SCpnt, done));
1379 if (hd->resetPending) {
1380 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1382 return SCSI_MLQUEUE_HOST_BUSY;
1386 * Put together a MPT SCSI request...
1388 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1389 dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1391 return SCSI_MLQUEUE_HOST_BUSY;
1394 pScsiReq = (SCSIIORequest_t *) mf;
1396 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1398 ADD_INDEX_LOG(my_idx);
1400 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1401 * Seems we may receive a buffer (datalen>0) even when there
1402 * will be no data transfer! GRRRRR...
1404 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1405 datalen = scsi_bufflen(SCpnt);
1406 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1407 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1408 datalen = scsi_bufflen(SCpnt);
1409 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1412 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1415 /* Default to untagged. Once a target structure has been allocated,
1416 * use the Inquiry data to determine if device supports tagged.
1419 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1420 && (SCpnt->device->tagged_supported)) {
1421 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1423 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1426 /* Use the above information to set up the message frame
1428 pScsiReq->TargetID = (u8) vdev->vtarget->id;
1429 pScsiReq->Bus = vdev->vtarget->channel;
1430 pScsiReq->ChainOffset = 0;
1431 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1432 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1434 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1435 pScsiReq->CDBLength = SCpnt->cmd_len;
1436 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1437 pScsiReq->Reserved = 0;
1438 pScsiReq->MsgFlags = mpt_msg_flags();
1439 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1440 pScsiReq->Control = cpu_to_le32(scsictl);
1443 * Write SCSI CDB into the message
1445 cmd_len = SCpnt->cmd_len;
1446 for (ii=0; ii < cmd_len; ii++)
1447 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1449 for (ii=cmd_len; ii < 16; ii++)
1450 pScsiReq->CDB[ii] = 0;
1453 pScsiReq->DataLength = cpu_to_le32(datalen);
1455 /* SenseBuffer low address */
1456 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1457 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1459 /* Now add the SG list
1460 * Always have a SGE even if null length.
1463 /* Add a NULL SGE */
1464 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1467 /* Add a 32 or 64 bit SGE */
1468 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1472 SCpnt->host_scribble = (unsigned char *)mf;
1473 hd->ScsiLookup[my_idx] = SCpnt;
1475 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1476 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1477 ioc->name, SCpnt, mf, my_idx));
1478 DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf)
1482 hd->ScsiLookup[my_idx] = NULL;
1483 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1484 mpt_free_msg_frame(hd->ioc, mf);
1485 return SCSI_MLQUEUE_HOST_BUSY;
1488 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1490 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1491 * with a SCSI IO request
1492 * @hd: Pointer to the MPT_SCSI_HOST instance
1493 * @req_idx: Index of the SCSI IO request frame.
1495 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1499 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1501 MPT_FRAME_HDR *chain;
1502 unsigned long flags;
1506 /* Get the first chain index and reset
1509 chain_idx = ioc->ReqToChain[req_idx];
1510 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1512 while (chain_idx != MPT_HOST_NO_CHAIN) {
1514 /* Save the next chain buffer index */
1515 next = ioc->ChainToChain[chain_idx];
1517 /* Free this chain buffer and reset
1520 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1522 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1523 + (chain_idx * ioc->req_sz));
1525 spin_lock_irqsave(&ioc->FreeQlock, flags);
1526 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1527 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1529 dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1530 ioc->name, chain_idx));
1538 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1543 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1545 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1546 * @hd: Pointer to MPT SCSI HOST structure
1547 * @type: Task Management type
1548 * @channel: channel number for task management
1549 * @id: Logical Target ID for reset (if appropriate)
1550 * @lun: Logical Unit for reset (if appropriate)
1551 * @ctx2abort: Context for the task to be aborted (if appropriate)
1552 * @timeout: timeout for task management control
1554 * Fall through to mpt_HardResetHandler if: not operational, too many
1555 * failed TM requests or handshake failure.
1557 * Remark: Currently invoked from a non-interrupt thread (_bh).
1559 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1562 * Returns 0 for SUCCESS, or %FAILED.
1565 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1570 unsigned long flags;
1573 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler Entered!\n", ioc->name));
1575 // SJR - CHECKME - Can we avoid this here?
1576 // (mpt_HardResetHandler has this check...)
1577 spin_lock_irqsave(&ioc->diagLock, flags);
1578 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1579 spin_unlock_irqrestore(&ioc->diagLock, flags);
1582 spin_unlock_irqrestore(&ioc->diagLock, flags);
1584 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1585 * If we time out and not bus reset, then we return a FAILED status
1587 * The call to mptscsih_tm_pending_wait() will set the pending flag
1589 * successful. Otherwise, reload the FW.
1591 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1592 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1593 dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler abort: "
1594 "Timed out waiting for last TM (%d) to complete! \n",
1595 ioc->name, hd->tmPending));
1597 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1598 dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler target "
1599 "reset: Timed out waiting for last TM (%d) "
1600 "to complete! \n", ioc->name,
1603 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1604 dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler bus reset: "
1605 "Timed out waiting for last TM (%d) to complete! \n",
1606 ioc->name, hd->tmPending));
1610 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1611 hd->tmPending |= (1 << type);
1612 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1615 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1617 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1618 printk(MYIOC_s_WARN_FMT
1619 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1620 ioc->name, type, ioc_raw_state);
1621 printk(KERN_WARNING " Issuing HardReset!!\n");
1622 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1623 printk((KERN_WARNING "TMHandler: HardReset "
1628 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1629 printk(MYIOC_s_WARN_FMT
1630 "TM Handler for type=%x: ioc_state: "
1631 "DOORBELL_ACTIVE (0x%x)!\n",
1632 ioc->name, type, ioc_raw_state);
1636 /* Isse the Task Mgmt request.
1638 if (hd->hard_resets < -1)
1641 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1642 ctx2abort, timeout);
1644 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1647 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
1650 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1651 "TMHandler rc = %d!\n", ioc->name, rc));
1657 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1659 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1660 * @hd: Pointer to MPT_SCSI_HOST structure
1661 * @type: Task Management type
1662 * @channel: channel number for task management
1663 * @id: Logical Target ID for reset (if appropriate)
1664 * @lun: Logical Unit for reset (if appropriate)
1665 * @ctx2abort: Context for the task to be aborted (if appropriate)
1666 * @timeout: timeout for task management control
1668 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1669 * or a non-interrupt thread. In the former, must not call schedule().
1671 * Not all fields are meaningfull for all task types.
1673 * Returns 0 for SUCCESS, or FAILED.
1677 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1680 SCSITaskMgmt_t *pScsiTm;
1684 /* Return Fail to calling function if no message frames available.
1686 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1687 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1691 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n",
1692 hd->ioc->name, mf));
1694 /* Format the Request
1696 pScsiTm = (SCSITaskMgmt_t *) mf;
1697 pScsiTm->TargetID = id;
1698 pScsiTm->Bus = channel;
1699 pScsiTm->ChainOffset = 0;
1700 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1702 pScsiTm->Reserved = 0;
1703 pScsiTm->TaskType = type;
1704 pScsiTm->Reserved1 = 0;
1705 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1706 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1708 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1710 for (ii=0; ii < 7; ii++)
1711 pScsiTm->Reserved2[ii] = 0;
1713 pScsiTm->TaskMsgContext = ctx2abort;
1715 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1716 "type=%d\n", hd->ioc->name, ctx2abort, type));
1718 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1720 if ((hd->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1721 (hd->ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1722 mpt_put_msg_frame_hi_pri(hd->ioc->TaskCtx, hd->ioc, mf);
1724 retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1725 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1727 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
1728 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1729 hd->ioc, mf, retval));
1734 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1735 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1736 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1738 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
1740 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1741 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
1742 hd->ioc->name, retval));
1747 * Handle success case, see if theres a non-zero ioc_status.
1749 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1750 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1751 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1761 * Free task managment mf, and corresponding tm flags
1763 mpt_free_msg_frame(hd->ioc, mf);
1765 hd->tmState = TM_STATE_NONE;
1770 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1772 switch (ioc->bus_type) {
1783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1785 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1786 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1788 * (linux scsi_host_template.eh_abort_handler routine)
1790 * Returns SUCCESS or FAILED.
1793 mptscsih_abort(struct scsi_cmnd * SCpnt)
1800 VirtDevice *vdevice;
1801 ulong sn = SCpnt->serial_number;
1804 /* If we can't locate our host adapter structure, return FAILED status.
1806 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1807 SCpnt->result = DID_RESET << 16;
1808 SCpnt->scsi_done(SCpnt);
1809 printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate "
1810 "host! (sc=%p)\n", SCpnt);
1815 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1817 scsi_print_command(SCpnt);
1819 vdevice = SCpnt->device->hostdata;
1820 if (!vdevice || !vdevice->vtarget) {
1821 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: device has been "
1822 "deleted (sc=%p)\n", ioc->name, SCpnt));
1823 SCpnt->result = DID_NO_CONNECT << 16;
1824 SCpnt->scsi_done(SCpnt);
1829 /* Task aborts are not supported for hidden raid components.
1831 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1832 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid "
1833 "component (sc=%p)\n", ioc->name, SCpnt));
1834 SCpnt->result = DID_RESET << 16;
1839 /* Find this command
1841 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1842 /* Cmd not found in ScsiLookup.
1845 SCpnt->result = DID_RESET << 16;
1846 dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: "
1847 "Command not in the active list! (sc=%p)\n", ioc->name,
1853 if (hd->resetPending) {
1858 if (hd->timeouts < -1)
1861 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1862 * (the IO to be ABORT'd)
1864 * NOTE: Since we do not byteswap MsgContext, we do not
1865 * swap it here either. It is an opaque cookie to
1866 * the controller, so it does not matter. -DaveM
1868 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1869 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1871 hd->abortSCpnt = SCpnt;
1873 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1874 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1875 ctx2abort, mptscsih_get_tm_timeout(ioc));
1877 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1878 SCpnt->serial_number == sn)
1882 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
1883 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1891 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1893 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1894 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1896 * (linux scsi_host_template.eh_dev_reset_handler routine)
1898 * Returns SUCCESS or FAILED.
1901 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1905 VirtDevice *vdevice;
1908 /* If we can't locate our host adapter structure, return FAILED status.
1910 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1911 printk(KERN_DEBUG MYNAM ": mptscsih_dev_reset: Can't "
1912 "locate host! (sc=%p)\n", SCpnt);
1917 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1919 scsi_print_command(SCpnt);
1921 if (hd->resetPending) {
1926 vdevice = SCpnt->device->hostdata;
1927 if (!vdevice || !vdevice->vtarget) {
1932 /* Target reset to hidden raid component is not supported
1934 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1939 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1940 vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
1941 mptscsih_get_tm_timeout(ioc));
1944 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1945 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1954 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1956 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1957 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1959 * (linux scsi_host_template.eh_bus_reset_handler routine)
1961 * Returns SUCCESS or FAILED.
1964 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1971 /* If we can't locate our host adapter structure, return FAILED status.
1973 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1974 printk(KERN_DEBUG MYNAM ": mptscsih_bus_reset: Can't "
1975 "locate host! (sc=%p)\n", SCpnt );
1980 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1982 scsi_print_command(SCpnt);
1984 if (hd->timeouts < -1)
1987 vdev = SCpnt->device->hostdata;
1988 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1989 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
1991 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1992 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
2000 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2002 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
2003 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
2005 * (linux scsi_host_template.eh_host_reset_handler routine)
2007 * Returns SUCCESS or FAILED.
2010 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
2016 /* If we can't locate the host to reset, then we failed. */
2017 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2018 printk( KERN_DEBUG MYNAM ": mptscsih_host_reset: Can't "
2019 "locate host! (sc=%p)\n", SCpnt);
2024 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
2027 /* If our attempts to reset the host failed, then return a failed
2028 * status. The host will be taken off line by the SCSI mid-layer.
2030 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
2033 /* Make sure TM pending is cleared and TM state is set to
2038 hd->tmState = TM_STATE_NONE;
2041 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
2042 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
2047 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2049 * mptscsih_tm_pending_wait - wait for pending task management request to complete
2050 * @hd: Pointer to MPT host structure.
2052 * Returns {SUCCESS,FAILED}.
2055 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
2057 unsigned long flags;
2058 int loop_count = 4 * 10; /* Wait 10 seconds */
2059 int status = FAILED;
2062 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2063 if (hd->tmState == TM_STATE_NONE) {
2064 hd->tmState = TM_STATE_IN_PROGRESS;
2066 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2070 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2072 } while (--loop_count);
2077 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2079 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2080 * @hd: Pointer to MPT host structure.
2081 * @timeout: timeout value
2083 * Returns {SUCCESS,FAILED}.
2086 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2088 unsigned long flags;
2089 int loop_count = 4 * timeout;
2090 int status = FAILED;
2093 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2094 if(hd->tmPending == 0) {
2096 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2099 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2101 } while (--loop_count);
2106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2108 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2112 switch (response_code) {
2113 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2114 desc = "The task completed.";
2116 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2117 desc = "The IOC received an invalid frame status.";
2119 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2120 desc = "The task type is not supported.";
2122 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2123 desc = "The requested task failed.";
2125 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2126 desc = "The task completed successfully.";
2128 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2129 desc = "The LUN request is invalid.";
2131 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2132 desc = "The task is in the IOC queue and has not been sent to target.";
2138 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2139 ioc->name, response_code, desc);
2142 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2144 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2145 * @ioc: Pointer to MPT_ADAPTER structure
2146 * @mf: Pointer to SCSI task mgmt request frame
2147 * @mr: Pointer to SCSI task mgmt reply frame
2149 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2150 * of any SCSI task management request.
2151 * This routine is registered with the MPT (base) driver at driver
2152 * load/init time via the mpt_register() API call.
2154 * Returns 1 indicating alloc'd request frame ptr should be freed.
2157 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2159 SCSITaskMgmtReply_t *pScsiTmReply;
2160 SCSITaskMgmt_t *pScsiTmReq;
2162 unsigned long flags;
2165 u32 termination_count;
2167 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2168 ioc->name, mf, mr));
2170 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2171 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2176 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2177 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2181 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2182 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2183 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2184 tmType = pScsiTmReq->TaskType;
2185 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2186 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2188 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2189 pScsiTmReply->ResponseCode)
2190 mptscsih_taskmgmt_response_code(ioc,
2191 pScsiTmReply->ResponseCode);
2192 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
2194 #ifdef CONFIG_FUSION_LOGGING
2195 if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
2196 (ioc->debug_level & MPT_DEBUG_TM ))
2197 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2198 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2199 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2200 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2201 le16_to_cpu(pScsiTmReply->IOCStatus),
2202 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2203 le32_to_cpu(pScsiTmReply->TerminationCount));
2206 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
2207 hd->abortSCpnt = NULL;
2211 /* Error? (anything non-zero?) */
2213 /* clear flags and continue.
2217 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2218 if (termination_count == 1)
2219 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2220 hd->abortSCpnt = NULL;
2223 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2225 /* If an internal command is present
2226 * or the TM failed - reload the FW.
2227 * FC FW may respond FAILED to an ABORT
2229 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2231 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2232 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2235 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2241 spin_lock_irqsave(&ioc->FreeQlock, flags);
2243 hd->tmState = TM_STATE_NONE;
2244 hd->tm_iocstatus = iocstatus;
2245 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2250 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2252 * This is anyones guess quite frankly.
2255 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2256 sector_t capacity, int geom[])
2266 dummy = heads * sectors;
2267 cylinders = capacity;
2268 sector_div(cylinders,dummy);
2271 * Handle extended translation size for logical drives
2274 if ((ulong)capacity >= 0x200000) {
2277 dummy = heads * sectors;
2278 cylinders = capacity;
2279 sector_div(cylinders,dummy);
2285 geom[2] = cylinders;
2290 /* Search IOC page 3 to determine if this is hidden physical disk
2294 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2296 struct inactive_raid_component_info *component_info;
2300 if (!ioc->raid_data.pIocPg3)
2302 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2303 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2304 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2311 * Check inactive list for matching phys disks
2313 if (list_empty(&ioc->raid_data.inactive_list))
2316 down(&ioc->raid_data.inactive_list_mutex);
2317 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2319 if ((component_info->d.PhysDiskID == id) &&
2320 (component_info->d.PhysDiskBus == channel))
2323 up(&ioc->raid_data.inactive_list_mutex);
2328 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2331 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2333 struct inactive_raid_component_info *component_info;
2337 if (!ioc->raid_data.pIocPg3)
2339 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2340 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2341 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2342 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2348 * Check inactive list for matching phys disks
2350 if (list_empty(&ioc->raid_data.inactive_list))
2353 down(&ioc->raid_data.inactive_list_mutex);
2354 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2356 if ((component_info->d.PhysDiskID == id) &&
2357 (component_info->d.PhysDiskBus == channel))
2358 rc = component_info->d.PhysDiskNum;
2360 up(&ioc->raid_data.inactive_list_mutex);
2365 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2368 * OS entry point to allow for host driver to free allocated memory
2369 * Called if no device present or device being unloaded
2372 mptscsih_slave_destroy(struct scsi_device *sdev)
2374 struct Scsi_Host *host = sdev->host;
2375 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2376 VirtTarget *vtarget;
2377 VirtDevice *vdevice;
2378 struct scsi_target *starget;
2380 starget = scsi_target(sdev);
2381 vtarget = starget->hostdata;
2382 vdevice = sdev->hostdata;
2384 mptscsih_search_running_cmds(hd, vdevice);
2385 vtarget->num_luns--;
2386 mptscsih_synchronize_cache(hd, vdevice);
2388 sdev->hostdata = NULL;
2391 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2393 * mptscsih_change_queue_depth - This function will set a devices queue depth
2394 * @sdev: per scsi_device pointer
2395 * @qdepth: requested queue depth
2397 * Adding support for new 'change_queue_depth' api.
2400 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2402 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2403 VirtTarget *vtarget;
2404 struct scsi_target *starget;
2408 starget = scsi_target(sdev);
2409 vtarget = starget->hostdata;
2411 if (hd->ioc->bus_type == SPI) {
2412 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2414 else if (sdev->type == TYPE_DISK &&
2415 vtarget->minSyncFactor <= MPT_ULTRA160)
2416 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2418 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2420 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2422 if (qdepth > max_depth)
2427 tagged = MSG_SIMPLE_TAG;
2429 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2430 return sdev->queue_depth;
2434 * OS entry point to adjust the queue_depths on a per-device basis.
2435 * Called once per device the bus scan. Use it to force the queue_depth
2436 * member to 1 if a device does not support Q tags.
2437 * Return non-zero if fails.
2440 mptscsih_slave_configure(struct scsi_device *sdev)
2442 struct Scsi_Host *sh = sdev->host;
2443 VirtTarget *vtarget;
2444 VirtDevice *vdevice;
2445 struct scsi_target *starget;
2446 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2448 starget = scsi_target(sdev);
2449 vtarget = starget->hostdata;
2450 vdevice = sdev->hostdata;
2452 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2453 "device @ %p, channel=%d, id=%d, lun=%d\n",
2454 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2455 if (hd->ioc->bus_type == SPI)
2456 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2457 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2458 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2459 sdev->ppr, sdev->inquiry_len));
2461 if (sdev->id > sh->max_id) {
2462 /* error case, should never happen */
2463 scsi_adjust_queue_depth(sdev, 0, 1);
2464 goto slave_configure_exit;
2467 vdevice->configured_lun = 1;
2468 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2470 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2471 "Queue depth=%d, tflags=%x\n",
2472 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2474 if (hd->ioc->bus_type == SPI)
2475 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2476 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2477 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2478 vtarget->minSyncFactor));
2480 slave_configure_exit:
2482 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2483 "tagged %d, simple %d, ordered %d\n",
2484 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2485 sdev->ordered_tags));
2490 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2492 * Private routines...
2495 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2496 /* Utility function to copy sense data from the scsi_cmnd buffer
2497 * to the FC and SCSI target structures.
2501 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2504 SCSIIORequest_t *pReq;
2505 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2507 /* Get target structure
2509 pReq = (SCSIIORequest_t *) mf;
2510 vdev = sc->device->hostdata;
2516 /* Copy the sense received into the scsi command block. */
2517 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2518 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2519 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2521 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2523 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2524 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2526 MPT_ADAPTER *ioc = hd->ioc;
2528 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2529 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2530 ioc->events[idx].eventContext = ioc->eventContext;
2532 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2533 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2534 (sc->device->channel << 8) | sc->device->id;
2536 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2538 ioc->eventContext++;
2539 if (hd->ioc->pcidev->vendor ==
2540 PCI_VENDOR_ID_IBM) {
2541 mptscsih_issue_sep_command(hd->ioc,
2542 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2543 vdev->vtarget->tflags |=
2544 MPT_TARGET_FLAGS_LED_ON;
2549 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2555 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2560 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2562 for (i = 0; i < hd->ioc->req_depth; i++) {
2563 if (hd->ScsiLookup[i] == sc) {
2571 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2573 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2576 unsigned long flags;
2579 dtmprintk(ioc, printk(KERN_DEBUG MYNAM
2580 ": IOC %s_reset routed to SCSI host driver!\n",
2581 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2582 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2584 /* If a FW reload request arrives after base installed but
2585 * before all scsi hosts have been attached, then an alt_ioc
2586 * may have a NULL sh pointer.
2588 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2591 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2593 if (reset_phase == MPT_IOC_SETUP_RESET) {
2594 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
2597 * 1. Set Hard Reset Pending Flag
2598 * All new commands go to doneQ
2600 hd->resetPending = 1;
2602 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2603 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
2605 /* 2. Flush running commands
2606 * Clean ScsiLookup (and associated memory)
2610 /* 2b. Reply to OS all known outstanding I/O commands.
2612 mptscsih_flush_running_cmds(hd);
2614 /* 2c. If there was an internal command that
2615 * has not completed, configuration or io request,
2616 * free these resources.
2619 del_timer(&hd->timer);
2620 mpt_free_msg_frame(ioc, hd->cmdPtr);
2623 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
2626 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
2628 /* Once a FW reload begins, all new OS commands are
2629 * redirected to the doneQ w/ a reset status.
2630 * Init all control structures.
2633 /* ScsiLookup initialization
2635 for (ii=0; ii < hd->ioc->req_depth; ii++)
2636 hd->ScsiLookup[ii] = NULL;
2638 /* 2. Chain Buffer initialization
2641 /* 4. Renegotiate to all devices, if SPI
2644 /* 5. Enable new commands to be posted
2646 spin_lock_irqsave(&ioc->FreeQlock, flags);
2648 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2649 hd->resetPending = 0;
2650 hd->tmState = TM_STATE_NONE;
2652 /* 6. If there was an internal command,
2653 * wake this process up.
2657 * Wake up the original calling thread
2659 hd->pLocal = &hd->localReply;
2660 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2661 hd->scandv_wait_done = 1;
2662 wake_up(&hd->scandv_waitq);
2666 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
2670 return 1; /* currently means nothing really */
2673 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2675 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2678 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2680 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2683 if (ioc->sh == NULL ||
2684 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2688 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2691 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2692 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2693 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2696 case MPI_EVENT_LOGOUT: /* 09 */
2700 case MPI_EVENT_RESCAN: /* 06 */
2704 * CHECKME! Don't think we need to do
2705 * anything for these, but...
2707 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2708 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2710 * CHECKME! Falling thru...
2714 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2717 case MPI_EVENT_NONE: /* 00 */
2718 case MPI_EVENT_LOG_DATA: /* 01 */
2719 case MPI_EVENT_STATE_CHANGE: /* 02 */
2720 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2722 dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event));
2726 return 1; /* currently means nothing really */
2729 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2731 * Bus Scan and Domain Validation functionality ...
2734 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2736 * mptscsih_scandv_complete - Scan and DV callback routine registered
2737 * to Fustion MPT (base) driver.
2739 * @ioc: Pointer to MPT_ADAPTER structure
2740 * @mf: Pointer to original MPT request frame
2741 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2743 * This routine is called from mpt.c::mpt_interrupt() at the completion
2744 * of any SCSI IO request.
2745 * This routine is registered with the Fusion MPT (base) driver at driver
2746 * load/init time via the mpt_register() API call.
2748 * Returns 1 indicating alloc'd request frame ptr should be freed.
2750 * Remark: Sets a completion code and (possibly) saves sense data
2751 * in the IOC member localReply structure.
2752 * Used ONLY for DV and other internal commands.
2755 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2758 SCSIIORequest_t *pReq;
2762 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2765 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2766 printk(MYIOC_s_ERR_FMT
2767 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2768 ioc->name, mf?"BAD":"NULL", (void *) mf);
2772 del_timer(&hd->timer);
2773 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2774 hd->ScsiLookup[req_idx] = NULL;
2775 pReq = (SCSIIORequest_t *) mf;
2777 if (mf != hd->cmdPtr) {
2778 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2779 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2783 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2784 hd->ioc->name, mf, mr, req_idx));
2786 hd->pLocal = &hd->localReply;
2787 hd->pLocal->scsiStatus = 0;
2789 /* If target struct exists, clear sense valid flag.
2792 completionCode = MPT_SCANDV_GOOD;
2794 SCSIIOReply_t *pReply;
2798 pReply = (SCSIIOReply_t *) mr;
2800 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2801 scsi_status = pReply->SCSIStatus;
2806 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2807 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2810 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2811 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2812 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2813 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2814 completionCode = MPT_SCANDV_DID_RESET;
2817 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2818 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2819 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2820 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2821 ConfigReply_t *pr = (ConfigReply_t *)mr;
2822 completionCode = MPT_SCANDV_GOOD;
2823 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2824 hd->pLocal->header.PageLength = pr->Header.PageLength;
2825 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2826 hd->pLocal->header.PageType = pr->Header.PageType;
2828 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2829 /* If the RAID Volume request is successful,
2830 * return GOOD, else indicate that
2831 * some type of error occurred.
2833 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2834 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2835 completionCode = MPT_SCANDV_GOOD;
2837 completionCode = MPT_SCANDV_SOME_ERROR;
2838 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2840 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2844 /* save sense data in global structure
2846 completionCode = MPT_SCANDV_SENSE;
2847 hd->pLocal->scsiStatus = scsi_status;
2848 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2849 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2851 sz = min_t(int, pReq->SenseBufferLength,
2852 SCSI_STD_SENSE_BYTES);
2853 memcpy(hd->pLocal->sense, sense_data, sz);
2855 ddvprintk(ioc, printk(KERN_DEBUG " Check Condition, sense ptr %p\n",
2857 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2858 if (pReq->CDB[0] == INQUIRY)
2859 completionCode = MPT_SCANDV_ISSUE_SENSE;
2861 completionCode = MPT_SCANDV_DID_RESET;
2863 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2864 completionCode = MPT_SCANDV_DID_RESET;
2865 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2866 completionCode = MPT_SCANDV_DID_RESET;
2868 completionCode = MPT_SCANDV_GOOD;
2869 hd->pLocal->scsiStatus = scsi_status;
2873 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2874 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2875 completionCode = MPT_SCANDV_DID_RESET;
2877 completionCode = MPT_SCANDV_SOME_ERROR;
2881 completionCode = MPT_SCANDV_SOME_ERROR;
2884 } /* switch(status) */
2886 } /* end of address reply case */
2888 hd->pLocal->completion = completionCode;
2890 /* MF and RF are freed in mpt_interrupt
2893 /* Free Chain buffers (will never chain) in scan or dv */
2894 //mptscsih_freeChainBuffers(ioc, req_idx);
2897 * Wake up the original calling thread
2899 hd->scandv_wait_done = 1;
2900 wake_up(&hd->scandv_waitq);
2905 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2906 /* mptscsih_timer_expired - Call back for timer process.
2907 * Used only for dv functionality.
2908 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2912 mptscsih_timer_expired(unsigned long data)
2914 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2916 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2919 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2921 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2922 /* Desire to issue a task management request here.
2923 * TM requests MUST be single threaded.
2924 * If old eh code and no TM current, issue request.
2925 * If new eh code, do nothing. Wait for OS cmd timeout
2929 /* Perform a FW reload */
2930 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2931 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2935 /* This should NEVER happen */
2936 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2939 /* No more processing.
2940 * TM call will generate an interrupt for SCSI TM Management.
2941 * The FW will reply to all outstanding commands, callback will finish cleanup.
2942 * Hard reset clean-up will free all resources.
2944 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name));
2950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2952 * mptscsih_do_cmd - Do internal command.
2953 * @hd: MPT_SCSI_HOST pointer
2954 * @io: INTERNAL_CMD pointer.
2956 * Issue the specified internally generated command and do command
2957 * specific cleanup. For bus scan / DV only.
2958 * NOTES: If command is Inquiry and status is good,
2959 * initialize a target structure, save the data
2961 * Remark: Single threaded access only.
2964 * < 0 if an illegal command or no resources
2968 * > 0 if command complete but some type of completion error.
2971 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2974 SCSIIORequest_t *pScsiReq;
2975 SCSIIORequest_t ReqCopy;
2976 int my_idx, ii, dir;
2980 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2983 in_isr = in_interrupt();
2985 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2991 /* Set command specific information
2996 dir = MPI_SCSIIO_CONTROL_READ;
3002 case TEST_UNIT_READY:
3004 dir = MPI_SCSIIO_CONTROL_READ;
3010 dir = MPI_SCSIIO_CONTROL_READ;
3012 CDB[4] = 1; /*Spin up the disk */
3020 dir = MPI_SCSIIO_CONTROL_READ;
3026 dir = MPI_SCSIIO_CONTROL_READ;
3028 if (io->flags & MPT_ICFLAG_ECHO) {
3034 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3037 CDB[6] = (io->size >> 16) & 0xFF;
3038 CDB[7] = (io->size >> 8) & 0xFF;
3039 CDB[8] = io->size & 0xFF;
3045 dir = MPI_SCSIIO_CONTROL_WRITE;
3047 if (io->flags & MPT_ICFLAG_ECHO) {
3052 CDB[6] = (io->size >> 16) & 0xFF;
3053 CDB[7] = (io->size >> 8) & 0xFF;
3054 CDB[8] = io->size & 0xFF;
3060 dir = MPI_SCSIIO_CONTROL_READ;
3067 dir = MPI_SCSIIO_CONTROL_READ;
3072 case SYNCHRONIZE_CACHE:
3074 dir = MPI_SCSIIO_CONTROL_READ;
3076 // CDB[1] = 0x02; /* set immediate bit */
3085 /* Get and Populate a free Frame
3087 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3088 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "No msg frames!\n",
3093 pScsiReq = (SCSIIORequest_t *) mf;
3095 /* Get the request index */
3096 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3097 ADD_INDEX_LOG(my_idx); /* for debug */
3099 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3100 pScsiReq->TargetID = io->physDiskNum;
3102 pScsiReq->ChainOffset = 0;
3103 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3105 pScsiReq->TargetID = io->id;
3106 pScsiReq->Bus = io->channel;
3107 pScsiReq->ChainOffset = 0;
3108 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3111 pScsiReq->CDBLength = cmdLen;
3112 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3114 pScsiReq->Reserved = 0;
3116 pScsiReq->MsgFlags = mpt_msg_flags();
3117 /* MsgContext set in mpt_get_msg_fram call */
3119 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3121 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3122 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3124 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3126 if (cmd == REQUEST_SENSE) {
3127 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3128 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
3129 hd->ioc->name, cmd));
3132 for (ii=0; ii < 16; ii++)
3133 pScsiReq->CDB[ii] = CDB[ii];
3135 pScsiReq->DataLength = cpu_to_le32(io->size);
3136 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3137 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3139 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3140 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3142 if (dir == MPI_SCSIIO_CONTROL_READ) {
3143 mpt_add_sge((char *) &pScsiReq->SGL,
3144 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3147 mpt_add_sge((char *) &pScsiReq->SGL,
3148 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3152 /* The ISR will free the request frame, but we need
3153 * the information to initialize the target. Duplicate.
3155 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3157 /* Issue this command after:
3160 * Wait until the reply has been received
3161 * ScsiScanDvCtx callback function will
3163 * set scandv_wait_done and call wake_up
3166 hd->timer.expires = jiffies + HZ*cmdTimeout;
3167 hd->scandv_wait_done = 0;
3169 /* Save cmd pointer, for resource free if timeout or
3174 add_timer(&hd->timer);
3175 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3176 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3179 rc = hd->pLocal->completion;
3180 hd->pLocal->skip = 0;
3182 /* Always set fatal error codes in some cases.
3184 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3186 else if (rc == MPT_SCANDV_SOME_ERROR)
3190 /* This should never happen. */
3191 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
3198 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3200 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3201 * @hd: Pointer to a SCSI HOST structure
3202 * @vdevice: virtual target device
3204 * Uses the ISR, but with special processing.
3205 * MUST be single-threaded.
3209 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3213 /* Ignore hidden raid components, this is handled when the command
3214 * is sent to the volume
3216 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3219 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3220 !vdevice->configured_lun)
3223 /* Following parameters will not change
3226 iocmd.cmd = SYNCHRONIZE_CACHE;
3228 iocmd.physDiskNum = -1;
3230 iocmd.data_dma = -1;
3232 iocmd.rsvd = iocmd.rsvd2 = 0;
3233 iocmd.channel = vdevice->vtarget->channel;
3234 iocmd.id = vdevice->vtarget->id;
3235 iocmd.lun = vdevice->lun;
3237 mptscsih_do_cmd(hd, &iocmd);
3241 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
3243 struct Scsi_Host *host = class_to_shost(cdev);
3244 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3245 MPT_ADAPTER *ioc = hd->ioc;
3247 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3248 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3249 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3250 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3251 ioc->facts.FWVersion.Word & 0x000000FF);
3253 static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
3256 mptscsih_version_bios_show(struct class_device *cdev, char *buf)
3258 struct Scsi_Host *host = class_to_shost(cdev);
3259 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3260 MPT_ADAPTER *ioc = hd->ioc;
3262 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3263 (ioc->biosVersion & 0xFF000000) >> 24,
3264 (ioc->biosVersion & 0x00FF0000) >> 16,
3265 (ioc->biosVersion & 0x0000FF00) >> 8,
3266 ioc->biosVersion & 0x000000FF);
3268 static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
3271 mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
3273 struct Scsi_Host *host = class_to_shost(cdev);
3274 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3275 MPT_ADAPTER *ioc = hd->ioc;
3277 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3279 static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
3282 mptscsih_version_product_show(struct class_device *cdev, char *buf)
3284 struct Scsi_Host *host = class_to_shost(cdev);
3285 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3286 MPT_ADAPTER *ioc = hd->ioc;
3288 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3290 static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
3291 mptscsih_version_product_show, NULL);
3294 mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
3296 struct Scsi_Host *host = class_to_shost(cdev);
3297 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3298 MPT_ADAPTER *ioc = hd->ioc;
3300 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3301 ioc->nvdata_version_persistent);
3303 static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
3304 mptscsih_version_nvdata_persistent_show, NULL);
3307 mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
3309 struct Scsi_Host *host = class_to_shost(cdev);
3310 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3311 MPT_ADAPTER *ioc = hd->ioc;
3313 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3315 static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
3316 mptscsih_version_nvdata_default_show, NULL);
3319 mptscsih_board_name_show(struct class_device *cdev, char *buf)
3321 struct Scsi_Host *host = class_to_shost(cdev);
3322 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3323 MPT_ADAPTER *ioc = hd->ioc;
3325 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3327 static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
3330 mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
3332 struct Scsi_Host *host = class_to_shost(cdev);
3333 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3334 MPT_ADAPTER *ioc = hd->ioc;
3336 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3338 static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
3339 mptscsih_board_assembly_show, NULL);
3342 mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
3344 struct Scsi_Host *host = class_to_shost(cdev);
3345 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3346 MPT_ADAPTER *ioc = hd->ioc;
3348 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3350 static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
3351 mptscsih_board_tracer_show, NULL);
3354 mptscsih_io_delay_show(struct class_device *cdev, char *buf)
3356 struct Scsi_Host *host = class_to_shost(cdev);
3357 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3358 MPT_ADAPTER *ioc = hd->ioc;
3360 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3362 static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
3363 mptscsih_io_delay_show, NULL);
3366 mptscsih_device_delay_show(struct class_device *cdev, char *buf)
3368 struct Scsi_Host *host = class_to_shost(cdev);
3369 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3370 MPT_ADAPTER *ioc = hd->ioc;
3372 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3374 static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
3375 mptscsih_device_delay_show, NULL);
3378 mptscsih_debug_level_show(struct class_device *cdev, char *buf)
3380 struct Scsi_Host *host = class_to_shost(cdev);
3381 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3382 MPT_ADAPTER *ioc = hd->ioc;
3384 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3387 mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
3390 struct Scsi_Host *host = class_to_shost(cdev);
3391 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3392 MPT_ADAPTER *ioc = hd->ioc;
3395 if (sscanf(buf, "%x", &val) != 1)
3398 ioc->debug_level = val;
3399 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3400 ioc->name, ioc->debug_level);
3403 static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3404 mptscsih_debug_level_show, mptscsih_debug_level_store);
3406 struct class_device_attribute *mptscsih_host_attrs[] = {
3407 &class_device_attr_version_fw,
3408 &class_device_attr_version_bios,
3409 &class_device_attr_version_mpi,
3410 &class_device_attr_version_product,
3411 &class_device_attr_version_nvdata_persistent,
3412 &class_device_attr_version_nvdata_default,
3413 &class_device_attr_board_name,
3414 &class_device_attr_board_assembly,
3415 &class_device_attr_board_tracer,
3416 &class_device_attr_io_delay,
3417 &class_device_attr_device_delay,
3418 &class_device_attr_debug_level,
3421 EXPORT_SYMBOL(mptscsih_host_attrs);
3423 EXPORT_SYMBOL(mptscsih_remove);
3424 EXPORT_SYMBOL(mptscsih_shutdown);
3426 EXPORT_SYMBOL(mptscsih_suspend);
3427 EXPORT_SYMBOL(mptscsih_resume);
3429 EXPORT_SYMBOL(mptscsih_proc_info);
3430 EXPORT_SYMBOL(mptscsih_info);
3431 EXPORT_SYMBOL(mptscsih_qcmd);
3432 EXPORT_SYMBOL(mptscsih_slave_destroy);
3433 EXPORT_SYMBOL(mptscsih_slave_configure);
3434 EXPORT_SYMBOL(mptscsih_abort);
3435 EXPORT_SYMBOL(mptscsih_dev_reset);
3436 EXPORT_SYMBOL(mptscsih_bus_reset);
3437 EXPORT_SYMBOL(mptscsih_host_reset);
3438 EXPORT_SYMBOL(mptscsih_bios_param);
3439 EXPORT_SYMBOL(mptscsih_io_done);
3440 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3441 EXPORT_SYMBOL(mptscsih_scandv_complete);
3442 EXPORT_SYMBOL(mptscsih_event_process);
3443 EXPORT_SYMBOL(mptscsih_ioc_reset);
3444 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3445 EXPORT_SYMBOL(mptscsih_timer_expired);
3446 EXPORT_SYMBOL(mptscsih_TMHandler);
3448 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/