[SCSI] fusion: convert to use the data buffer accessors
[linux-2.6.git] / drivers / message / fusion / mptscsih.c
blob561074a04b03ce83b381c68201986b78763e46ea
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:mpt_linux_developer@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_compat.h" /* linux-2.6 tweaks */
48 #include <linux/module.h>
49 #include <linux/kernel.h>
50 #include <linux/init.h>
51 #include <linux/errno.h>
52 #include <linux/kdev_t.h>
53 #include <linux/blkdev.h>
54 #include <linux/delay.h> /* for mdelay */
55 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
56 #include <linux/reboot.h> /* notifier code */
57 #include <linux/workqueue.h>
59 #include <scsi/scsi.h>
60 #include <scsi/scsi_cmnd.h>
61 #include <scsi/scsi_device.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include <scsi/scsi_dbg.h>
66 #include "mptbase.h"
67 #include "mptscsih.h"
68 #include "lsi/mpi_log_sas.h"
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME "Fusion MPT SCSI Host driver"
72 #define my_VERSION MPT_LINUX_VERSION_COMMON
73 #define MYNAM "mptscsih"
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 MODULE_VERSION(my_VERSION);
80 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
82 * Other private/forward protos...
84 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
85 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
86 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
88 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
89 SCSIIORequest_t *pReq, int req_idx);
90 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
91 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
92 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
93 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
94 static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
96 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
98 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
99 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
101 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
102 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
103 static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
105 void mptscsih_remove(struct pci_dev *);
106 void mptscsih_shutdown(struct pci_dev *);
107 #ifdef CONFIG_PM
108 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
109 int mptscsih_resume(struct pci_dev *pdev);
110 #endif
112 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
116 * mptscsih_add_sge - Place a simple SGE at address pAddr.
117 * @pAddr: virtual address for SGE
118 * @flagslength: SGE flags and data transfer length
119 * @dma_addr: Physical address
121 * This routine places a MPT request frame back on the MPT adapter's
122 * FreeQ.
124 static inline void
125 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
127 if (sizeof(dma_addr_t) == sizeof(u64)) {
128 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
129 u32 tmp = dma_addr & 0xFFFFFFFF;
131 pSge->FlagsLength = cpu_to_le32(flagslength);
132 pSge->Address.Low = cpu_to_le32(tmp);
133 tmp = (u32) ((u64)dma_addr >> 32);
134 pSge->Address.High = cpu_to_le32(tmp);
136 } else {
137 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
138 pSge->FlagsLength = cpu_to_le32(flagslength);
139 pSge->Address = cpu_to_le32(dma_addr);
141 } /* mptscsih_add_sge() */
143 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
145 * mptscsih_add_chain - Place a chain SGE at address pAddr.
146 * @pAddr: virtual address for SGE
147 * @next: nextChainOffset value (u32's)
148 * @length: length of next SGL segment
149 * @dma_addr: Physical address
151 * This routine places a MPT request frame back on the MPT adapter's
152 * FreeQ.
154 static inline void
155 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
157 if (sizeof(dma_addr_t) == sizeof(u64)) {
158 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
159 u32 tmp = dma_addr & 0xFFFFFFFF;
161 pChain->Length = cpu_to_le16(length);
162 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
164 pChain->NextChainOffset = next;
166 pChain->Address.Low = cpu_to_le32(tmp);
167 tmp = (u32) ((u64)dma_addr >> 32);
168 pChain->Address.High = cpu_to_le32(tmp);
169 } else {
170 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
171 pChain->Length = cpu_to_le16(length);
172 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
173 pChain->NextChainOffset = next;
174 pChain->Address = cpu_to_le32(dma_addr);
176 } /* mptscsih_add_chain() */
178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
180 * mptscsih_getFreeChainBuffer - Function to get a free chain
181 * from the MPT_SCSI_HOST FreeChainQ.
182 * @ioc: Pointer to MPT_ADAPTER structure
183 * @req_idx: Index of the SCSI IO request frame. (output)
185 * return SUCCESS or FAILED
187 static inline int
188 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
190 MPT_FRAME_HDR *chainBuf;
191 unsigned long flags;
192 int rc;
193 int chain_idx;
195 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
196 ioc->name));
197 spin_lock_irqsave(&ioc->FreeQlock, flags);
198 if (!list_empty(&ioc->FreeChainQ)) {
199 int offset;
201 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
202 u.frame.linkage.list);
203 list_del(&chainBuf->u.frame.linkage.list);
204 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
205 chain_idx = offset / ioc->req_sz;
206 rc = SUCCESS;
207 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
208 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
209 } else {
210 rc = FAILED;
211 chain_idx = MPT_HOST_NO_CHAIN;
212 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
213 ioc->name));
215 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
217 *retIndex = chain_idx;
218 return rc;
219 } /* mptscsih_getFreeChainBuffer() */
221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
223 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
224 * SCSIIORequest_t Message Frame.
225 * @ioc: Pointer to MPT_ADAPTER structure
226 * @SCpnt: Pointer to scsi_cmnd structure
227 * @pReq: Pointer to SCSIIORequest_t structure
229 * Returns ...
231 static int
232 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
233 SCSIIORequest_t *pReq, int req_idx)
235 char *psge;
236 char *chainSge;
237 struct scatterlist *sg;
238 int frm_sz;
239 int sges_left, sg_done;
240 int chain_idx = MPT_HOST_NO_CHAIN;
241 int sgeOffset;
242 int numSgeSlots, numSgeThisFrame;
243 u32 sgflags, sgdir, thisxfer = 0;
244 int chain_dma_off = 0;
245 int newIndex;
246 int ii;
247 dma_addr_t v2;
248 u32 RequestNB;
250 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
251 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
252 sgdir = MPT_TRANSFER_HOST_TO_IOC;
253 } else {
254 sgdir = MPT_TRANSFER_IOC_TO_HOST;
257 psge = (char *) &pReq->SGL;
258 frm_sz = ioc->req_sz;
260 /* Map the data portion, if any.
261 * sges_left = 0 if no data transfer.
263 sges_left = scsi_dma_map(SCpnt);
264 if (sges_left < 0)
265 return FAILED;
267 /* Handle the SG case.
269 sg = scsi_sglist(SCpnt);
270 sg_done = 0;
271 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
272 chainSge = NULL;
274 /* Prior to entering this loop - the following must be set
275 * current MF: sgeOffset (bytes)
276 * chainSge (Null if original MF is not a chain buffer)
277 * sg_done (num SGE done for this MF)
280 nextSGEset:
281 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
282 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
284 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
286 /* Get first (num - 1) SG elements
287 * Skip any SG entries with a length of 0
288 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
290 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
291 thisxfer = sg_dma_len(sg);
292 if (thisxfer == 0) {
293 sg ++; /* Get next SG element from the OS */
294 sg_done++;
295 continue;
298 v2 = sg_dma_address(sg);
299 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
301 sg++; /* Get next SG element from the OS */
302 psge += (sizeof(u32) + sizeof(dma_addr_t));
303 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
304 sg_done++;
307 if (numSgeThisFrame == sges_left) {
308 /* Add last element, end of buffer and end of list flags.
310 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
311 MPT_SGE_FLAGS_END_OF_BUFFER |
312 MPT_SGE_FLAGS_END_OF_LIST;
314 /* Add last SGE and set termination flags.
315 * Note: Last SGE may have a length of 0 - which should be ok.
317 thisxfer = sg_dma_len(sg);
319 v2 = sg_dma_address(sg);
320 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
322 sg++;
323 psge += (sizeof(u32) + sizeof(dma_addr_t));
325 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
326 sg_done++;
328 if (chainSge) {
329 /* The current buffer is a chain buffer,
330 * but there is not another one.
331 * Update the chain element
332 * Offset and Length fields.
334 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
335 } else {
336 /* The current buffer is the original MF
337 * and there is no Chain buffer.
339 pReq->ChainOffset = 0;
340 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
341 dsgprintk((MYIOC_s_INFO_FMT
342 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
343 ioc->RequestNB[req_idx] = RequestNB;
345 } else {
346 /* At least one chain buffer is needed.
347 * Complete the first MF
348 * - last SGE element, set the LastElement bit
349 * - set ChainOffset (words) for orig MF
350 * (OR finish previous MF chain buffer)
351 * - update MFStructPtr ChainIndex
352 * - Populate chain element
353 * Also
354 * Loop until done.
357 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
358 ioc->name, sg_done));
360 /* Set LAST_ELEMENT flag for last non-chain element
361 * in the buffer. Since psge points at the NEXT
362 * SGE element, go back one SGE element, update the flags
363 * and reset the pointer. (Note: sgflags & thisxfer are already
364 * set properly).
366 if (sg_done) {
367 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
368 sgflags = le32_to_cpu(*ptmp);
369 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
370 *ptmp = cpu_to_le32(sgflags);
373 if (chainSge) {
374 /* The current buffer is a chain buffer.
375 * chainSge points to the previous Chain Element.
376 * Update its chain element Offset and Length (must
377 * include chain element size) fields.
378 * Old chain element is now complete.
380 u8 nextChain = (u8) (sgeOffset >> 2);
381 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
382 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
383 } else {
384 /* The original MF buffer requires a chain buffer -
385 * set the offset.
386 * Last element in this MF is a chain element.
388 pReq->ChainOffset = (u8) (sgeOffset >> 2);
389 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
390 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
391 ioc->RequestNB[req_idx] = RequestNB;
394 sges_left -= sg_done;
397 /* NOTE: psge points to the beginning of the chain element
398 * in current buffer. Get a chain buffer.
400 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
401 dfailprintk((MYIOC_s_INFO_FMT
402 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
403 ioc->name, pReq->CDB[0], SCpnt));
404 return FAILED;
407 /* Update the tracking arrays.
408 * If chainSge == NULL, update ReqToChain, else ChainToChain
410 if (chainSge) {
411 ioc->ChainToChain[chain_idx] = newIndex;
412 } else {
413 ioc->ReqToChain[req_idx] = newIndex;
415 chain_idx = newIndex;
416 chain_dma_off = ioc->req_sz * chain_idx;
418 /* Populate the chainSGE for the current buffer.
419 * - Set chain buffer pointer to psge and fill
420 * out the Address and Flags fields.
422 chainSge = (char *) psge;
423 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
424 psge, req_idx));
426 /* Start the SGE for the next buffer
428 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
429 sgeOffset = 0;
430 sg_done = 0;
432 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
433 psge, chain_idx));
435 /* Start the SGE for the next buffer
438 goto nextSGEset;
441 return SUCCESS;
442 } /* mptscsih_AddSGE() */
444 static void
445 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
446 U32 SlotStatus)
448 MPT_FRAME_HDR *mf;
449 SEPRequest_t *SEPMsg;
451 if (ioc->bus_type == FC)
452 return;
454 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
455 dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
456 ioc->name,__FUNCTION__));
457 return;
460 SEPMsg = (SEPRequest_t *)mf;
461 SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
462 SEPMsg->Bus = vtarget->channel;
463 SEPMsg->TargetID = vtarget->id;
464 SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
465 SEPMsg->SlotStatus = SlotStatus;
466 devtverboseprintk((MYIOC_s_WARN_FMT
467 "Sending SEP cmd=%x channel=%d id=%d\n",
468 ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
469 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
472 #ifdef MPT_DEBUG_REPLY
474 * mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
475 * @ioc: Pointer to MPT_ADAPTER structure
476 * @ioc_status: U32 IOCStatus word from IOC
477 * @scsi_status: U8 sam status from target
478 * @scsi_state: U8 scsi state
479 * @sc: original scsi cmnd pointer
480 * @mf: Pointer to MPT request frame
482 * Refer to lsi/mpi.h.
484 static void
485 mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
486 u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
488 char extend_desc[EVENT_DESCR_STR_SZ];
489 char *desc = NULL;
491 switch (ioc_status) {
493 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
494 desc = "SCSI Invalid Bus";
495 break;
497 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
498 desc = "SCSI Invalid TargetID";
499 break;
501 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
503 * Inquiry is issued for device scanning
505 if (sc->cmnd[0] != 0x12)
506 desc = "SCSI Device Not There";
507 break;
509 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
510 desc = "SCSI Data Overrun";
511 break;
513 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
514 desc = "SCSI I/O Data Error";
515 break;
517 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
518 desc = "SCSI Protocol Error";
519 break;
521 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
522 desc = "SCSI Task Terminated";
523 break;
525 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
526 desc = "SCSI Residual Mismatch";
527 break;
529 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
530 desc = "SCSI Task Management Failed";
531 break;
533 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
534 desc = "SCSI IOC Terminated";
535 break;
537 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
538 desc = "SCSI Ext Terminated";
539 break;
542 if (!desc)
543 return;
545 snprintf(extend_desc, EVENT_DESCR_STR_SZ,
546 "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
547 sc->device->host->host_no,
548 sc->device->channel, sc->device->id, sc->device->lun,
549 sc->cmnd[0], scsi_status, scsi_state);
551 printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
552 ioc->name, ioc_status, desc, extend_desc);
554 #endif
556 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
558 * mptscsih_io_done - Main SCSI IO callback routine registered to
559 * Fusion MPT (base) driver
560 * @ioc: Pointer to MPT_ADAPTER structure
561 * @mf: Pointer to original MPT request frame
562 * @r: Pointer to MPT reply frame (NULL if TurboReply)
564 * This routine is called from mpt.c::mpt_interrupt() at the completion
565 * of any SCSI IO request.
566 * This routine is registered with the Fusion MPT (base) driver at driver
567 * load/init time via the mpt_register() API call.
569 * Returns 1 indicating alloc'd request frame ptr should be freed.
572 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
574 struct scsi_cmnd *sc;
575 MPT_SCSI_HOST *hd;
576 SCSIIORequest_t *pScsiReq;
577 SCSIIOReply_t *pScsiReply;
578 u16 req_idx, req_idx_MR;
579 VirtDevice *vdev;
580 VirtTarget *vtarget;
582 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
584 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
585 req_idx_MR = (mr != NULL) ?
586 le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
587 if ((req_idx != req_idx_MR) ||
588 (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
589 printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
590 ioc->name);
591 printk (MYIOC_s_ERR_FMT
592 "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
593 ioc->name, req_idx, req_idx_MR, mf, mr,
594 hd->ScsiLookup[req_idx_MR]);
595 return 0;
598 sc = hd->ScsiLookup[req_idx];
599 hd->ScsiLookup[req_idx] = NULL;
600 if (sc == NULL) {
601 MPIHeader_t *hdr = (MPIHeader_t *)mf;
603 /* Remark: writeSDP1 will use the ScsiDoneCtx
604 * If a SCSI I/O cmd, device disabled by OS and
605 * completion done. Cannot touch sc struct. Just free mem.
607 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
608 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
609 ioc->name);
611 mptscsih_freeChainBuffers(ioc, req_idx);
612 return 1;
615 if ((unsigned char *)mf != sc->host_scribble) {
616 mptscsih_freeChainBuffers(ioc, req_idx);
617 return 1;
620 sc->host_scribble = NULL;
621 sc->result = DID_OK << 16; /* Set default reply as OK */
622 pScsiReq = (SCSIIORequest_t *) mf;
623 pScsiReply = (SCSIIOReply_t *) mr;
625 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
626 dmfprintk((MYIOC_s_INFO_FMT
627 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
628 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
629 }else{
630 dmfprintk((MYIOC_s_INFO_FMT
631 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
632 ioc->name, mf, mr, sc, req_idx));
635 if (pScsiReply == NULL) {
636 /* special context reply handling */
638 } else {
639 u32 xfer_cnt;
640 u16 status;
641 u8 scsi_state, scsi_status;
642 u32 log_info;
644 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
645 scsi_state = pScsiReply->SCSIState;
646 scsi_status = pScsiReply->SCSIStatus;
647 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
648 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
649 log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
652 * if we get a data underrun indication, yet no data was
653 * transferred and the SCSI status indicates that the
654 * command was never started, change the data underrun
655 * to success
657 if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
658 (scsi_status == MPI_SCSI_STATUS_BUSY ||
659 scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
660 scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
661 status = MPI_IOCSTATUS_SUCCESS;
664 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
665 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
668 * Look for + dump FCP ResponseInfo[]!
670 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
671 pScsiReply->ResponseInfo) {
672 printk(KERN_NOTICE "[%d:%d:%d:%d] "
673 "FCP_ResponseInfo=%08xh\n",
674 sc->device->host->host_no, sc->device->channel,
675 sc->device->id, sc->device->lun,
676 le32_to_cpu(pScsiReply->ResponseInfo));
679 switch(status) {
680 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
681 /* CHECKME!
682 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
683 * But not: DID_BUS_BUSY lest one risk
684 * killing interrupt handler:-(
686 sc->result = SAM_STAT_BUSY;
687 break;
689 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
690 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
691 sc->result = DID_BAD_TARGET << 16;
692 break;
694 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
695 /* Spoof to SCSI Selection Timeout! */
696 if (ioc->bus_type != FC)
697 sc->result = DID_NO_CONNECT << 16;
698 /* else fibre, just stall until rescan event */
699 else
700 sc->result = DID_REQUEUE << 16;
702 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
703 hd->sel_timeout[pScsiReq->TargetID]++;
705 vdev = sc->device->hostdata;
706 if (!vdev)
707 break;
708 vtarget = vdev->vtarget;
709 if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
710 mptscsih_issue_sep_command(ioc, vtarget,
711 MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
712 vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
714 break;
716 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
717 if ( ioc->bus_type == SAS ) {
718 u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
719 if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
720 if ((log_info & SAS_LOGINFO_MASK)
721 == SAS_LOGINFO_NEXUS_LOSS) {
722 sc->result = (DID_BUS_BUSY << 16);
723 break;
726 } else if (ioc->bus_type == FC) {
728 * The FC IOC may kill a request for variety of
729 * reasons, some of which may be recovered by a
730 * retry, some which are unlikely to be
731 * recovered. Return DID_ERROR instead of
732 * DID_RESET to permit retry of the command,
733 * just not an infinite number of them
735 sc->result = DID_ERROR << 16;
736 break;
740 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
743 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
744 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
745 /* Linux handles an unsolicited DID_RESET better
746 * than an unsolicited DID_ABORT.
748 sc->result = DID_RESET << 16;
750 break;
752 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
753 scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);
754 if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
755 sc->result=DID_SOFT_ERROR << 16;
756 else /* Sufficient data transfer occurred */
757 sc->result = (DID_OK << 16) | scsi_status;
758 dreplyprintk((KERN_NOTICE
759 "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
760 sc->result, sc->device->channel, sc->device->id));
761 break;
763 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
765 * Do upfront check for valid SenseData and give it
766 * precedence!
768 sc->result = (DID_OK << 16) | scsi_status;
769 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
770 /* Have already saved the status and sense data
773 } else {
774 if (xfer_cnt < sc->underflow) {
775 if (scsi_status == SAM_STAT_BUSY)
776 sc->result = SAM_STAT_BUSY;
777 else
778 sc->result = DID_SOFT_ERROR << 16;
780 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
781 /* What to do?
783 sc->result = DID_SOFT_ERROR << 16;
785 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
786 /* Not real sure here either... */
787 sc->result = DID_RESET << 16;
791 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
792 sc->underflow));
793 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
794 /* Report Queue Full
796 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
797 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
799 break;
801 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
802 scsi_set_resid(sc, 0);
803 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
804 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
805 sc->result = (DID_OK << 16) | scsi_status;
806 if (scsi_state == 0) {
808 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
810 * If running against circa 200003dd 909 MPT f/w,
811 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
812 * (QUEUE_FULL) returned from device! --> get 0x0000?128
813 * and with SenseBytes set to 0.
815 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
816 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
819 else if (scsi_state &
820 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
823 * What to do?
825 sc->result = DID_SOFT_ERROR << 16;
827 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
828 /* Not real sure here either... */
829 sc->result = DID_RESET << 16;
831 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
832 /* Device Inq. data indicates that it supports
833 * QTags, but rejects QTag messages.
834 * This command completed OK.
836 * Not real sure here either so do nothing... */
839 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
840 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
842 /* Add handling of:
843 * Reservation Conflict, Busy,
844 * Command Terminated, CHECK
846 break;
848 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
849 sc->result = DID_SOFT_ERROR << 16;
850 break;
852 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
853 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
854 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
855 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
856 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
857 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
858 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
859 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
860 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
861 default:
863 * What to do?
865 sc->result = DID_SOFT_ERROR << 16;
866 break;
868 } /* switch(status) */
870 #ifdef MPT_DEBUG_REPLY
871 if (sc->result) {
873 mptscsih_iocstatus_info_scsiio(ioc, status,
874 scsi_status, scsi_state, sc);
876 dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
877 "result=0x%08x\n\tiocstatus=0x%04X "
878 "scsi_state=0x%02X scsi_status=0x%02X "
879 "loginfo=0x%08X\n", __FUNCTION__,
880 sc->device->host->host_no, sc->device->channel, sc->device->id,
881 sc->device->lun, sc->cmnd[0], sc->result, status,
882 scsi_state, scsi_status, log_info));
884 dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
885 "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
886 sc->device->host->host_no,
887 sc->device->channel, sc->device->id,
888 sc->device->lun, scsi_get_resid(sc),
889 scsi_bufflen(sc), xfer_cnt));
891 #endif
893 } /* end of address reply case */
895 /* Unmap the DMA buffers, if any. */
896 scsi_dma_unmap(sc);
898 sc->scsi_done(sc); /* Issue the command callback */
900 /* Free Chain buffers */
901 mptscsih_freeChainBuffers(ioc, req_idx);
902 return 1;
906 * mptscsih_flush_running_cmds - For each command found, search
907 * Scsi_Host instance taskQ and reply to OS.
908 * Called only if recovering from a FW reload.
909 * @hd: Pointer to a SCSI HOST structure
911 * Returns: None.
913 * Must be called while new I/Os are being queued.
915 static void
916 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
918 MPT_ADAPTER *ioc = hd->ioc;
919 struct scsi_cmnd *SCpnt;
920 MPT_FRAME_HDR *mf;
921 int ii;
922 int max = ioc->req_depth;
924 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
925 for (ii= 0; ii < max; ii++) {
926 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
928 /* Command found.
931 /* Null ScsiLookup index
933 hd->ScsiLookup[ii] = NULL;
935 mf = MPT_INDEX_2_MFPTR(ioc, ii);
936 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
937 mf, SCpnt));
939 /* Free Chain buffers */
940 mptscsih_freeChainBuffers(ioc, ii);
942 /* Free Message frames */
943 mpt_free_msg_frame(ioc, mf);
945 if ((unsigned char *)mf != SCpnt->host_scribble)
946 continue;
948 /* Set status, free OS resources (SG DMA buffers)
949 * Do OS callback
951 scsi_dma_unmap(SCpnt);
953 SCpnt->result = DID_RESET << 16;
954 SCpnt->host_scribble = NULL;
956 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
960 return;
964 * mptscsih_search_running_cmds - Delete any commands associated
965 * with the specified target and lun. Function called only
966 * when a lun is disable by mid-layer.
967 * Do NOT access the referenced scsi_cmnd structure or
968 * members. Will cause either a paging or NULL ptr error.
969 * (BUT, BUT, BUT, the code does reference it! - mdr)
970 * @hd: Pointer to a SCSI HOST structure
971 * @vdevice: per device private data
973 * Returns: None.
975 * Called from slave_destroy.
977 static void
978 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
980 SCSIIORequest_t *mf = NULL;
981 int ii;
982 int max = hd->ioc->req_depth;
983 struct scsi_cmnd *sc;
984 struct scsi_lun lun;
986 dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
987 vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
989 for (ii=0; ii < max; ii++) {
990 if ((sc = hd->ScsiLookup[ii]) != NULL) {
992 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
993 if (mf == NULL)
994 continue;
995 int_to_scsilun(vdevice->lun, &lun);
996 if ((mf->Bus != vdevice->vtarget->channel) ||
997 (mf->TargetID != vdevice->vtarget->id) ||
998 memcmp(lun.scsi_lun, mf->LUN, 8))
999 continue;
1000 dsprintk(( "search_running: found (sc=%p, mf = %p) "
1001 "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
1002 mf, mf->Bus, mf->TargetID, vdevice->lun));
1004 /* Cleanup
1006 hd->ScsiLookup[ii] = NULL;
1007 mptscsih_freeChainBuffers(hd->ioc, ii);
1008 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1009 if ((unsigned char *)mf != sc->host_scribble)
1010 continue;
1011 scsi_dma_unmap(sc);
1013 sc->host_scribble = NULL;
1014 sc->result = DID_NO_CONNECT << 16;
1015 sc->scsi_done(sc);
1018 return;
1021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1025 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1026 * from a SCSI target device.
1027 * @sc: Pointer to scsi_cmnd structure
1028 * @pScsiReply: Pointer to SCSIIOReply_t
1029 * @pScsiReq: Pointer to original SCSI request
1031 * This routine periodically reports QUEUE_FULL status returned from a
1032 * SCSI target device. It reports this to the console via kernel
1033 * printk() API call, not more than once every 10 seconds.
1035 static void
1036 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1038 long time = jiffies;
1039 MPT_SCSI_HOST *hd;
1041 if (sc->device == NULL)
1042 return;
1043 if (sc->device->host == NULL)
1044 return;
1045 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1046 return;
1048 if (time - hd->last_queue_full > 10 * HZ) {
1049 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1050 hd->ioc->name, 0, sc->device->id, sc->device->lun));
1051 hd->last_queue_full = time;
1055 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1057 * mptscsih_remove - Removed scsi devices
1058 * @pdev: Pointer to pci_dev structure
1062 void
1063 mptscsih_remove(struct pci_dev *pdev)
1065 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1066 struct Scsi_Host *host = ioc->sh;
1067 MPT_SCSI_HOST *hd;
1068 int sz1;
1070 if(!host) {
1071 mpt_detach(pdev);
1072 return;
1075 scsi_remove_host(host);
1077 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1078 return;
1080 mptscsih_shutdown(pdev);
1082 sz1=0;
1084 if (hd->ScsiLookup != NULL) {
1085 sz1 = hd->ioc->req_depth * sizeof(void *);
1086 kfree(hd->ScsiLookup);
1087 hd->ScsiLookup = NULL;
1090 dprintk((MYIOC_s_INFO_FMT
1091 "Free'd ScsiLookup (%d) memory\n",
1092 hd->ioc->name, sz1));
1094 kfree(hd->info_kbuf);
1096 /* NULL the Scsi_Host pointer
1098 hd->ioc->sh = NULL;
1100 scsi_host_put(host);
1102 mpt_detach(pdev);
1106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1108 * mptscsih_shutdown - reboot notifier
1111 void
1112 mptscsih_shutdown(struct pci_dev *pdev)
1114 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1115 struct Scsi_Host *host = ioc->sh;
1116 MPT_SCSI_HOST *hd;
1118 if(!host)
1119 return;
1121 hd = (MPT_SCSI_HOST *)host->hostdata;
1125 #ifdef CONFIG_PM
1126 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1128 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1133 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1135 mptscsih_shutdown(pdev);
1136 return mpt_suspend(pdev,state);
1139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1141 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1146 mptscsih_resume(struct pci_dev *pdev)
1148 return mpt_resume(pdev);
1151 #endif
1153 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1155 * mptscsih_info - Return information about MPT adapter
1156 * @SChost: Pointer to Scsi_Host structure
1158 * (linux scsi_host_template.info routine)
1160 * Returns pointer to buffer where information was written.
1162 const char *
1163 mptscsih_info(struct Scsi_Host *SChost)
1165 MPT_SCSI_HOST *h;
1166 int size = 0;
1168 h = (MPT_SCSI_HOST *)SChost->hostdata;
1170 if (h) {
1171 if (h->info_kbuf == NULL)
1172 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1173 return h->info_kbuf;
1174 h->info_kbuf[0] = '\0';
1176 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1177 h->info_kbuf[size-1] = '\0';
1180 return h->info_kbuf;
1183 struct info_str {
1184 char *buffer;
1185 int length;
1186 int offset;
1187 int pos;
1190 static void
1191 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1193 if (info->pos + len > info->length)
1194 len = info->length - info->pos;
1196 if (info->pos + len < info->offset) {
1197 info->pos += len;
1198 return;
1201 if (info->pos < info->offset) {
1202 data += (info->offset - info->pos);
1203 len -= (info->offset - info->pos);
1206 if (len > 0) {
1207 memcpy(info->buffer + info->pos, data, len);
1208 info->pos += len;
1212 static int
1213 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1215 va_list args;
1216 char buf[81];
1217 int len;
1219 va_start(args, fmt);
1220 len = vsprintf(buf, fmt, args);
1221 va_end(args);
1223 mptscsih_copy_mem_info(info, buf, len);
1224 return len;
1227 static int
1228 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1230 struct info_str info;
1232 info.buffer = pbuf;
1233 info.length = len;
1234 info.offset = offset;
1235 info.pos = 0;
1237 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1238 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1239 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1240 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1242 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1247 * mptscsih_proc_info - Return information about MPT adapter
1248 * @host: scsi host struct
1249 * @buffer: if write, user data; if read, buffer for user
1250 * @start: returns the buffer address
1251 * @offset: if write, 0; if read, the current offset into the buffer from
1252 * the previous read.
1253 * @length: if write, return length;
1254 * @func: write = 1; read = 0
1256 * (linux scsi_host_template.info routine)
1259 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1260 int length, int func)
1262 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1263 MPT_ADAPTER *ioc = hd->ioc;
1264 int size = 0;
1266 if (func) {
1268 * write is not supported
1270 } else {
1271 if (start)
1272 *start = buffer;
1274 size = mptscsih_host_info(ioc, buffer, offset, length);
1277 return size;
1280 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1281 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1283 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1285 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1286 * @SCpnt: Pointer to scsi_cmnd structure
1287 * @done: Pointer SCSI mid-layer IO completion function
1289 * (linux scsi_host_template.queuecommand routine)
1290 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1291 * from a linux scsi_cmnd request and send it to the IOC.
1293 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1296 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1298 MPT_SCSI_HOST *hd;
1299 MPT_FRAME_HDR *mf;
1300 SCSIIORequest_t *pScsiReq;
1301 VirtDevice *vdev = SCpnt->device->hostdata;
1302 int lun;
1303 u32 datalen;
1304 u32 scsictl;
1305 u32 scsidir;
1306 u32 cmd_len;
1307 int my_idx;
1308 int ii;
1310 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1311 lun = SCpnt->device->lun;
1312 SCpnt->scsi_done = done;
1314 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1315 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1317 if (hd->resetPending) {
1318 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1319 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1320 return SCSI_MLQUEUE_HOST_BUSY;
1324 * Put together a MPT SCSI request...
1326 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1327 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1328 hd->ioc->name));
1329 return SCSI_MLQUEUE_HOST_BUSY;
1332 pScsiReq = (SCSIIORequest_t *) mf;
1334 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1336 ADD_INDEX_LOG(my_idx);
1338 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1339 * Seems we may receive a buffer (datalen>0) even when there
1340 * will be no data transfer! GRRRRR...
1342 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1343 datalen = scsi_bufflen(SCpnt);
1344 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1345 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1346 datalen = scsi_bufflen(SCpnt);
1347 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1348 } else {
1349 datalen = 0;
1350 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1353 /* Default to untagged. Once a target structure has been allocated,
1354 * use the Inquiry data to determine if device supports tagged.
1356 if (vdev
1357 && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1358 && (SCpnt->device->tagged_supported)) {
1359 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1360 } else {
1361 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1364 /* Use the above information to set up the message frame
1366 pScsiReq->TargetID = (u8) vdev->vtarget->id;
1367 pScsiReq->Bus = vdev->vtarget->channel;
1368 pScsiReq->ChainOffset = 0;
1369 if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
1370 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1371 else
1372 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1373 pScsiReq->CDBLength = SCpnt->cmd_len;
1374 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1375 pScsiReq->Reserved = 0;
1376 pScsiReq->MsgFlags = mpt_msg_flags();
1377 int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1378 pScsiReq->Control = cpu_to_le32(scsictl);
1381 * Write SCSI CDB into the message
1383 cmd_len = SCpnt->cmd_len;
1384 for (ii=0; ii < cmd_len; ii++)
1385 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1387 for (ii=cmd_len; ii < 16; ii++)
1388 pScsiReq->CDB[ii] = 0;
1390 /* DataLength */
1391 pScsiReq->DataLength = cpu_to_le32(datalen);
1393 /* SenseBuffer low address */
1394 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1395 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1397 /* Now add the SG list
1398 * Always have a SGE even if null length.
1400 if (datalen == 0) {
1401 /* Add a NULL SGE */
1402 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1403 (dma_addr_t) -1);
1404 } else {
1405 /* Add a 32 or 64 bit SGE */
1406 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1407 goto fail;
1410 SCpnt->host_scribble = (unsigned char *)mf;
1411 hd->ScsiLookup[my_idx] = SCpnt;
1413 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1414 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1415 hd->ioc->name, SCpnt, mf, my_idx));
1416 DBG_DUMP_REQUEST_FRAME(mf)
1417 return 0;
1419 fail:
1420 hd->ScsiLookup[my_idx] = NULL;
1421 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1422 mpt_free_msg_frame(hd->ioc, mf);
1423 return SCSI_MLQUEUE_HOST_BUSY;
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1428 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1429 * with a SCSI IO request
1430 * @hd: Pointer to the MPT_SCSI_HOST instance
1431 * @req_idx: Index of the SCSI IO request frame.
1433 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1434 * No return.
1436 static void
1437 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1439 MPT_FRAME_HDR *chain;
1440 unsigned long flags;
1441 int chain_idx;
1442 int next;
1444 /* Get the first chain index and reset
1445 * tracker state.
1447 chain_idx = ioc->ReqToChain[req_idx];
1448 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1450 while (chain_idx != MPT_HOST_NO_CHAIN) {
1452 /* Save the next chain buffer index */
1453 next = ioc->ChainToChain[chain_idx];
1455 /* Free this chain buffer and reset
1456 * tracker
1458 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1460 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1461 + (chain_idx * ioc->req_sz));
1463 spin_lock_irqsave(&ioc->FreeQlock, flags);
1464 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1465 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1467 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1468 ioc->name, chain_idx));
1470 /* handle next */
1471 chain_idx = next;
1473 return;
1476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1478 * Reset Handling
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484 * @hd: Pointer to MPT SCSI HOST structure
1485 * @type: Task Management type
1486 * @channel: channel number for task management
1487 * @id: Logical Target ID for reset (if appropriate)
1488 * @lun: Logical Unit for reset (if appropriate)
1489 * @ctx2abort: Context for the task to be aborted (if appropriate)
1490 * @timeout: timeout for task management control
1492 * Fall through to mpt_HardResetHandler if: not operational, too many
1493 * failed TM requests or handshake failure.
1495 * Remark: Currently invoked from a non-interrupt thread (_bh).
1497 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1498 * will be active.
1500 * Returns 0 for SUCCESS, or %FAILED.
1503 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1505 MPT_ADAPTER *ioc;
1506 int rc = -1;
1507 u32 ioc_raw_state;
1508 unsigned long flags;
1510 ioc = hd->ioc;
1511 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1513 // SJR - CHECKME - Can we avoid this here?
1514 // (mpt_HardResetHandler has this check...)
1515 spin_lock_irqsave(&ioc->diagLock, flags);
1516 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1517 spin_unlock_irqrestore(&ioc->diagLock, flags);
1518 return FAILED;
1520 spin_unlock_irqrestore(&ioc->diagLock, flags);
1522 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1523 * If we time out and not bus reset, then we return a FAILED status
1524 * to the caller.
1525 * The call to mptscsih_tm_pending_wait() will set the pending flag
1526 * if we are
1527 * successful. Otherwise, reload the FW.
1529 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1530 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1531 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1532 "Timed out waiting for last TM (%d) to complete! \n",
1533 hd->ioc->name, hd->tmPending));
1534 return FAILED;
1535 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1536 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
1537 "reset: Timed out waiting for last TM (%d) "
1538 "to complete! \n", hd->ioc->name,
1539 hd->tmPending));
1540 return FAILED;
1541 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1542 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1543 "Timed out waiting for last TM (%d) to complete! \n",
1544 hd->ioc->name, hd->tmPending));
1545 return FAILED;
1547 } else {
1548 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1549 hd->tmPending |= (1 << type);
1550 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1553 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1555 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1556 printk(MYIOC_s_WARN_FMT
1557 "TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1558 ioc->name, type, ioc_raw_state);
1559 printk(KERN_WARNING " Issuing HardReset!!\n");
1560 if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1561 printk((KERN_WARNING "TMHandler: HardReset "
1562 "FAILED!!\n"));
1563 return FAILED;
1566 if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1567 printk(MYIOC_s_WARN_FMT
1568 "TM Handler for type=%x: ioc_state: "
1569 "DOORBELL_ACTIVE (0x%x)!\n",
1570 ioc->name, type, ioc_raw_state);
1571 return FAILED;
1574 /* Isse the Task Mgmt request.
1576 if (hd->hard_resets < -1)
1577 hd->hard_resets++;
1579 rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1580 ctx2abort, timeout);
1581 if (rc)
1582 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1583 hd->ioc->name);
1584 else
1585 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
1586 hd->ioc->name));
1588 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1590 return rc;
1594 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1596 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1597 * @hd: Pointer to MPT_SCSI_HOST structure
1598 * @type: Task Management type
1599 * @channel: channel number for task management
1600 * @id: Logical Target ID for reset (if appropriate)
1601 * @lun: Logical Unit for reset (if appropriate)
1602 * @ctx2abort: Context for the task to be aborted (if appropriate)
1603 * @timeout: timeout for task management control
1605 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1606 * or a non-interrupt thread. In the former, must not call schedule().
1608 * Not all fields are meaningfull for all task types.
1610 * Returns 0 for SUCCESS, or FAILED.
1613 static int
1614 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1616 MPT_FRAME_HDR *mf;
1617 SCSITaskMgmt_t *pScsiTm;
1618 int ii;
1619 int retval;
1621 /* Return Fail to calling function if no message frames available.
1623 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1624 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1625 hd->ioc->name));
1626 return FAILED;
1628 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1629 hd->ioc->name, mf));
1631 /* Format the Request
1633 pScsiTm = (SCSITaskMgmt_t *) mf;
1634 pScsiTm->TargetID = id;
1635 pScsiTm->Bus = channel;
1636 pScsiTm->ChainOffset = 0;
1637 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1639 pScsiTm->Reserved = 0;
1640 pScsiTm->TaskType = type;
1641 pScsiTm->Reserved1 = 0;
1642 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1643 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1645 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1647 for (ii=0; ii < 7; ii++)
1648 pScsiTm->Reserved2[ii] = 0;
1650 pScsiTm->TaskMsgContext = ctx2abort;
1652 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1653 "type=%d\n", hd->ioc->name, ctx2abort, type));
1655 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1657 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1658 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
1659 dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
1660 " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1661 hd->ioc, mf, retval));
1662 goto fail_out;
1665 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1666 dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1667 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1668 hd->ioc, mf));
1669 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1670 hd->ioc->name));
1671 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1672 dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
1673 hd->ioc->name, retval));
1674 goto fail_out;
1678 * Handle success case, see if theres a non-zero ioc_status.
1680 if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1681 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1682 hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1683 retval = 0;
1684 else
1685 retval = FAILED;
1687 return retval;
1689 fail_out:
1692 * Free task managment mf, and corresponding tm flags
1694 mpt_free_msg_frame(hd->ioc, mf);
1695 hd->tmPending = 0;
1696 hd->tmState = TM_STATE_NONE;
1697 return FAILED;
1700 static int
1701 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1703 switch (ioc->bus_type) {
1704 case FC:
1705 return 40;
1706 case SAS:
1707 return 10;
1708 case SPI:
1709 default:
1710 return 2;
1714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1716 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1717 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1719 * (linux scsi_host_template.eh_abort_handler routine)
1721 * Returns SUCCESS or FAILED.
1724 mptscsih_abort(struct scsi_cmnd * SCpnt)
1726 MPT_SCSI_HOST *hd;
1727 MPT_FRAME_HDR *mf;
1728 u32 ctx2abort;
1729 int scpnt_idx;
1730 int retval;
1731 VirtDevice *vdev;
1732 ulong sn = SCpnt->serial_number;
1734 /* If we can't locate our host adapter structure, return FAILED status.
1736 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1737 SCpnt->result = DID_RESET << 16;
1738 SCpnt->scsi_done(SCpnt);
1739 dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1740 "Can't locate host! (sc=%p)\n",
1741 SCpnt));
1742 return FAILED;
1745 /* Find this command
1747 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1748 /* Cmd not found in ScsiLookup.
1749 * Do OS callback.
1751 SCpnt->result = DID_RESET << 16;
1752 dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1753 "Command not in the active list! (sc=%p)\n",
1754 hd->ioc->name, SCpnt));
1755 return SUCCESS;
1758 if (hd->resetPending)
1759 return FAILED;
1761 if (hd->timeouts < -1)
1762 hd->timeouts++;
1764 printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1765 hd->ioc->name, SCpnt);
1766 scsi_print_command(SCpnt);
1768 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1769 * (the IO to be ABORT'd)
1771 * NOTE: Since we do not byteswap MsgContext, we do not
1772 * swap it here either. It is an opaque cookie to
1773 * the controller, so it does not matter. -DaveM
1775 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1776 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1778 hd->abortSCpnt = SCpnt;
1780 vdev = SCpnt->device->hostdata;
1781 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1782 vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
1783 ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1785 if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1786 SCpnt->serial_number == sn)
1787 retval = FAILED;
1789 printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1790 hd->ioc->name,
1791 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1793 if (retval == 0)
1794 return SUCCESS;
1795 else
1796 return FAILED;
1799 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1801 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1802 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1804 * (linux scsi_host_template.eh_dev_reset_handler routine)
1806 * Returns SUCCESS or FAILED.
1809 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1811 MPT_SCSI_HOST *hd;
1812 int retval;
1813 VirtDevice *vdev;
1815 /* If we can't locate our host adapter structure, return FAILED status.
1817 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1818 dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1819 "Can't locate host! (sc=%p)\n",
1820 SCpnt));
1821 return FAILED;
1824 if (hd->resetPending)
1825 return FAILED;
1827 printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1828 hd->ioc->name, SCpnt);
1829 scsi_print_command(SCpnt);
1831 vdev = SCpnt->device->hostdata;
1832 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1833 vdev->vtarget->channel, vdev->vtarget->id,
1834 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1836 printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1837 hd->ioc->name,
1838 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1840 if (retval == 0)
1841 return SUCCESS;
1842 else
1843 return FAILED;
1847 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1849 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1850 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1852 * (linux scsi_host_template.eh_bus_reset_handler routine)
1854 * Returns SUCCESS or FAILED.
1857 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1859 MPT_SCSI_HOST *hd;
1860 int retval;
1861 VirtDevice *vdev;
1863 /* If we can't locate our host adapter structure, return FAILED status.
1865 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1866 dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1867 "Can't locate host! (sc=%p)\n",
1868 SCpnt ) );
1869 return FAILED;
1872 printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1873 hd->ioc->name, SCpnt);
1874 scsi_print_command(SCpnt);
1876 if (hd->timeouts < -1)
1877 hd->timeouts++;
1879 vdev = SCpnt->device->hostdata;
1880 retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1881 vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1883 printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1884 hd->ioc->name,
1885 ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1887 if (retval == 0)
1888 return SUCCESS;
1889 else
1890 return FAILED;
1893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1895 * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1896 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1898 * (linux scsi_host_template.eh_host_reset_handler routine)
1900 * Returns SUCCESS or FAILED.
1903 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1905 MPT_SCSI_HOST * hd;
1906 int status = SUCCESS;
1908 /* If we can't locate the host to reset, then we failed. */
1909 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1910 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1911 "Can't locate host! (sc=%p)\n",
1912 SCpnt ) );
1913 return FAILED;
1916 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1917 hd->ioc->name, SCpnt);
1919 /* If our attempts to reset the host failed, then return a failed
1920 * status. The host will be taken off line by the SCSI mid-layer.
1922 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1923 status = FAILED;
1924 } else {
1925 /* Make sure TM pending is cleared and TM state is set to
1926 * NONE.
1928 hd->tmPending = 0;
1929 hd->tmState = TM_STATE_NONE;
1932 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1933 "Status = %s\n",
1934 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1936 return status;
1939 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1941 * mptscsih_tm_pending_wait - wait for pending task management request to complete
1942 * @hd: Pointer to MPT host structure.
1944 * Returns {SUCCESS,FAILED}.
1946 static int
1947 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1949 unsigned long flags;
1950 int loop_count = 4 * 10; /* Wait 10 seconds */
1951 int status = FAILED;
1953 do {
1954 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1955 if (hd->tmState == TM_STATE_NONE) {
1956 hd->tmState = TM_STATE_IN_PROGRESS;
1957 hd->tmPending = 1;
1958 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1959 status = SUCCESS;
1960 break;
1962 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1963 msleep(250);
1964 } while (--loop_count);
1966 return status;
1969 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1971 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1972 * @hd: Pointer to MPT host structure.
1973 * @timeout: timeout value
1975 * Returns {SUCCESS,FAILED}.
1977 static int
1978 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1980 unsigned long flags;
1981 int loop_count = 4 * timeout;
1982 int status = FAILED;
1984 do {
1985 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1986 if(hd->tmPending == 0) {
1987 status = SUCCESS;
1988 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1989 break;
1991 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1992 msleep(250);
1993 } while (--loop_count);
1995 return status;
1998 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1999 static void
2000 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2002 char *desc;
2004 switch (response_code) {
2005 case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2006 desc = "The task completed.";
2007 break;
2008 case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2009 desc = "The IOC received an invalid frame status.";
2010 break;
2011 case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2012 desc = "The task type is not supported.";
2013 break;
2014 case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2015 desc = "The requested task failed.";
2016 break;
2017 case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2018 desc = "The task completed successfully.";
2019 break;
2020 case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2021 desc = "The LUN request is invalid.";
2022 break;
2023 case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2024 desc = "The task is in the IOC queue and has not been sent to target.";
2025 break;
2026 default:
2027 desc = "unknown";
2028 break;
2030 printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2031 ioc->name, response_code, desc);
2034 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2036 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2037 * @ioc: Pointer to MPT_ADAPTER structure
2038 * @mf: Pointer to SCSI task mgmt request frame
2039 * @mr: Pointer to SCSI task mgmt reply frame
2041 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2042 * of any SCSI task management request.
2043 * This routine is registered with the MPT (base) driver at driver
2044 * load/init time via the mpt_register() API call.
2046 * Returns 1 indicating alloc'd request frame ptr should be freed.
2049 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2051 SCSITaskMgmtReply_t *pScsiTmReply;
2052 SCSITaskMgmt_t *pScsiTmReq;
2053 MPT_SCSI_HOST *hd;
2054 unsigned long flags;
2055 u16 iocstatus;
2056 u8 tmType;
2057 u32 termination_count;
2059 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2060 ioc->name, mf, mr));
2061 if (!ioc->sh) {
2062 dtmprintk((MYIOC_s_WARN_FMT
2063 "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2064 return 1;
2067 if (mr == NULL) {
2068 dtmprintk((MYIOC_s_WARN_FMT
2069 "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2070 return 1;
2073 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2074 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2075 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2076 tmType = pScsiTmReq->TaskType;
2077 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2078 termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2080 if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2081 pScsiTmReply->ResponseCode)
2082 mptscsih_taskmgmt_response_code(ioc,
2083 pScsiTmReply->ResponseCode);
2084 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2086 #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
2087 printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2088 "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2089 "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2090 pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2091 le16_to_cpu(pScsiTmReply->IOCStatus),
2092 le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2093 le32_to_cpu(pScsiTmReply->TerminationCount));
2094 #endif
2095 if (!iocstatus) {
2096 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2097 hd->abortSCpnt = NULL;
2098 goto out;
2101 /* Error? (anything non-zero?) */
2103 /* clear flags and continue.
2105 switch (tmType) {
2107 case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2108 if (termination_count == 1)
2109 iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2110 hd->abortSCpnt = NULL;
2111 break;
2113 case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2115 /* If an internal command is present
2116 * or the TM failed - reload the FW.
2117 * FC FW may respond FAILED to an ABORT
2119 if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2120 hd->cmdPtr)
2121 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2122 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2123 break;
2125 case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2126 default:
2127 break;
2130 out:
2131 spin_lock_irqsave(&ioc->FreeQlock, flags);
2132 hd->tmPending = 0;
2133 hd->tmState = TM_STATE_NONE;
2134 hd->tm_iocstatus = iocstatus;
2135 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2137 return 1;
2140 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2142 * This is anyones guess quite frankly.
2145 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2146 sector_t capacity, int geom[])
2148 int heads;
2149 int sectors;
2150 sector_t cylinders;
2151 ulong dummy;
2153 heads = 64;
2154 sectors = 32;
2156 dummy = heads * sectors;
2157 cylinders = capacity;
2158 sector_div(cylinders,dummy);
2161 * Handle extended translation size for logical drives
2162 * > 1Gb
2164 if ((ulong)capacity >= 0x200000) {
2165 heads = 255;
2166 sectors = 63;
2167 dummy = heads * sectors;
2168 cylinders = capacity;
2169 sector_div(cylinders,dummy);
2172 /* return result */
2173 geom[0] = heads;
2174 geom[1] = sectors;
2175 geom[2] = cylinders;
2177 dprintk((KERN_NOTICE
2178 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2179 sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
2181 return 0;
2184 /* Search IOC page 3 to determine if this is hidden physical disk
2188 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2190 struct inactive_raid_component_info *component_info;
2191 int i;
2192 int rc = 0;
2194 if (!ioc->raid_data.pIocPg3)
2195 goto out;
2196 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2197 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2198 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2199 rc = 1;
2200 goto out;
2205 * Check inactive list for matching phys disks
2207 if (list_empty(&ioc->raid_data.inactive_list))
2208 goto out;
2210 down(&ioc->raid_data.inactive_list_mutex);
2211 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2212 list) {
2213 if ((component_info->d.PhysDiskID == id) &&
2214 (component_info->d.PhysDiskBus == channel))
2215 rc = 1;
2217 up(&ioc->raid_data.inactive_list_mutex);
2219 out:
2220 return rc;
2222 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2225 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2227 struct inactive_raid_component_info *component_info;
2228 int i;
2229 int rc = -ENXIO;
2231 if (!ioc->raid_data.pIocPg3)
2232 goto out;
2233 for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2234 if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2235 (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2236 rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2237 goto out;
2242 * Check inactive list for matching phys disks
2244 if (list_empty(&ioc->raid_data.inactive_list))
2245 goto out;
2247 down(&ioc->raid_data.inactive_list_mutex);
2248 list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2249 list) {
2250 if ((component_info->d.PhysDiskID == id) &&
2251 (component_info->d.PhysDiskBus == channel))
2252 rc = component_info->d.PhysDiskNum;
2254 up(&ioc->raid_data.inactive_list_mutex);
2256 out:
2257 return rc;
2259 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2262 * OS entry point to allow for host driver to free allocated memory
2263 * Called if no device present or device being unloaded
2265 void
2266 mptscsih_slave_destroy(struct scsi_device *sdev)
2268 struct Scsi_Host *host = sdev->host;
2269 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2270 VirtTarget *vtarget;
2271 VirtDevice *vdevice;
2272 struct scsi_target *starget;
2274 starget = scsi_target(sdev);
2275 vtarget = starget->hostdata;
2276 vdevice = sdev->hostdata;
2278 mptscsih_search_running_cmds(hd, vdevice);
2279 vtarget->num_luns--;
2280 mptscsih_synchronize_cache(hd, vdevice);
2281 kfree(vdevice);
2282 sdev->hostdata = NULL;
2285 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2287 * mptscsih_change_queue_depth - This function will set a devices queue depth
2288 * @sdev: per scsi_device pointer
2289 * @qdepth: requested queue depth
2291 * Adding support for new 'change_queue_depth' api.
2294 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2296 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2297 VirtTarget *vtarget;
2298 struct scsi_target *starget;
2299 int max_depth;
2300 int tagged;
2302 starget = scsi_target(sdev);
2303 vtarget = starget->hostdata;
2305 if (hd->ioc->bus_type == SPI) {
2306 if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2307 max_depth = 1;
2308 else if (sdev->type == TYPE_DISK &&
2309 vtarget->minSyncFactor <= MPT_ULTRA160)
2310 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2311 else
2312 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2313 } else
2314 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2316 if (qdepth > max_depth)
2317 qdepth = max_depth;
2318 if (qdepth == 1)
2319 tagged = 0;
2320 else
2321 tagged = MSG_SIMPLE_TAG;
2323 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2324 return sdev->queue_depth;
2328 * OS entry point to adjust the queue_depths on a per-device basis.
2329 * Called once per device the bus scan. Use it to force the queue_depth
2330 * member to 1 if a device does not support Q tags.
2331 * Return non-zero if fails.
2334 mptscsih_slave_configure(struct scsi_device *sdev)
2336 struct Scsi_Host *sh = sdev->host;
2337 VirtTarget *vtarget;
2338 VirtDevice *vdevice;
2339 struct scsi_target *starget;
2340 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2342 starget = scsi_target(sdev);
2343 vtarget = starget->hostdata;
2344 vdevice = sdev->hostdata;
2346 dsprintk((MYIOC_s_INFO_FMT
2347 "device @ %p, channel=%d, id=%d, lun=%d\n",
2348 hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2349 if (hd->ioc->bus_type == SPI)
2350 dsprintk((MYIOC_s_INFO_FMT
2351 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2352 hd->ioc->name, sdev->sdtr, sdev->wdtr,
2353 sdev->ppr, sdev->inquiry_len));
2355 if (sdev->id > sh->max_id) {
2356 /* error case, should never happen */
2357 scsi_adjust_queue_depth(sdev, 0, 1);
2358 goto slave_configure_exit;
2361 vdevice->configured_lun = 1;
2362 mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2364 dsprintk((MYIOC_s_INFO_FMT
2365 "Queue depth=%d, tflags=%x\n",
2366 hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2368 if (hd->ioc->bus_type == SPI)
2369 dsprintk((MYIOC_s_INFO_FMT
2370 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2371 hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2372 vtarget->minSyncFactor));
2374 slave_configure_exit:
2376 dsprintk((MYIOC_s_INFO_FMT
2377 "tagged %d, simple %d, ordered %d\n",
2378 hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2379 sdev->ordered_tags));
2381 return 0;
2384 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2386 * Private routines...
2389 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2390 /* Utility function to copy sense data from the scsi_cmnd buffer
2391 * to the FC and SCSI target structures.
2394 static void
2395 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2397 VirtDevice *vdev;
2398 SCSIIORequest_t *pReq;
2399 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2401 /* Get target structure
2403 pReq = (SCSIIORequest_t *) mf;
2404 vdev = sc->device->hostdata;
2406 if (sense_count) {
2407 u8 *sense_data;
2408 int req_index;
2410 /* Copy the sense received into the scsi command block. */
2411 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2412 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2413 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2415 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2417 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2418 if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2419 int idx;
2420 MPT_ADAPTER *ioc = hd->ioc;
2422 idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2423 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2424 ioc->events[idx].eventContext = ioc->eventContext;
2426 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2427 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2428 (sc->device->channel << 8) || sc->device->id;
2430 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2432 ioc->eventContext++;
2433 if (hd->ioc->pcidev->vendor ==
2434 PCI_VENDOR_ID_IBM) {
2435 mptscsih_issue_sep_command(hd->ioc,
2436 vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2437 vdev->vtarget->tflags |=
2438 MPT_TARGET_FLAGS_LED_ON;
2442 } else {
2443 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2444 hd->ioc->name));
2448 static int
2449 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2451 MPT_SCSI_HOST *hd;
2452 int i;
2454 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2456 for (i = 0; i < hd->ioc->req_depth; i++) {
2457 if (hd->ScsiLookup[i] == sc) {
2458 return i;
2462 return -1;
2465 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2467 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2469 MPT_SCSI_HOST *hd;
2470 unsigned long flags;
2471 int ii;
2473 dtmprintk((KERN_WARNING MYNAM
2474 ": IOC %s_reset routed to SCSI host driver!\n",
2475 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2476 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2478 /* If a FW reload request arrives after base installed but
2479 * before all scsi hosts have been attached, then an alt_ioc
2480 * may have a NULL sh pointer.
2482 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2483 return 0;
2484 else
2485 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2487 if (reset_phase == MPT_IOC_SETUP_RESET) {
2488 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2490 /* Clean Up:
2491 * 1. Set Hard Reset Pending Flag
2492 * All new commands go to doneQ
2494 hd->resetPending = 1;
2496 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2497 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2499 /* 2. Flush running commands
2500 * Clean ScsiLookup (and associated memory)
2501 * AND clean mytaskQ
2504 /* 2b. Reply to OS all known outstanding I/O commands.
2506 mptscsih_flush_running_cmds(hd);
2508 /* 2c. If there was an internal command that
2509 * has not completed, configuration or io request,
2510 * free these resources.
2512 if (hd->cmdPtr) {
2513 del_timer(&hd->timer);
2514 mpt_free_msg_frame(ioc, hd->cmdPtr);
2517 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2519 } else {
2520 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2522 /* Once a FW reload begins, all new OS commands are
2523 * redirected to the doneQ w/ a reset status.
2524 * Init all control structures.
2527 /* ScsiLookup initialization
2529 for (ii=0; ii < hd->ioc->req_depth; ii++)
2530 hd->ScsiLookup[ii] = NULL;
2532 /* 2. Chain Buffer initialization
2535 /* 4. Renegotiate to all devices, if SPI
2538 /* 5. Enable new commands to be posted
2540 spin_lock_irqsave(&ioc->FreeQlock, flags);
2541 hd->tmPending = 0;
2542 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2543 hd->resetPending = 0;
2544 hd->tmState = TM_STATE_NONE;
2546 /* 6. If there was an internal command,
2547 * wake this process up.
2549 if (hd->cmdPtr) {
2551 * Wake up the original calling thread
2553 hd->pLocal = &hd->localReply;
2554 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2555 hd->scandv_wait_done = 1;
2556 wake_up(&hd->scandv_waitq);
2557 hd->cmdPtr = NULL;
2560 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2564 return 1; /* currently means nothing really */
2567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2569 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2571 MPT_SCSI_HOST *hd;
2572 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2574 devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2575 ioc->name, event));
2577 if (ioc->sh == NULL ||
2578 ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2579 return 1;
2581 switch (event) {
2582 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2583 /* FIXME! */
2584 break;
2585 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2586 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2587 if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2588 hd->soft_resets++;
2589 break;
2590 case MPI_EVENT_LOGOUT: /* 09 */
2591 /* FIXME! */
2592 break;
2594 case MPI_EVENT_RESCAN: /* 06 */
2595 break;
2598 * CHECKME! Don't think we need to do
2599 * anything for these, but...
2601 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2602 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2604 * CHECKME! Falling thru...
2606 break;
2608 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2609 break;
2611 case MPI_EVENT_NONE: /* 00 */
2612 case MPI_EVENT_LOG_DATA: /* 01 */
2613 case MPI_EVENT_STATE_CHANGE: /* 02 */
2614 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2615 default:
2616 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2617 break;
2620 return 1; /* currently means nothing really */
2623 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2625 * Bus Scan and Domain Validation functionality ...
2628 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2630 * mptscsih_scandv_complete - Scan and DV callback routine registered
2631 * to Fustion MPT (base) driver.
2633 * @ioc: Pointer to MPT_ADAPTER structure
2634 * @mf: Pointer to original MPT request frame
2635 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
2637 * This routine is called from mpt.c::mpt_interrupt() at the completion
2638 * of any SCSI IO request.
2639 * This routine is registered with the Fusion MPT (base) driver at driver
2640 * load/init time via the mpt_register() API call.
2642 * Returns 1 indicating alloc'd request frame ptr should be freed.
2644 * Remark: Sets a completion code and (possibly) saves sense data
2645 * in the IOC member localReply structure.
2646 * Used ONLY for DV and other internal commands.
2649 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2651 MPT_SCSI_HOST *hd;
2652 SCSIIORequest_t *pReq;
2653 int completionCode;
2654 u16 req_idx;
2656 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2658 if ((mf == NULL) ||
2659 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2660 printk(MYIOC_s_ERR_FMT
2661 "ScanDvComplete, %s req frame ptr! (=%p)\n",
2662 ioc->name, mf?"BAD":"NULL", (void *) mf);
2663 goto wakeup;
2666 del_timer(&hd->timer);
2667 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2668 hd->ScsiLookup[req_idx] = NULL;
2669 pReq = (SCSIIORequest_t *) mf;
2671 if (mf != hd->cmdPtr) {
2672 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2673 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2675 hd->cmdPtr = NULL;
2677 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2678 hd->ioc->name, mf, mr, req_idx));
2680 hd->pLocal = &hd->localReply;
2681 hd->pLocal->scsiStatus = 0;
2683 /* If target struct exists, clear sense valid flag.
2685 if (mr == NULL) {
2686 completionCode = MPT_SCANDV_GOOD;
2687 } else {
2688 SCSIIOReply_t *pReply;
2689 u16 status;
2690 u8 scsi_status;
2692 pReply = (SCSIIOReply_t *) mr;
2694 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2695 scsi_status = pReply->SCSIStatus;
2697 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
2698 status, pReply->SCSIState, scsi_status,
2699 le32_to_cpu(pReply->IOCLogInfo)));
2701 switch(status) {
2703 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
2704 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2705 break;
2707 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
2708 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
2709 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
2710 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
2711 completionCode = MPT_SCANDV_DID_RESET;
2712 break;
2714 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
2715 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
2716 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
2717 if (pReply->Function == MPI_FUNCTION_CONFIG) {
2718 ConfigReply_t *pr = (ConfigReply_t *)mr;
2719 completionCode = MPT_SCANDV_GOOD;
2720 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2721 hd->pLocal->header.PageLength = pr->Header.PageLength;
2722 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2723 hd->pLocal->header.PageType = pr->Header.PageType;
2725 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2726 /* If the RAID Volume request is successful,
2727 * return GOOD, else indicate that
2728 * some type of error occurred.
2730 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
2731 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2732 completionCode = MPT_SCANDV_GOOD;
2733 else
2734 completionCode = MPT_SCANDV_SOME_ERROR;
2735 memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2737 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2738 u8 *sense_data;
2739 int sz;
2741 /* save sense data in global structure
2743 completionCode = MPT_SCANDV_SENSE;
2744 hd->pLocal->scsiStatus = scsi_status;
2745 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2746 (req_idx * MPT_SENSE_BUFFER_ALLOC));
2748 sz = min_t(int, pReq->SenseBufferLength,
2749 SCSI_STD_SENSE_BYTES);
2750 memcpy(hd->pLocal->sense, sense_data, sz);
2752 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
2753 sense_data));
2754 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2755 if (pReq->CDB[0] == INQUIRY)
2756 completionCode = MPT_SCANDV_ISSUE_SENSE;
2757 else
2758 completionCode = MPT_SCANDV_DID_RESET;
2760 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2761 completionCode = MPT_SCANDV_DID_RESET;
2762 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2763 completionCode = MPT_SCANDV_DID_RESET;
2764 else {
2765 completionCode = MPT_SCANDV_GOOD;
2766 hd->pLocal->scsiStatus = scsi_status;
2768 break;
2770 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
2771 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2772 completionCode = MPT_SCANDV_DID_RESET;
2773 else
2774 completionCode = MPT_SCANDV_SOME_ERROR;
2775 break;
2777 default:
2778 completionCode = MPT_SCANDV_SOME_ERROR;
2779 break;
2781 } /* switch(status) */
2783 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
2784 completionCode));
2785 } /* end of address reply case */
2787 hd->pLocal->completion = completionCode;
2789 /* MF and RF are freed in mpt_interrupt
2791 wakeup:
2792 /* Free Chain buffers (will never chain) in scan or dv */
2793 //mptscsih_freeChainBuffers(ioc, req_idx);
2796 * Wake up the original calling thread
2798 hd->scandv_wait_done = 1;
2799 wake_up(&hd->scandv_waitq);
2801 return 1;
2804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2805 /* mptscsih_timer_expired - Call back for timer process.
2806 * Used only for dv functionality.
2807 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2810 void
2811 mptscsih_timer_expired(unsigned long data)
2813 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2815 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2817 if (hd->cmdPtr) {
2818 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2820 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2821 /* Desire to issue a task management request here.
2822 * TM requests MUST be single threaded.
2823 * If old eh code and no TM current, issue request.
2824 * If new eh code, do nothing. Wait for OS cmd timeout
2825 * for bus reset.
2827 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
2828 } else {
2829 /* Perform a FW reload */
2830 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2831 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2834 } else {
2835 /* This should NEVER happen */
2836 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2839 /* No more processing.
2840 * TM call will generate an interrupt for SCSI TM Management.
2841 * The FW will reply to all outstanding commands, callback will finish cleanup.
2842 * Hard reset clean-up will free all resources.
2844 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
2846 return;
2850 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2852 * mptscsih_do_cmd - Do internal command.
2853 * @hd: MPT_SCSI_HOST pointer
2854 * @io: INTERNAL_CMD pointer.
2856 * Issue the specified internally generated command and do command
2857 * specific cleanup. For bus scan / DV only.
2858 * NOTES: If command is Inquiry and status is good,
2859 * initialize a target structure, save the data
2861 * Remark: Single threaded access only.
2863 * Return:
2864 * < 0 if an illegal command or no resources
2866 * 0 if good
2868 * > 0 if command complete but some type of completion error.
2870 static int
2871 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2873 MPT_FRAME_HDR *mf;
2874 SCSIIORequest_t *pScsiReq;
2875 SCSIIORequest_t ReqCopy;
2876 int my_idx, ii, dir;
2877 int rc, cmdTimeout;
2878 int in_isr;
2879 char cmdLen;
2880 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2881 char cmd = io->cmd;
2883 in_isr = in_interrupt();
2884 if (in_isr) {
2885 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2886 hd->ioc->name));
2887 return -EPERM;
2891 /* Set command specific information
2893 switch (cmd) {
2894 case INQUIRY:
2895 cmdLen = 6;
2896 dir = MPI_SCSIIO_CONTROL_READ;
2897 CDB[0] = cmd;
2898 CDB[4] = io->size;
2899 cmdTimeout = 10;
2900 break;
2902 case TEST_UNIT_READY:
2903 cmdLen = 6;
2904 dir = MPI_SCSIIO_CONTROL_READ;
2905 cmdTimeout = 10;
2906 break;
2908 case START_STOP:
2909 cmdLen = 6;
2910 dir = MPI_SCSIIO_CONTROL_READ;
2911 CDB[0] = cmd;
2912 CDB[4] = 1; /*Spin up the disk */
2913 cmdTimeout = 15;
2914 break;
2916 case REQUEST_SENSE:
2917 cmdLen = 6;
2918 CDB[0] = cmd;
2919 CDB[4] = io->size;
2920 dir = MPI_SCSIIO_CONTROL_READ;
2921 cmdTimeout = 10;
2922 break;
2924 case READ_BUFFER:
2925 cmdLen = 10;
2926 dir = MPI_SCSIIO_CONTROL_READ;
2927 CDB[0] = cmd;
2928 if (io->flags & MPT_ICFLAG_ECHO) {
2929 CDB[1] = 0x0A;
2930 } else {
2931 CDB[1] = 0x02;
2934 if (io->flags & MPT_ICFLAG_BUF_CAP) {
2935 CDB[1] |= 0x01;
2937 CDB[6] = (io->size >> 16) & 0xFF;
2938 CDB[7] = (io->size >> 8) & 0xFF;
2939 CDB[8] = io->size & 0xFF;
2940 cmdTimeout = 10;
2941 break;
2943 case WRITE_BUFFER:
2944 cmdLen = 10;
2945 dir = MPI_SCSIIO_CONTROL_WRITE;
2946 CDB[0] = cmd;
2947 if (io->flags & MPT_ICFLAG_ECHO) {
2948 CDB[1] = 0x0A;
2949 } else {
2950 CDB[1] = 0x02;
2952 CDB[6] = (io->size >> 16) & 0xFF;
2953 CDB[7] = (io->size >> 8) & 0xFF;
2954 CDB[8] = io->size & 0xFF;
2955 cmdTimeout = 10;
2956 break;
2958 case RESERVE:
2959 cmdLen = 6;
2960 dir = MPI_SCSIIO_CONTROL_READ;
2961 CDB[0] = cmd;
2962 cmdTimeout = 10;
2963 break;
2965 case RELEASE:
2966 cmdLen = 6;
2967 dir = MPI_SCSIIO_CONTROL_READ;
2968 CDB[0] = cmd;
2969 cmdTimeout = 10;
2970 break;
2972 case SYNCHRONIZE_CACHE:
2973 cmdLen = 10;
2974 dir = MPI_SCSIIO_CONTROL_READ;
2975 CDB[0] = cmd;
2976 // CDB[1] = 0x02; /* set immediate bit */
2977 cmdTimeout = 10;
2978 break;
2980 default:
2981 /* Error Case */
2982 return -EFAULT;
2985 /* Get and Populate a free Frame
2987 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
2988 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
2989 hd->ioc->name));
2990 return -EBUSY;
2993 pScsiReq = (SCSIIORequest_t *) mf;
2995 /* Get the request index */
2996 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2997 ADD_INDEX_LOG(my_idx); /* for debug */
2999 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3000 pScsiReq->TargetID = io->physDiskNum;
3001 pScsiReq->Bus = 0;
3002 pScsiReq->ChainOffset = 0;
3003 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3004 } else {
3005 pScsiReq->TargetID = io->id;
3006 pScsiReq->Bus = io->channel;
3007 pScsiReq->ChainOffset = 0;
3008 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3011 pScsiReq->CDBLength = cmdLen;
3012 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3014 pScsiReq->Reserved = 0;
3016 pScsiReq->MsgFlags = mpt_msg_flags();
3017 /* MsgContext set in mpt_get_msg_fram call */
3019 int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3021 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3022 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3023 else
3024 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3026 if (cmd == REQUEST_SENSE) {
3027 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3028 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3029 hd->ioc->name, cmd));
3032 for (ii=0; ii < 16; ii++)
3033 pScsiReq->CDB[ii] = CDB[ii];
3035 pScsiReq->DataLength = cpu_to_le32(io->size);
3036 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3037 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3039 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3040 hd->ioc->name, cmd, io->channel, io->id, io->lun));
3042 if (dir == MPI_SCSIIO_CONTROL_READ) {
3043 mpt_add_sge((char *) &pScsiReq->SGL,
3044 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3045 io->data_dma);
3046 } else {
3047 mpt_add_sge((char *) &pScsiReq->SGL,
3048 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3049 io->data_dma);
3052 /* The ISR will free the request frame, but we need
3053 * the information to initialize the target. Duplicate.
3055 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3057 /* Issue this command after:
3058 * finish init
3059 * add timer
3060 * Wait until the reply has been received
3061 * ScsiScanDvCtx callback function will
3062 * set hd->pLocal;
3063 * set scandv_wait_done and call wake_up
3065 hd->pLocal = NULL;
3066 hd->timer.expires = jiffies + HZ*cmdTimeout;
3067 hd->scandv_wait_done = 0;
3069 /* Save cmd pointer, for resource free if timeout or
3070 * FW reload occurs
3072 hd->cmdPtr = mf;
3074 add_timer(&hd->timer);
3075 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3076 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3078 if (hd->pLocal) {
3079 rc = hd->pLocal->completion;
3080 hd->pLocal->skip = 0;
3082 /* Always set fatal error codes in some cases.
3084 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3085 rc = -ENXIO;
3086 else if (rc == MPT_SCANDV_SOME_ERROR)
3087 rc = -rc;
3088 } else {
3089 rc = -EFAULT;
3090 /* This should never happen. */
3091 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3092 hd->ioc->name));
3095 return rc;
3098 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3100 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3101 * @hd: Pointer to a SCSI HOST structure
3102 * @vdevice: virtual target device
3104 * Uses the ISR, but with special processing.
3105 * MUST be single-threaded.
3108 static void
3109 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3111 INTERNAL_CMD iocmd;
3113 /* Following parameters will not change
3114 * in this routine.
3116 iocmd.cmd = SYNCHRONIZE_CACHE;
3117 iocmd.flags = 0;
3118 iocmd.physDiskNum = -1;
3119 iocmd.data = NULL;
3120 iocmd.data_dma = -1;
3121 iocmd.size = 0;
3122 iocmd.rsvd = iocmd.rsvd2 = 0;
3123 iocmd.channel = vdevice->vtarget->channel;
3124 iocmd.id = vdevice->vtarget->id;
3125 iocmd.lun = vdevice->lun;
3127 if ((vdevice->vtarget->type == TYPE_DISK) &&
3128 (vdevice->configured_lun))
3129 mptscsih_do_cmd(hd, &iocmd);
3132 EXPORT_SYMBOL(mptscsih_remove);
3133 EXPORT_SYMBOL(mptscsih_shutdown);
3134 #ifdef CONFIG_PM
3135 EXPORT_SYMBOL(mptscsih_suspend);
3136 EXPORT_SYMBOL(mptscsih_resume);
3137 #endif
3138 EXPORT_SYMBOL(mptscsih_proc_info);
3139 EXPORT_SYMBOL(mptscsih_info);
3140 EXPORT_SYMBOL(mptscsih_qcmd);
3141 EXPORT_SYMBOL(mptscsih_slave_destroy);
3142 EXPORT_SYMBOL(mptscsih_slave_configure);
3143 EXPORT_SYMBOL(mptscsih_abort);
3144 EXPORT_SYMBOL(mptscsih_dev_reset);
3145 EXPORT_SYMBOL(mptscsih_bus_reset);
3146 EXPORT_SYMBOL(mptscsih_host_reset);
3147 EXPORT_SYMBOL(mptscsih_bios_param);
3148 EXPORT_SYMBOL(mptscsih_io_done);
3149 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3150 EXPORT_SYMBOL(mptscsih_scandv_complete);
3151 EXPORT_SYMBOL(mptscsih_event_process);
3152 EXPORT_SYMBOL(mptscsih_ioc_reset);
3153 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3154 EXPORT_SYMBOL(mptscsih_timer_expired);
3155 EXPORT_SYMBOL(mptscsih_TMHandler);
3157 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/