[ARM] Add fallocate syscall entry
[linux-2.6/openmoko-kernel/knife-kernel.git] / drivers / message / fusion / mptscsih.c
blob5431529741ad28380442e3b5618d799b988bdecd
1 /*
2 * linux/drivers/message/fusion/mptscsih.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2007 LSI Logic Corporation
7 * (mailto:DL-MPTFusionLinux@lsi.com)
9 */
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.
21 NO WARRANTY
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>
65 #include "mptbase.h"
66 #include "mptscsih.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 *);
106 #ifdef CONFIG_PM
107 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
108 int mptscsih_resume(struct pci_dev *pdev);
109 #endif
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
121 * FreeQ.
123 static inline void
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);
135 } else {
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
151 * FreeQ.
153 static inline void
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);
168 } else {
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
186 static inline int
187 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
189 MPT_FRAME_HDR *chainBuf;
190 unsigned long flags;
191 int rc;
192 int chain_idx;
194 dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n",
195 ioc->name));
196 spin_lock_irqsave(&ioc->FreeQlock, flags);
197 if (!list_empty(&ioc->FreeChainQ)) {
198 int offset;
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;
205 rc = SUCCESS;
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));
208 } else {
209 rc = FAILED;
210 chain_idx = MPT_HOST_NO_CHAIN;
211 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n",
212 ioc->name));
214 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
216 *retIndex = chain_idx;
217 return rc;
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
228 * Returns ...
230 static int
231 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
232 SCSIIORequest_t *pReq, int req_idx)
234 char *psge;
235 char *chainSge;
236 struct scatterlist *sg;
237 int frm_sz;
238 int sges_left, sg_done;
239 int chain_idx = MPT_HOST_NO_CHAIN;
240 int sgeOffset;
241 int numSgeSlots, numSgeThisFrame;
242 u32 sgflags, sgdir, thisxfer = 0;
243 int chain_dma_off = 0;
244 int newIndex;
245 int ii;
246 dma_addr_t v2;
247 u32 RequestNB;
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;
252 } else {
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);
263 if (sges_left < 0)
264 return FAILED;
266 /* Handle the SG case.
268 sg = scsi_sglist(SCpnt);
269 sg_done = 0;
270 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
271 chainSge = NULL;
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)
279 nextSGEset:
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);
291 if (thisxfer == 0) {
292 sg ++; /* Get next SG element from the OS */
293 sg_done++;
294 continue;
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));
303 sg_done++;
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);
321 sg++;
322 psge += (sizeof(u32) + sizeof(dma_addr_t));
324 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
325 sg_done++;
327 if (chainSge) {
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);
334 } else {
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;
344 } else {
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
352 * Also
353 * Loop until done.
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
363 * set properly).
365 if (sg_done) {
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);
372 if (chainSge) {
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);
382 } else {
383 /* The original MF buffer requires a chain buffer -
384 * set the offset.
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));
403 return FAILED;
406 /* Update the tracking arrays.
407 * If chainSge == NULL, update ReqToChain, else ChainToChain
409 if (chainSge) {
410 ioc->ChainToChain[chain_idx] = newIndex;
411 } else {
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)",
423 psge, req_idx));
425 /* Start the SGE for the next buffer
427 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
428 sgeOffset = 0;
429 sg_done = 0;
431 dsgprintk(ioc, printk(KERN_DEBUG " Chain buff @ %p (index 0x%x)\n",
432 psge, chain_idx));
434 /* Start the SGE for the next buffer
437 goto nextSGEset;
440 return SUCCESS;
441 } /* mptscsih_AddSGE() */
443 static void
444 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
445 U32 SlotStatus)
447 MPT_FRAME_HDR *mf;
448 SEPRequest_t *SEPMsg;
450 if (ioc->bus_type != SAS)
451 return;
453 /* Not supported for hidden raid components
455 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
456 return;
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__));
461 return;
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.
487 static void
488 mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply)
490 char *desc = NULL;
491 char *desc1 = NULL;
492 u16 ioc_status;
493 u8 skey, asc, ascq;
495 ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
497 switch (ioc_status) {
499 case MPI_IOCSTATUS_SUCCESS:
500 desc = "success";
501 break;
502 case MPI_IOCSTATUS_SCSI_INVALID_BUS:
503 desc = "invalid bus";
504 break;
505 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
506 desc = "invalid target_id";
507 break;
508 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
509 desc = "device not there";
510 break;
511 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
512 desc = "data overrun";
513 break;
514 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
515 desc = "data underrun";
516 break;
517 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:
518 desc = "I/O data error";
519 break;
520 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:
521 desc = "protocol error";
522 break;
523 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
524 desc = "task terminated";
525 break;
526 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
527 desc = "residual mismatch";
528 break;
529 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
530 desc = "task management failed";
531 break;
532 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
533 desc = "IOC terminated";
534 break;
535 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
536 desc = "ext terminated";
537 break;
538 default:
539 desc = "";
540 break;
543 switch (pScsiReply->SCSIStatus)
546 case MPI_SCSI_STATUS_SUCCESS:
547 desc1 = "success";
548 break;
549 case MPI_SCSI_STATUS_CHECK_CONDITION:
550 desc1 = "check condition";
551 break;
552 case MPI_SCSI_STATUS_CONDITION_MET:
553 desc1 = "condition met";
554 break;
555 case MPI_SCSI_STATUS_BUSY:
556 desc1 = "busy";
557 break;
558 case MPI_SCSI_STATUS_INTERMEDIATE:
559 desc1 = "intermediate";
560 break;
561 case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:
562 desc1 = "intermediate condmet";
563 break;
564 case MPI_SCSI_STATUS_RESERVATION_CONFLICT:
565 desc1 = "reservation conflict";
566 break;
567 case MPI_SCSI_STATUS_COMMAND_TERMINATED:
568 desc1 = "command terminated";
569 break;
570 case MPI_SCSI_STATUS_TASK_SET_FULL:
571 desc1 = "task set full";
572 break;
573 case MPI_SCSI_STATUS_ACA_ACTIVE:
574 desc1 = "aca active";
575 break;
576 case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:
577 desc1 = "fcpext device logged out";
578 break;
579 case MPI_SCSI_STATUS_FCPEXT_NO_LINK:
580 desc1 = "fcpext no link";
581 break;
582 case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:
583 desc1 = "fcpext unassigned";
584 break;
585 default:
586 desc1 = "";
587 break;
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",
601 desc, ioc_status,
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",
612 skey, asc, ascq);
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));
623 #endif
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;
644 MPT_SCSI_HOST *hd;
645 SCSIIORequest_t *pScsiReq;
646 SCSIIOReply_t *pScsiReply;
647 u16 req_idx, req_idx_MR;
648 VirtDevice *vdev;
649 VirtTarget *vtarget;
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",
659 ioc->name);
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]);
664 return 0;
667 sc = hd->ScsiLookup[req_idx];
668 hd->ScsiLookup[req_idx] = NULL;
669 if (sc == 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",
678 ioc->name);
680 mptscsih_freeChainBuffers(ioc, req_idx);
681 return 1;
684 if ((unsigned char *)mf != sc->host_scribble) {
685 mptscsih_freeChainBuffers(ioc, req_idx);
686 return 1;
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));
698 }else{
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 */
707 } else {
708 u32 xfer_cnt;
709 u16 status;
710 u8 scsi_state, scsi_status;
711 u32 log_info;
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
724 * to success
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));
748 switch(status) {
749 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
750 /* CHECKME!
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;
756 break;
758 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
759 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
760 sc->result = DID_BAD_TARGET << 16;
761 break;
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 */
768 else
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;
775 if (!vdev)
776 break;
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;
783 break;
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);
792 break;
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;
805 break;
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;
819 break;
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));
830 break;
832 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
834 * Do upfront check for valid SenseData and give it
835 * precedence!
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
842 } else {
843 if (xfer_cnt < sc->underflow) {
844 if (scsi_status == SAM_STAT_BUSY)
845 sc->result = SAM_STAT_BUSY;
846 else
847 sc->result = DID_SOFT_ERROR << 16;
849 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
850 /* What to do?
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",
862 sc->underflow));
863 dreplyprintk(ioc, printk(KERN_DEBUG " ActBytesXferd=%02xh\n", xfer_cnt));
865 /* Report Queue Full
867 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
868 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
870 break;
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)
894 * What to do?
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);
913 /* Add handling of:
914 * Reservation Conflict, Busy,
915 * Command Terminated, CHECK
917 break;
919 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
920 sc->result = DID_SOFT_ERROR << 16;
921 break;
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 */
932 default:
934 * What to do?
936 sc->result = DID_SOFT_ERROR << 16;
937 break;
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);
944 #endif
946 } /* end of address reply case */
948 /* Unmap the DMA buffers, if any. */
949 scsi_dma_unmap(sc);
951 sc->scsi_done(sc); /* Issue the command callback */
953 /* Free Chain buffers */
954 mptscsih_freeChainBuffers(ioc, req_idx);
955 return 1;
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
964 * Returns: None.
966 * Must be called while new I/Os are being queued.
968 static void
969 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
971 MPT_ADAPTER *ioc = hd->ioc;
972 struct scsi_cmnd *SCpnt;
973 MPT_FRAME_HDR *mf;
974 int ii;
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) {
981 /* Command found.
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",
990 mf, SCpnt));
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)
999 continue;
1001 /* Set status, free OS resources (SG DMA buffers)
1002 * Do OS callback
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 */
1013 return;
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
1026 * Returns: None.
1028 * Called from slave_destroy.
1030 static void
1031 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1033 SCSIIORequest_t *mf = NULL;
1034 int ii;
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);
1046 if (mf == NULL)
1047 continue;
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)
1054 continue;
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))
1060 continue;
1062 /* Cleanup
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)
1068 continue;
1069 scsi_dma_unmap(sc);
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);
1075 sc->scsi_done(sc);
1078 return;
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.
1095 static void
1096 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1098 long time = jiffies;
1099 MPT_SCSI_HOST *hd;
1101 if (sc->device == NULL)
1102 return;
1103 if (sc->device->host == NULL)
1104 return;
1105 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1106 return;
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
1122 void
1123 mptscsih_remove(struct pci_dev *pdev)
1125 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1126 struct Scsi_Host *host = ioc->sh;
1127 MPT_SCSI_HOST *hd;
1128 int sz1;
1130 if(!host) {
1131 mpt_detach(pdev);
1132 return;
1135 scsi_remove_host(host);
1137 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1138 return;
1140 mptscsih_shutdown(pdev);
1142 sz1=0;
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
1158 hd->ioc->sh = NULL;
1160 scsi_host_put(host);
1162 mpt_detach(pdev);
1166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1168 * mptscsih_shutdown - reboot notifier
1171 void
1172 mptscsih_shutdown(struct pci_dev *pdev)
1174 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1175 struct Scsi_Host *host = ioc->sh;
1176 MPT_SCSI_HOST *hd;
1178 if(!host)
1179 return;
1181 hd = (MPT_SCSI_HOST *)host->hostdata;
1185 #ifdef CONFIG_PM
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);
1211 #endif
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.
1222 const char *
1223 mptscsih_info(struct Scsi_Host *SChost)
1225 MPT_SCSI_HOST *h;
1226 int size = 0;
1228 h = (MPT_SCSI_HOST *)SChost->hostdata;
1230 if (h) {
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;
1243 struct info_str {
1244 char *buffer;
1245 int length;
1246 int offset;
1247 int pos;
1250 static void
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) {
1257 info->pos += len;
1258 return;
1261 if (info->pos < info->offset) {
1262 data += (info->offset - info->pos);
1263 len -= (info->offset - info->pos);
1266 if (len > 0) {
1267 memcpy(info->buffer + info->pos, data, len);
1268 info->pos += len;
1272 static int
1273 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1275 va_list args;
1276 char buf[81];
1277 int len;
1279 va_start(args, fmt);
1280 len = vsprintf(buf, fmt, args);
1281 va_end(args);
1283 mptscsih_copy_mem_info(info, buf, len);
1284 return len;
1287 static int
1288 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1290 struct info_str info;
1292 info.buffer = pbuf;
1293 info.length = len;
1294 info.offset = offset;
1295 info.pos = 0;
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;
1324 int size = 0;
1326 if (func) {
1328 * write is not supported
1330 } else {
1331 if (start)
1332 *start = buffer;
1334 size = mptscsih_host_info(ioc, buffer, offset, length);
1337 return size;
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 *))
1358 MPT_SCSI_HOST *hd;
1359 MPT_FRAME_HDR *mf;
1360 SCSIIORequest_t *pScsiReq;
1361 VirtDevice *vdev = SCpnt->device->hostdata;
1362 int lun;
1363 u32 datalen;
1364 u32 scsictl;
1365 u32 scsidir;
1366 u32 cmd_len;
1367 int my_idx;
1368 int ii;
1369 MPT_ADAPTER *ioc;
1371 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1372 ioc = hd->ioc;
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",
1381 ioc->name, SCpnt));
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",
1390 ioc->name));
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) */
1410 } else {
1411 datalen = 0;
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.
1418 if (vdev
1419 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1420 && (SCpnt->device->tagged_supported)) {
1421 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1422 } else {
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;
1433 else
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;
1452 /* DataLength */
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.
1462 if (datalen == 0) {
1463 /* Add a NULL SGE */
1464 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1465 (dma_addr_t) -1);
1466 } else {
1467 /* Add a 32 or 64 bit SGE */
1468 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1469 goto fail;
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)
1479 return 0;
1481 fail:
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.
1496 * No return.
1498 static void
1499 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1501 MPT_FRAME_HDR *chain;
1502 unsigned long flags;
1503 int chain_idx;
1504 int next;
1506 /* Get the first chain index and reset
1507 * tracker state.
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
1518 * tracker
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));
1532 /* handle next */
1533 chain_idx = next;
1535 return;
1538 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1540 * Reset Handling
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
1560 * will be active.
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)
1567 MPT_ADAPTER *ioc;
1568 int rc = -1;
1569 u32 ioc_raw_state;
1570 unsigned long flags;
1572 ioc = hd->ioc;
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);
1580 return FAILED;
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
1586 * to the caller.
1587 * The call to mptscsih_tm_pending_wait() will set the pending flag
1588 * if we are
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));
1596 return FAILED;
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,
1601 hd->tmPending));
1602 return FAILED;
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));
1607 return FAILED;
1609 } else {
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 "
1624 "FAILED!!\n"));
1625 return FAILED;
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);
1633 return FAILED;
1636 /* Isse the Task Mgmt request.
1638 if (hd->hard_resets < -1)
1639 hd->hard_resets++;
1641 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1642 ctx2abort, timeout);
1643 if (rc)
1644 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1645 ioc->name);
1646 else
1647 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issue of TaskMgmt Successful!\n",
1648 ioc->name));
1650 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1651 "TMHandler rc = %d!\n", ioc->name, rc));
1653 return 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.
1676 static int
1677 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1679 MPT_FRAME_HDR *mf;
1680 SCSITaskMgmt_t *pScsiTm;
1681 int ii;
1682 int retval;
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",
1688 hd->ioc->name));
1689 return FAILED;
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 ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1721 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
1722 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!"
1723 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1724 hd->ioc, mf, retval));
1725 goto fail_out;
1728 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1729 dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1730 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1731 hd->ioc, mf));
1732 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n",
1733 hd->ioc->name));
1734 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1735 dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n",
1736 hd->ioc->name, retval));
1737 goto fail_out;
1741 * Handle success case, see if theres a non-zero ioc_status.
1743 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1744 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1745 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1746 retval = 0;
1747 else
1748 retval = FAILED;
1750 return retval;
1752 fail_out:
1755 * Free task managment mf, and corresponding tm flags
1757 mpt_free_msg_frame(hd->ioc, mf);
1758 hd->tmPending = 0;
1759 hd->tmState = TM_STATE_NONE;
1760 return FAILED;
1763 static int
1764 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1766 switch (ioc->bus_type) {
1767 case FC:
1768 return 40;
1769 case SAS:
1770 return 10;
1771 case SPI:
1772 default:
1773 return 2;
1777 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1779 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1780 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1782 * (linux scsi_host_template.eh_abort_handler routine)
1784 * Returns SUCCESS or FAILED.
1787 mptscsih_abort(struct scsi_cmnd * SCpnt)
1789 MPT_SCSI_HOST *hd;
1790 MPT_FRAME_HDR *mf;
1791 u32 ctx2abort;
1792 int scpnt_idx;
1793 int retval;
1794 VirtDevice *vdevice;
1795 ulong sn = SCpnt->serial_number;
1796 MPT_ADAPTER *ioc;
1798 /* If we can't locate our host adapter structure, return FAILED status.
1800 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1801 SCpnt->result = DID_RESET << 16;
1802 SCpnt->scsi_done(SCpnt);
1803 printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate "
1804 "host! (sc=%p)\n", SCpnt);
1805 return FAILED;
1808 ioc = hd->ioc;
1809 printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1810 ioc->name, SCpnt);
1811 scsi_print_command(SCpnt);
1813 vdevice = SCpnt->device->hostdata;
1814 if (!vdevice || !vdevice->vtarget) {
1815 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: device has been "
1816 "deleted (sc=%p)\n", ioc->name, SCpnt));
1817 SCpnt->result = DID_NO_CONNECT << 16;
1818 SCpnt->scsi_done(SCpnt);
1819 retval = 0;
1820 goto out;
1823 /* Task aborts are not supported for hidden raid components.
1825 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1826 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid "
1827 "component (sc=%p)\n", ioc->name, SCpnt));
1828 SCpnt->result = DID_RESET << 16;
1829 retval = FAILED;
1830 goto out;
1833 /* Find this command
1835 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1836 /* Cmd not found in ScsiLookup.
1837 * Do OS callback.
1839 SCpnt->result = DID_RESET << 16;
1840 dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: "
1841 "Command not in the active list! (sc=%p)\n", ioc->name,
1842 SCpnt));
1843 retval = 0;
1844 goto out;
1847 if (hd->resetPending) {
1848 retval = FAILED;
1849 goto out;
1852 if (hd->timeouts < -1)
1853 hd->timeouts++;
1855 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1856 * (the IO to be ABORT'd)
1858 * NOTE: Since we do not byteswap MsgContext, we do not
1859 * swap it here either. It is an opaque cookie to
1860 * the controller, so it does not matter. -DaveM
1862 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1863 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1865 hd->abortSCpnt = SCpnt;
1867 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1868 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun,
1869 ctx2abort, mptscsih_get_tm_timeout(ioc));
1871 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1872 SCpnt->serial_number == sn)
1873 retval = FAILED;
1875 out:
1876 printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n",
1877 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1879 if (retval == 0)
1880 return SUCCESS;
1881 else
1882 return FAILED;
1885 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1887 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1888 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1890 * (linux scsi_host_template.eh_dev_reset_handler routine)
1892 * Returns SUCCESS or FAILED.
1895 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1897 MPT_SCSI_HOST *hd;
1898 int retval;
1899 VirtDevice *vdevice;
1900 MPT_ADAPTER *ioc;
1902 /* If we can't locate our host adapter structure, return FAILED status.
1904 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1905 printk(KERN_DEBUG MYNAM ": mptscsih_dev_reset: Can't "
1906 "locate host! (sc=%p)\n", SCpnt);
1907 return FAILED;
1910 ioc = hd->ioc;
1911 printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1912 ioc->name, SCpnt);
1913 scsi_print_command(SCpnt);
1915 if (hd->resetPending) {
1916 retval = FAILED;
1917 goto out;
1920 vdevice = SCpnt->device->hostdata;
1921 if (!vdevice || !vdevice->vtarget) {
1922 retval = 0;
1923 goto out;
1926 /* Target reset to hidden raid component is not supported
1928 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1929 retval = FAILED;
1930 goto out;
1933 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1934 vdevice->vtarget->channel, vdevice->vtarget->id, 0, 0,
1935 mptscsih_get_tm_timeout(ioc));
1937 out:
1938 printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1939 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1941 if (retval == 0)
1942 return SUCCESS;
1943 else
1944 return FAILED;
1948 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1950 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1951 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1953 * (linux scsi_host_template.eh_bus_reset_handler routine)
1955 * Returns SUCCESS or FAILED.
1958 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1960 MPT_SCSI_HOST *hd;
1961 int retval;
1962 VirtDevice *vdev;
1963 MPT_ADAPTER *ioc;
1965 /* If we can't locate our host adapter structure, return FAILED status.
1967 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1968 printk(KERN_DEBUG MYNAM ": mptscsih_bus_reset: Can't "
1969 "locate host! (sc=%p)\n", SCpnt );
1970 return FAILED;
1973 ioc = hd->ioc;
1974 printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1975 ioc->name, SCpnt);
1976 scsi_print_command(SCpnt);
1978 if (hd->timeouts < -1)
1979 hd->timeouts++;
1981 vdev = SCpnt->device->hostdata;
1982 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1983 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc));
1985 printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1986 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1988 if (retval == 0)
1989 return SUCCESS;
1990 else
1991 return FAILED;
1994 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1996 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1997 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1999 * (linux scsi_host_template.eh_host_reset_handler routine)
2001 * Returns SUCCESS or FAILED.
2004 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
2006 MPT_SCSI_HOST * hd;
2007 int retval;
2008 MPT_ADAPTER *ioc;
2010 /* If we can't locate the host to reset, then we failed. */
2011 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2012 printk( KERN_DEBUG MYNAM ": mptscsih_host_reset: Can't "
2013 "locate host! (sc=%p)\n", SCpnt);
2014 return FAILED;
2017 ioc = hd->ioc;
2018 printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
2019 ioc->name, SCpnt);
2021 /* If our attempts to reset the host failed, then return a failed
2022 * status. The host will be taken off line by the SCSI mid-layer.
2024 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
2025 retval = FAILED;
2026 } else {
2027 /* Make sure TM pending is cleared and TM state is set to
2028 * NONE.
2030 retval = 0;
2031 hd->tmPending = 0;
2032 hd->tmState = TM_STATE_NONE;
2035 printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
2036 ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
2038 return retval;
2041 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2043 * mptscsih_tm_pending_wait - wait for pending task management request to complete
2044 * @hd: Pointer to MPT host structure.
2046 * Returns {SUCCESS,FAILED}.
2048 static int
2049 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
2051 unsigned long flags;
2052 int loop_count = 4 * 10; /* Wait 10 seconds */
2053 int status = FAILED;
2055 do {
2056 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2057 if (hd->tmState == TM_STATE_NONE) {
2058 hd->tmState = TM_STATE_IN_PROGRESS;
2059 hd->tmPending = 1;
2060 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2061 status = SUCCESS;
2062 break;
2064 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2065 msleep(250);
2066 } while (--loop_count);
2068 return status;
2071 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2073 * mptscsih_tm_wait_for_completion - wait for completion of TM task
2074 * @hd: Pointer to MPT host structure.
2075 * @timeout: timeout value
2077 * Returns {SUCCESS,FAILED}.
2079 static int
2080 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2082 unsigned long flags;
2083 int loop_count = 4 * timeout;
2084 int status = FAILED;
2086 do {
2087 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2088 if(hd->tmPending == 0) {
2089 status = SUCCESS;
2090 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2091 break;
2093 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2094 msleep(250);
2095 } while (--loop_count);
2097 return status;
2100 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2101 static void
2102 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2104 char *desc;
2106 switch (response_code) {
2107 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2108 desc = "The task completed.";
2109 break;
2110 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2111 desc = "The IOC received an invalid frame status.";
2112 break;
2113 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2114 desc = "The task type is not supported.";
2115 break;
2116 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2117 desc = "The requested task failed.";
2118 break;
2119 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2120 desc = "The task completed successfully.";
2121 break;
2122 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2123 desc = "The LUN request is invalid.";
2124 break;
2125 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2126 desc = "The task is in the IOC queue and has not been sent to target.";
2127 break;
2128 default:
2129 desc = "unknown";
2130 break;
2132 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2133 ioc->name, response_code, desc);
2136 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2138 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2139 * @ioc: Pointer to MPT_ADAPTER structure
2140 * @mf: Pointer to SCSI task mgmt request frame
2141 * @mr: Pointer to SCSI task mgmt reply frame
2143 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2144 * of any SCSI task management request.
2145 * This routine is registered with the MPT (base) driver at driver
2146 * load/init time via the mpt_register() API call.
2148 * Returns 1 indicating alloc'd request frame ptr should be freed.
2151 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2153 SCSITaskMgmtReply_t *pScsiTmReply;
2154 SCSITaskMgmt_t *pScsiTmReq;
2155 MPT_SCSI_HOST *hd;
2156 unsigned long flags;
2157 u16 iocstatus;
2158 u8 tmType;
2159 u32 termination_count;
2161 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2162 ioc->name, mf, mr));
2163 if (!ioc->sh) {
2164 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2165 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2166 return 1;
2169 if (mr == NULL) {
2170 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT
2171 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2172 return 1;
2175 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2176 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2177 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2178 tmType = pScsiTmReq->TaskType;
2179 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2180 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2182 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2183 pScsiTmReply->ResponseCode)
2184 mptscsih_taskmgmt_response_code(ioc,
2185 pScsiTmReply->ResponseCode);
2186 DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
2188 #ifdef CONFIG_FUSION_LOGGING
2189 if ((ioc->debug_level & MPT_DEBUG_REPLY) ||
2190 (ioc->debug_level & MPT_DEBUG_TM ))
2191 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2192 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2193 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2194 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2195 le16_to_cpu(pScsiTmReply->IOCStatus),
2196 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2197 le32_to_cpu(pScsiTmReply->TerminationCount));
2198 #endif
2199 if (!iocstatus) {
2200 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT " TaskMgmt SUCCESS\n", ioc->name));
2201 hd->abortSCpnt = NULL;
2202 goto out;
2205 /* Error? (anything non-zero?) */
2207 /* clear flags and continue.
2209 switch (tmType) {
2211 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2212 if (termination_count == 1)
2213 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2214 hd->abortSCpnt = NULL;
2215 break;
2217 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2219 /* If an internal command is present
2220 * or the TM failed - reload the FW.
2221 * FC FW may respond FAILED to an ABORT
2223 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2224 hd->cmdPtr)
2225 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2226 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2227 break;
2229 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2230 default:
2231 break;
2234 out:
2235 spin_lock_irqsave(&ioc->FreeQlock, flags);
2236 hd->tmPending = 0;
2237 hd->tmState = TM_STATE_NONE;
2238 hd->tm_iocstatus = iocstatus;
2239 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2241 return 1;
2244 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2246 * This is anyones guess quite frankly.
2249 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2250 sector_t capacity, int geom[])
2252 int heads;
2253 int sectors;
2254 sector_t cylinders;
2255 ulong dummy;
2257 heads = 64;
2258 sectors = 32;
2260 dummy = heads * sectors;
2261 cylinders = capacity;
2262 sector_div(cylinders,dummy);
2265 * Handle extended translation size for logical drives
2266 * > 1Gb
2268 if ((ulong)capacity >= 0x200000) {
2269 heads = 255;
2270 sectors = 63;
2271 dummy = heads * sectors;
2272 cylinders = capacity;
2273 sector_div(cylinders,dummy);
2276 /* return result */
2277 geom[0] = heads;
2278 geom[1] = sectors;
2279 geom[2] = cylinders;
2281 return 0;
2284 /* Search IOC page 3 to determine if this is hidden physical disk
2288 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2290 struct inactive_raid_component_info *component_info;
2291 int i;
2292 int rc = 0;
2294 if (!ioc->raid_data.pIocPg3)
2295 goto out;
2296 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2297 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2298 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2299 rc = 1;
2300 goto out;
2305 * Check inactive list for matching phys disks
2307 if (list_empty(&ioc->raid_data.inactive_list))
2308 goto out;
2310 down(&ioc->raid_data.inactive_list_mutex);
2311 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2312 list) {
2313 if ((component_info->d.PhysDiskID == id) &&
2314 (component_info->d.PhysDiskBus == channel))
2315 rc = 1;
2317 up(&ioc->raid_data.inactive_list_mutex);
2319 out:
2320 return rc;
2322 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2325 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2327 struct inactive_raid_component_info *component_info;
2328 int i;
2329 int rc = -ENXIO;
2331 if (!ioc->raid_data.pIocPg3)
2332 goto out;
2333 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2334 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2335 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2336 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2337 goto out;
2342 * Check inactive list for matching phys disks
2344 if (list_empty(&ioc->raid_data.inactive_list))
2345 goto out;
2347 down(&ioc->raid_data.inactive_list_mutex);
2348 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2349 list) {
2350 if ((component_info->d.PhysDiskID == id) &&
2351 (component_info->d.PhysDiskBus == channel))
2352 rc = component_info->d.PhysDiskNum;
2354 up(&ioc->raid_data.inactive_list_mutex);
2356 out:
2357 return rc;
2359 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2362 * OS entry point to allow for host driver to free allocated memory
2363 * Called if no device present or device being unloaded
2365 void
2366 mptscsih_slave_destroy(struct scsi_device *sdev)
2368 struct Scsi_Host *host = sdev->host;
2369 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2370 VirtTarget *vtarget;
2371 VirtDevice *vdevice;
2372 struct scsi_target *starget;
2374 starget = scsi_target(sdev);
2375 vtarget = starget->hostdata;
2376 vdevice = sdev->hostdata;
2378 mptscsih_search_running_cmds(hd, vdevice);
2379 vtarget->num_luns--;
2380 mptscsih_synchronize_cache(hd, vdevice);
2381 kfree(vdevice);
2382 sdev->hostdata = NULL;
2385 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2387 * mptscsih_change_queue_depth - This function will set a devices queue depth
2388 * @sdev: per scsi_device pointer
2389 * @qdepth: requested queue depth
2391 * Adding support for new 'change_queue_depth' api.
2394 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2396 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2397 VirtTarget *vtarget;
2398 struct scsi_target *starget;
2399 int max_depth;
2400 int tagged;
2402 starget = scsi_target(sdev);
2403 vtarget = starget->hostdata;
2405 if (hd->ioc->bus_type == SPI) {
2406 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2407 max_depth = 1;
2408 else if (sdev->type == TYPE_DISK &&
2409 vtarget->minSyncFactor <= MPT_ULTRA160)
2410 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2411 else
2412 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2413 } else
2414 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2416 if (qdepth > max_depth)
2417 qdepth = max_depth;
2418 if (qdepth == 1)
2419 tagged = 0;
2420 else
2421 tagged = MSG_SIMPLE_TAG;
2423 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2424 return sdev->queue_depth;
2428 * OS entry point to adjust the queue_depths on a per-device basis.
2429 * Called once per device the bus scan. Use it to force the queue_depth
2430 * member to 1 if a device does not support Q tags.
2431 * Return non-zero if fails.
2434 mptscsih_slave_configure(struct scsi_device *sdev)
2436 struct Scsi_Host *sh = sdev->host;
2437 VirtTarget *vtarget;
2438 VirtDevice *vdevice;
2439 struct scsi_target *starget;
2440 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2442 starget = scsi_target(sdev);
2443 vtarget = starget->hostdata;
2444 vdevice = sdev->hostdata;
2446 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2447 "device @ %p, channel=%d, id=%d, lun=%d\n",
2448 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2449 if (hd->ioc->bus_type == SPI)
2450 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2451 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2452 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2453 sdev->ppr, sdev->inquiry_len));
2455 if (sdev->id > sh->max_id) {
2456 /* error case, should never happen */
2457 scsi_adjust_queue_depth(sdev, 0, 1);
2458 goto slave_configure_exit;
2461 vdevice->configured_lun = 1;
2462 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2464 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2465 "Queue depth=%d, tflags=%x\n",
2466 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2468 if (hd->ioc->bus_type == SPI)
2469 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2470 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2471 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2472 vtarget->minSyncFactor));
2474 slave_configure_exit:
2476 dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT
2477 "tagged %d, simple %d, ordered %d\n",
2478 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2479 sdev->ordered_tags));
2481 return 0;
2484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2486 * Private routines...
2489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2490 /* Utility function to copy sense data from the scsi_cmnd buffer
2491 * to the FC and SCSI target structures.
2494 static void
2495 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2497 VirtDevice *vdev;
2498 SCSIIORequest_t *pReq;
2499 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2501 /* Get target structure
2503 pReq = (SCSIIORequest_t *) mf;
2504 vdev = sc->device->hostdata;
2506 if (sense_count) {
2507 u8 *sense_data;
2508 int req_index;
2510 /* Copy the sense received into the scsi command block. */
2511 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2512 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2513 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2515 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2517 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2518 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2519 int idx;
2520 MPT_ADAPTER *ioc = hd->ioc;
2522 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2523 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2524 ioc->events[idx].eventContext = ioc->eventContext;
2526 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2527 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2528 (sc->device->channel << 8) | sc->device->id;
2530 ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2532 ioc->eventContext++;
2533 if (hd->ioc->pcidev->vendor ==
2534 PCI_VENDOR_ID_IBM) {
2535 mptscsih_issue_sep_command(hd->ioc,
2536 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2537 vdev->vtarget->tflags |=
2538 MPT_TARGET_FLAGS_LED_ON;
2542 } else {
2543 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2544 hd->ioc->name));
2548 static int
2549 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2551 MPT_SCSI_HOST *hd;
2552 int i;
2554 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2556 for (i = 0; i < hd->ioc->req_depth; i++) {
2557 if (hd->ScsiLookup[i] == sc) {
2558 return i;
2562 return -1;
2565 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2567 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2569 MPT_SCSI_HOST *hd;
2570 unsigned long flags;
2571 int ii;
2573 dtmprintk(ioc, printk(KERN_DEBUG MYNAM
2574 ": IOC %s_reset routed to SCSI host driver!\n",
2575 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2576 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2578 /* If a FW reload request arrives after base installed but
2579 * before all scsi hosts have been attached, then an alt_ioc
2580 * may have a NULL sh pointer.
2582 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2583 return 0;
2584 else
2585 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2587 if (reset_phase == MPT_IOC_SETUP_RESET) {
2588 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name));
2590 /* Clean Up:
2591 * 1. Set Hard Reset Pending Flag
2592 * All new commands go to doneQ
2594 hd->resetPending = 1;
2596 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2597 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name));
2599 /* 2. Flush running commands
2600 * Clean ScsiLookup (and associated memory)
2601 * AND clean mytaskQ
2604 /* 2b. Reply to OS all known outstanding I/O commands.
2606 mptscsih_flush_running_cmds(hd);
2608 /* 2c. If there was an internal command that
2609 * has not completed, configuration or io request,
2610 * free these resources.
2612 if (hd->cmdPtr) {
2613 del_timer(&hd->timer);
2614 mpt_free_msg_frame(ioc, hd->cmdPtr);
2617 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name));
2619 } else {
2620 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name));
2622 /* Once a FW reload begins, all new OS commands are
2623 * redirected to the doneQ w/ a reset status.
2624 * Init all control structures.
2627 /* ScsiLookup initialization
2629 for (ii=0; ii < hd->ioc->req_depth; ii++)
2630 hd->ScsiLookup[ii] = NULL;
2632 /* 2. Chain Buffer initialization
2635 /* 4. Renegotiate to all devices, if SPI
2638 /* 5. Enable new commands to be posted
2640 spin_lock_irqsave(&ioc->FreeQlock, flags);
2641 hd->tmPending = 0;
2642 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2643 hd->resetPending = 0;
2644 hd->tmState = TM_STATE_NONE;
2646 /* 6. If there was an internal command,
2647 * wake this process up.
2649 if (hd->cmdPtr) {
2651 * Wake up the original calling thread
2653 hd->pLocal = &hd->localReply;
2654 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2655 hd->scandv_wait_done = 1;
2656 wake_up(&hd->scandv_waitq);
2657 hd->cmdPtr = NULL;
2660 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name));
2664 return 1; /* currently means nothing really */
2667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2669 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2671 MPT_SCSI_HOST *hd;
2672 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2674 devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2675 ioc->name, event));
2677 if (ioc->sh == NULL ||
2678 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2679 return 1;
2681 switch (event) {
2682 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2683 /* FIXME! */
2684 break;
2685 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2686 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2687 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2688 hd->soft_resets++;
2689 break;
2690 case MPI_EVENT_LOGOUT: /* 09 */
2691 /* FIXME! */
2692 break;
2694 case MPI_EVENT_RESCAN: /* 06 */
2695 break;
2698 * CHECKME! Don't think we need to do
2699 * anything for these, but...
2701 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2702 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2704 * CHECKME! Falling thru...
2706 break;
2708 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2709 break;
2711 case MPI_EVENT_NONE: /* 00 */
2712 case MPI_EVENT_LOG_DATA: /* 01 */
2713 case MPI_EVENT_STATE_CHANGE: /* 02 */
2714 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2715 default:
2716 dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event));
2717 break;
2720 return 1; /* currently means nothing really */
2723 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2725 * Bus Scan and Domain Validation functionality ...
2728 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2730 * mptscsih_scandv_complete - Scan and DV callback routine registered
2731 * to Fustion MPT (base) driver.
2733 * @ioc: Pointer to MPT_ADAPTER structure
2734 * @mf: Pointer to original MPT request frame
2735 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2737 * This routine is called from mpt.c::mpt_interrupt() at the completion
2738 * of any SCSI IO request.
2739 * This routine is registered with the Fusion MPT (base) driver at driver
2740 * load/init time via the mpt_register() API call.
2742 * Returns 1 indicating alloc'd request frame ptr should be freed.
2744 * Remark: Sets a completion code and (possibly) saves sense data
2745 * in the IOC member localReply structure.
2746 * Used ONLY for DV and other internal commands.
2749 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2751 MPT_SCSI_HOST *hd;
2752 SCSIIORequest_t *pReq;
2753 int completionCode;
2754 u16 req_idx;
2756 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2758 if ((mf == NULL) ||
2759 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2760 printk(MYIOC_s_ERR_FMT
2761 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2762 ioc->name, mf?"BAD":"NULL", (void *) mf);
2763 goto wakeup;
2766 del_timer(&hd->timer);
2767 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2768 hd->ScsiLookup[req_idx] = NULL;
2769 pReq = (SCSIIORequest_t *) mf;
2771 if (mf != hd->cmdPtr) {
2772 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2773 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2775 hd->cmdPtr = NULL;
2777 ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2778 hd->ioc->name, mf, mr, req_idx));
2780 hd->pLocal = &hd->localReply;
2781 hd->pLocal->scsiStatus = 0;
2783 /* If target struct exists, clear sense valid flag.
2785 if (mr == NULL) {
2786 completionCode = MPT_SCANDV_GOOD;
2787 } else {
2788 SCSIIOReply_t *pReply;
2789 u16 status;
2790 u8 scsi_status;
2792 pReply = (SCSIIOReply_t *) mr;
2794 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2795 scsi_status = pReply->SCSIStatus;
2798 switch(status) {
2800 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2801 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2802 break;
2804 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2805 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2806 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2807 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2808 completionCode = MPT_SCANDV_DID_RESET;
2809 break;
2811 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2812 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2813 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2814 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2815 ConfigReply_t *pr = (ConfigReply_t *)mr;
2816 completionCode = MPT_SCANDV_GOOD;
2817 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2818 hd->pLocal->header.PageLength = pr->Header.PageLength;
2819 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2820 hd->pLocal->header.PageType = pr->Header.PageType;
2822 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2823 /* If the RAID Volume request is successful,
2824 * return GOOD, else indicate that
2825 * some type of error occurred.
2827 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2828 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2829 completionCode = MPT_SCANDV_GOOD;
2830 else
2831 completionCode = MPT_SCANDV_SOME_ERROR;
2832 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2834 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2835 u8 *sense_data;
2836 int sz;
2838 /* save sense data in global structure
2840 completionCode = MPT_SCANDV_SENSE;
2841 hd->pLocal->scsiStatus = scsi_status;
2842 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2843 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2845 sz = min_t(int, pReq->SenseBufferLength,
2846 SCSI_STD_SENSE_BYTES);
2847 memcpy(hd->pLocal->sense, sense_data, sz);
2849 ddvprintk(ioc, printk(KERN_DEBUG " Check Condition, sense ptr %p\n",
2850 sense_data));
2851 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2852 if (pReq->CDB[0] == INQUIRY)
2853 completionCode = MPT_SCANDV_ISSUE_SENSE;
2854 else
2855 completionCode = MPT_SCANDV_DID_RESET;
2857 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2858 completionCode = MPT_SCANDV_DID_RESET;
2859 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2860 completionCode = MPT_SCANDV_DID_RESET;
2861 else {
2862 completionCode = MPT_SCANDV_GOOD;
2863 hd->pLocal->scsiStatus = scsi_status;
2865 break;
2867 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2868 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2869 completionCode = MPT_SCANDV_DID_RESET;
2870 else
2871 completionCode = MPT_SCANDV_SOME_ERROR;
2872 break;
2874 default:
2875 completionCode = MPT_SCANDV_SOME_ERROR;
2876 break;
2878 } /* switch(status) */
2880 } /* end of address reply case */
2882 hd->pLocal->completion = completionCode;
2884 /* MF and RF are freed in mpt_interrupt
2886 wakeup:
2887 /* Free Chain buffers (will never chain) in scan or dv */
2888 //mptscsih_freeChainBuffers(ioc, req_idx);
2891 * Wake up the original calling thread
2893 hd->scandv_wait_done = 1;
2894 wake_up(&hd->scandv_waitq);
2896 return 1;
2899 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2900 /* mptscsih_timer_expired - Call back for timer process.
2901 * Used only for dv functionality.
2902 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2905 void
2906 mptscsih_timer_expired(unsigned long data)
2908 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2910 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2912 if (hd->cmdPtr) {
2913 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2915 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2916 /* Desire to issue a task management request here.
2917 * TM requests MUST be single threaded.
2918 * If old eh code and no TM current, issue request.
2919 * If new eh code, do nothing. Wait for OS cmd timeout
2920 * for bus reset.
2922 } else {
2923 /* Perform a FW reload */
2924 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2925 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2928 } else {
2929 /* This should NEVER happen */
2930 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2933 /* No more processing.
2934 * TM call will generate an interrupt for SCSI TM Management.
2935 * The FW will reply to all outstanding commands, callback will finish cleanup.
2936 * Hard reset clean-up will free all resources.
2938 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name));
2940 return;
2944 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2946 * mptscsih_do_cmd - Do internal command.
2947 * @hd: MPT_SCSI_HOST pointer
2948 * @io: INTERNAL_CMD pointer.
2950 * Issue the specified internally generated command and do command
2951 * specific cleanup. For bus scan / DV only.
2952 * NOTES: If command is Inquiry and status is good,
2953 * initialize a target structure, save the data
2955 * Remark: Single threaded access only.
2957 * Return:
2958 * < 0 if an illegal command or no resources
2960 * 0 if good
2962 * > 0 if command complete but some type of completion error.
2964 static int
2965 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2967 MPT_FRAME_HDR *mf;
2968 SCSIIORequest_t *pScsiReq;
2969 SCSIIORequest_t ReqCopy;
2970 int my_idx, ii, dir;
2971 int rc, cmdTimeout;
2972 int in_isr;
2973 char cmdLen;
2974 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2975 char cmd = io->cmd;
2977 in_isr = in_interrupt();
2978 if (in_isr) {
2979 dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2980 hd->ioc->name));
2981 return -EPERM;
2985 /* Set command specific information
2987 switch (cmd) {
2988 case INQUIRY:
2989 cmdLen = 6;
2990 dir = MPI_SCSIIO_CONTROL_READ;
2991 CDB[0] = cmd;
2992 CDB[4] = io->size;
2993 cmdTimeout = 10;
2994 break;
2996 case TEST_UNIT_READY:
2997 cmdLen = 6;
2998 dir = MPI_SCSIIO_CONTROL_READ;
2999 cmdTimeout = 10;
3000 break;
3002 case START_STOP:
3003 cmdLen = 6;
3004 dir = MPI_SCSIIO_CONTROL_READ;
3005 CDB[0] = cmd;
3006 CDB[4] = 1; /*Spin up the disk */
3007 cmdTimeout = 15;
3008 break;
3010 case REQUEST_SENSE:
3011 cmdLen = 6;
3012 CDB[0] = cmd;
3013 CDB[4] = io->size;
3014 dir = MPI_SCSIIO_CONTROL_READ;
3015 cmdTimeout = 10;
3016 break;
3018 case READ_BUFFER:
3019 cmdLen = 10;
3020 dir = MPI_SCSIIO_CONTROL_READ;
3021 CDB[0] = cmd;
3022 if (io->flags & MPT_ICFLAG_ECHO) {
3023 CDB[1] = 0x0A;
3024 } else {
3025 CDB[1] = 0x02;
3028 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3029 CDB[1] |= 0x01;
3031 CDB[6] = (io->size >> 16) & 0xFF;
3032 CDB[7] = (io->size >> 8) & 0xFF;
3033 CDB[8] = io->size & 0xFF;
3034 cmdTimeout = 10;
3035 break;
3037 case WRITE_BUFFER:
3038 cmdLen = 10;
3039 dir = MPI_SCSIIO_CONTROL_WRITE;
3040 CDB[0] = cmd;
3041 if (io->flags & MPT_ICFLAG_ECHO) {
3042 CDB[1] = 0x0A;
3043 } else {
3044 CDB[1] = 0x02;
3046 CDB[6] = (io->size >> 16) & 0xFF;
3047 CDB[7] = (io->size >> 8) & 0xFF;
3048 CDB[8] = io->size & 0xFF;
3049 cmdTimeout = 10;
3050 break;
3052 case RESERVE:
3053 cmdLen = 6;
3054 dir = MPI_SCSIIO_CONTROL_READ;
3055 CDB[0] = cmd;
3056 cmdTimeout = 10;
3057 break;
3059 case RELEASE:
3060 cmdLen = 6;
3061 dir = MPI_SCSIIO_CONTROL_READ;
3062 CDB[0] = cmd;
3063 cmdTimeout = 10;
3064 break;
3066 case SYNCHRONIZE_CACHE:
3067 cmdLen = 10;
3068 dir = MPI_SCSIIO_CONTROL_READ;
3069 CDB[0] = cmd;
3070 // CDB[1] = 0x02; /* set immediate bit */
3071 cmdTimeout = 10;
3072 break;
3074 default:
3075 /* Error Case */
3076 return -EFAULT;
3079 /* Get and Populate a free Frame
3081 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3082 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "No msg frames!\n",
3083 hd->ioc->name));
3084 return -EBUSY;
3087 pScsiReq = (SCSIIORequest_t *) mf;
3089 /* Get the request index */
3090 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3091 ADD_INDEX_LOG(my_idx); /* for debug */
3093 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3094 pScsiReq->TargetID = io->physDiskNum;
3095 pScsiReq->Bus = 0;
3096 pScsiReq->ChainOffset = 0;
3097 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3098 } else {
3099 pScsiReq->TargetID = io->id;
3100 pScsiReq->Bus = io->channel;
3101 pScsiReq->ChainOffset = 0;
3102 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3105 pScsiReq->CDBLength = cmdLen;
3106 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3108 pScsiReq->Reserved = 0;
3110 pScsiReq->MsgFlags = mpt_msg_flags();
3111 /* MsgContext set in mpt_get_msg_fram call */
3113 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3115 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3116 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3117 else
3118 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3120 if (cmd == REQUEST_SENSE) {
3121 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3122 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n",
3123 hd->ioc->name, cmd));
3126 for (ii=0; ii < 16; ii++)
3127 pScsiReq->CDB[ii] = CDB[ii];
3129 pScsiReq->DataLength = cpu_to_le32(io->size);
3130 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3131 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3133 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3134 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3136 if (dir == MPI_SCSIIO_CONTROL_READ) {
3137 mpt_add_sge((char *) &pScsiReq->SGL,
3138 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3139 io->data_dma);
3140 } else {
3141 mpt_add_sge((char *) &pScsiReq->SGL,
3142 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3143 io->data_dma);
3146 /* The ISR will free the request frame, but we need
3147 * the information to initialize the target. Duplicate.
3149 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3151 /* Issue this command after:
3152 * finish init
3153 * add timer
3154 * Wait until the reply has been received
3155 * ScsiScanDvCtx callback function will
3156 * set hd->pLocal;
3157 * set scandv_wait_done and call wake_up
3159 hd->pLocal = NULL;
3160 hd->timer.expires = jiffies + HZ*cmdTimeout;
3161 hd->scandv_wait_done = 0;
3163 /* Save cmd pointer, for resource free if timeout or
3164 * FW reload occurs
3166 hd->cmdPtr = mf;
3168 add_timer(&hd->timer);
3169 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3170 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3172 if (hd->pLocal) {
3173 rc = hd->pLocal->completion;
3174 hd->pLocal->skip = 0;
3176 /* Always set fatal error codes in some cases.
3178 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3179 rc = -ENXIO;
3180 else if (rc == MPT_SCANDV_SOME_ERROR)
3181 rc = -rc;
3182 } else {
3183 rc = -EFAULT;
3184 /* This should never happen. */
3185 ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n",
3186 hd->ioc->name));
3189 return rc;
3192 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3194 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3195 * @hd: Pointer to a SCSI HOST structure
3196 * @vdevice: virtual target device
3198 * Uses the ISR, but with special processing.
3199 * MUST be single-threaded.
3202 static void
3203 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3205 INTERNAL_CMD iocmd;
3207 /* Ignore hidden raid components, this is handled when the command
3208 * is sent to the volume
3210 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3211 return;
3213 if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3214 !vdevice->configured_lun)
3215 return;
3217 /* Following parameters will not change
3218 * in this routine.
3220 iocmd.cmd = SYNCHRONIZE_CACHE;
3221 iocmd.flags = 0;
3222 iocmd.physDiskNum = -1;
3223 iocmd.data = NULL;
3224 iocmd.data_dma = -1;
3225 iocmd.size = 0;
3226 iocmd.rsvd = iocmd.rsvd2 = 0;
3227 iocmd.channel = vdevice->vtarget->channel;
3228 iocmd.id = vdevice->vtarget->id;
3229 iocmd.lun = vdevice->lun;
3231 mptscsih_do_cmd(hd, &iocmd);
3234 static ssize_t
3235 mptscsih_version_fw_show(struct class_device *cdev, char *buf)
3237 struct Scsi_Host *host = class_to_shost(cdev);
3238 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3239 MPT_ADAPTER *ioc = hd->ioc;
3241 return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3242 (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3243 (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3244 (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3245 ioc->facts.FWVersion.Word & 0x000000FF);
3247 static CLASS_DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
3249 static ssize_t
3250 mptscsih_version_bios_show(struct class_device *cdev, char *buf)
3252 struct Scsi_Host *host = class_to_shost(cdev);
3253 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3254 MPT_ADAPTER *ioc = hd->ioc;
3256 return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3257 (ioc->biosVersion & 0xFF000000) >> 24,
3258 (ioc->biosVersion & 0x00FF0000) >> 16,
3259 (ioc->biosVersion & 0x0000FF00) >> 8,
3260 ioc->biosVersion & 0x000000FF);
3262 static CLASS_DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
3264 static ssize_t
3265 mptscsih_version_mpi_show(struct class_device *cdev, char *buf)
3267 struct Scsi_Host *host = class_to_shost(cdev);
3268 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3269 MPT_ADAPTER *ioc = hd->ioc;
3271 return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3273 static CLASS_DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
3275 static ssize_t
3276 mptscsih_version_product_show(struct class_device *cdev, char *buf)
3278 struct Scsi_Host *host = class_to_shost(cdev);
3279 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3280 MPT_ADAPTER *ioc = hd->ioc;
3282 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3284 static CLASS_DEVICE_ATTR(version_product, S_IRUGO,
3285 mptscsih_version_product_show, NULL);
3287 static ssize_t
3288 mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf)
3290 struct Scsi_Host *host = class_to_shost(cdev);
3291 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3292 MPT_ADAPTER *ioc = hd->ioc;
3294 return snprintf(buf, PAGE_SIZE, "%02xh\n",
3295 ioc->nvdata_version_persistent);
3297 static CLASS_DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
3298 mptscsih_version_nvdata_persistent_show, NULL);
3300 static ssize_t
3301 mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf)
3303 struct Scsi_Host *host = class_to_shost(cdev);
3304 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3305 MPT_ADAPTER *ioc = hd->ioc;
3307 return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3309 static CLASS_DEVICE_ATTR(version_nvdata_default, S_IRUGO,
3310 mptscsih_version_nvdata_default_show, NULL);
3312 static ssize_t
3313 mptscsih_board_name_show(struct class_device *cdev, char *buf)
3315 struct Scsi_Host *host = class_to_shost(cdev);
3316 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3317 MPT_ADAPTER *ioc = hd->ioc;
3319 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3321 static CLASS_DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
3323 static ssize_t
3324 mptscsih_board_assembly_show(struct class_device *cdev, char *buf)
3326 struct Scsi_Host *host = class_to_shost(cdev);
3327 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3328 MPT_ADAPTER *ioc = hd->ioc;
3330 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3332 static CLASS_DEVICE_ATTR(board_assembly, S_IRUGO,
3333 mptscsih_board_assembly_show, NULL);
3335 static ssize_t
3336 mptscsih_board_tracer_show(struct class_device *cdev, char *buf)
3338 struct Scsi_Host *host = class_to_shost(cdev);
3339 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3340 MPT_ADAPTER *ioc = hd->ioc;
3342 return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3344 static CLASS_DEVICE_ATTR(board_tracer, S_IRUGO,
3345 mptscsih_board_tracer_show, NULL);
3347 static ssize_t
3348 mptscsih_io_delay_show(struct class_device *cdev, char *buf)
3350 struct Scsi_Host *host = class_to_shost(cdev);
3351 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3352 MPT_ADAPTER *ioc = hd->ioc;
3354 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3356 static CLASS_DEVICE_ATTR(io_delay, S_IRUGO,
3357 mptscsih_io_delay_show, NULL);
3359 static ssize_t
3360 mptscsih_device_delay_show(struct class_device *cdev, char *buf)
3362 struct Scsi_Host *host = class_to_shost(cdev);
3363 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3364 MPT_ADAPTER *ioc = hd->ioc;
3366 return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3368 static CLASS_DEVICE_ATTR(device_delay, S_IRUGO,
3369 mptscsih_device_delay_show, NULL);
3371 static ssize_t
3372 mptscsih_debug_level_show(struct class_device *cdev, char *buf)
3374 struct Scsi_Host *host = class_to_shost(cdev);
3375 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
3376 MPT_ADAPTER *ioc = hd->ioc;
3378 return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3380 static ssize_t
3381 mptscsih_debug_level_store(struct class_device *cdev, const char *buf,
3382 size_t count)
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;
3387 int val = 0;
3389 if (sscanf(buf, "%x", &val) != 1)
3390 return -EINVAL;
3392 ioc->debug_level = val;
3393 printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3394 ioc->name, ioc->debug_level);
3395 return strlen(buf);
3397 static CLASS_DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3398 mptscsih_debug_level_show, mptscsih_debug_level_store);
3400 struct class_device_attribute *mptscsih_host_attrs[] = {
3401 &class_device_attr_version_fw,
3402 &class_device_attr_version_bios,
3403 &class_device_attr_version_mpi,
3404 &class_device_attr_version_product,
3405 &class_device_attr_version_nvdata_persistent,
3406 &class_device_attr_version_nvdata_default,
3407 &class_device_attr_board_name,
3408 &class_device_attr_board_assembly,
3409 &class_device_attr_board_tracer,
3410 &class_device_attr_io_delay,
3411 &class_device_attr_device_delay,
3412 &class_device_attr_debug_level,
3413 NULL,
3415 EXPORT_SYMBOL(mptscsih_host_attrs);
3417 EXPORT_SYMBOL(mptscsih_remove);
3418 EXPORT_SYMBOL(mptscsih_shutdown);
3419 #ifdef CONFIG_PM
3420 EXPORT_SYMBOL(mptscsih_suspend);
3421 EXPORT_SYMBOL(mptscsih_resume);
3422 #endif
3423 EXPORT_SYMBOL(mptscsih_proc_info);
3424 EXPORT_SYMBOL(mptscsih_info);
3425 EXPORT_SYMBOL(mptscsih_qcmd);
3426 EXPORT_SYMBOL(mptscsih_slave_destroy);
3427 EXPORT_SYMBOL(mptscsih_slave_configure);
3428 EXPORT_SYMBOL(mptscsih_abort);
3429 EXPORT_SYMBOL(mptscsih_dev_reset);
3430 EXPORT_SYMBOL(mptscsih_bus_reset);
3431 EXPORT_SYMBOL(mptscsih_host_reset);
3432 EXPORT_SYMBOL(mptscsih_bios_param);
3433 EXPORT_SYMBOL(mptscsih_io_done);
3434 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3435 EXPORT_SYMBOL(mptscsih_scandv_complete);
3436 EXPORT_SYMBOL(mptscsih_event_process);
3437 EXPORT_SYMBOL(mptscsih_ioc_reset);
3438 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3439 EXPORT_SYMBOL(mptscsih_timer_expired);
3440 EXPORT_SYMBOL(mptscsih_TMHandler);
3442 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/