xref: /linux/drivers/message/fusion/mptscsih.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
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.
5  *
6  *  Copyright (c) 1999-2007 LSI Logic Corporation
7  *  (mailto:mpt_linux_developer@lsi.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
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.
15 
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.
20 
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.
31 
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
40 
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
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46 
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>
58 
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>
65 
66 #include "mptbase.h"
67 #include "mptscsih.h"
68 #include "lsi/mpi_log_sas.h"
69 
70 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
71 #define my_NAME		"Fusion MPT SCSI Host driver"
72 #define my_VERSION	MPT_LINUX_VERSION_COMMON
73 #define MYNAM		"mptscsih"
74 
75 MODULE_AUTHOR(MODULEAUTHOR);
76 MODULE_DESCRIPTION(my_NAME);
77 MODULE_LICENSE("GPL");
78 MODULE_VERSION(my_VERSION);
79 
80 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
81 /*
82  *  Other private/forward protos...
83  */
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);
87 
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);
95 
96 static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout);
97 
98 int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
99 int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
100 
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);
104 
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
111 
112 #define SNS_LEN(scp)	sizeof((scp)->sense_buffer)
113 
114 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
115 /**
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
120  *
121  *	This routine places a MPT request frame back on the MPT adapter's
122  *	FreeQ.
123  */
124 static inline void
125 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
126 {
127 	if (sizeof(dma_addr_t) == sizeof(u64)) {
128 		SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
129 		u32 tmp = dma_addr & 0xFFFFFFFF;
130 
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);
135 
136 	} else {
137 		SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
138 		pSge->FlagsLength = cpu_to_le32(flagslength);
139 		pSge->Address = cpu_to_le32(dma_addr);
140 	}
141 } /* mptscsih_add_sge() */
142 
143 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
144 /**
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
150  *
151  *	This routine places a MPT request frame back on the MPT adapter's
152  *	FreeQ.
153  */
154 static inline void
155 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
156 {
157 	if (sizeof(dma_addr_t) == sizeof(u64)) {
158 		SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
159 		u32 tmp = dma_addr & 0xFFFFFFFF;
160 
161 		pChain->Length = cpu_to_le16(length);
162 		pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
163 
164 		pChain->NextChainOffset = next;
165 
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);
175 	}
176 } /* mptscsih_add_chain() */
177 
178 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
179 /*
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)
184  *
185  *	return SUCCESS or FAILED
186  */
187 static inline int
188 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
189 {
190 	MPT_FRAME_HDR *chainBuf;
191 	unsigned long flags;
192 	int rc;
193 	int chain_idx;
194 
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;
200 
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));
214 	}
215 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
216 
217 	*retIndex = chain_idx;
218 	return rc;
219 } /* mptscsih_getFreeChainBuffer() */
220 
221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
222 /*
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
228  *
229  *	Returns ...
230  */
231 static int
232 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
233 		SCSIIORequest_t *pReq, int req_idx)
234 {
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;
249 
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;
255 	}
256 
257 	psge = (char *) &pReq->SGL;
258 	frm_sz = ioc->req_sz;
259 
260 	/* Map the data portion, if any.
261 	 * sges_left  = 0 if no data transfer.
262 	 */
263 	if ( (sges_left = SCpnt->use_sg) ) {
264 		sges_left = pci_map_sg(ioc->pcidev,
265 			       (struct scatterlist *) SCpnt->request_buffer,
266  			       SCpnt->use_sg,
267 			       SCpnt->sc_data_direction);
268 		if (sges_left == 0)
269 			return FAILED;
270 	} else if (SCpnt->request_bufflen) {
271 		SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
272 				      SCpnt->request_buffer,
273 				      SCpnt->request_bufflen,
274 				      SCpnt->sc_data_direction);
275 		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
276 				ioc->name, SCpnt, SCpnt->request_bufflen));
277 		mptscsih_add_sge((char *) &pReq->SGL,
278 			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
279 			SCpnt->SCp.dma_handle);
280 
281 		return SUCCESS;
282 	}
283 
284 	/* Handle the SG case.
285 	 */
286 	sg = (struct scatterlist *) SCpnt->request_buffer;
287 	sg_done  = 0;
288 	sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
289 	chainSge = NULL;
290 
291 	/* Prior to entering this loop - the following must be set
292 	 * current MF:  sgeOffset (bytes)
293 	 *              chainSge (Null if original MF is not a chain buffer)
294 	 *              sg_done (num SGE done for this MF)
295 	 */
296 
297 nextSGEset:
298 	numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
299 	numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
300 
301 	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
302 
303 	/* Get first (num - 1) SG elements
304 	 * Skip any SG entries with a length of 0
305 	 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
306 	 */
307 	for (ii=0; ii < (numSgeThisFrame-1); ii++) {
308 		thisxfer = sg_dma_len(sg);
309 		if (thisxfer == 0) {
310 			sg ++; /* Get next SG element from the OS */
311 			sg_done++;
312 			continue;
313 		}
314 
315 		v2 = sg_dma_address(sg);
316 		mptscsih_add_sge(psge, sgflags | thisxfer, v2);
317 
318 		sg++;		/* Get next SG element from the OS */
319 		psge += (sizeof(u32) + sizeof(dma_addr_t));
320 		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
321 		sg_done++;
322 	}
323 
324 	if (numSgeThisFrame == sges_left) {
325 		/* Add last element, end of buffer and end of list flags.
326 		 */
327 		sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
328 				MPT_SGE_FLAGS_END_OF_BUFFER |
329 				MPT_SGE_FLAGS_END_OF_LIST;
330 
331 		/* Add last SGE and set termination flags.
332 		 * Note: Last SGE may have a length of 0 - which should be ok.
333 		 */
334 		thisxfer = sg_dma_len(sg);
335 
336 		v2 = sg_dma_address(sg);
337 		mptscsih_add_sge(psge, sgflags | thisxfer, v2);
338 		/*
339 		sg++;
340 		psge += (sizeof(u32) + sizeof(dma_addr_t));
341 		*/
342 		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
343 		sg_done++;
344 
345 		if (chainSge) {
346 			/* The current buffer is a chain buffer,
347 			 * but there is not another one.
348 			 * Update the chain element
349 			 * Offset and Length fields.
350 			 */
351 			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
352 		} else {
353 			/* The current buffer is the original MF
354 			 * and there is no Chain buffer.
355 			 */
356 			pReq->ChainOffset = 0;
357 			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
358 			dsgprintk((MYIOC_s_INFO_FMT
359 			    "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
360 			ioc->RequestNB[req_idx] = RequestNB;
361 		}
362 	} else {
363 		/* At least one chain buffer is needed.
364 		 * Complete the first MF
365 		 *  - last SGE element, set the LastElement bit
366 		 *  - set ChainOffset (words) for orig MF
367 		 *             (OR finish previous MF chain buffer)
368 		 *  - update MFStructPtr ChainIndex
369 		 *  - Populate chain element
370 		 * Also
371 		 * Loop until done.
372 		 */
373 
374 		dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
375 				ioc->name, sg_done));
376 
377 		/* Set LAST_ELEMENT flag for last non-chain element
378 		 * in the buffer. Since psge points at the NEXT
379 		 * SGE element, go back one SGE element, update the flags
380 		 * and reset the pointer. (Note: sgflags & thisxfer are already
381 		 * set properly).
382 		 */
383 		if (sg_done) {
384 			u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
385 			sgflags = le32_to_cpu(*ptmp);
386 			sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
387 			*ptmp = cpu_to_le32(sgflags);
388 		}
389 
390 		if (chainSge) {
391 			/* The current buffer is a chain buffer.
392 			 * chainSge points to the previous Chain Element.
393 			 * Update its chain element Offset and Length (must
394 			 * include chain element size) fields.
395 			 * Old chain element is now complete.
396 			 */
397 			u8 nextChain = (u8) (sgeOffset >> 2);
398 			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
399 			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
400 		} else {
401 			/* The original MF buffer requires a chain buffer -
402 			 * set the offset.
403 			 * Last element in this MF is a chain element.
404 			 */
405 			pReq->ChainOffset = (u8) (sgeOffset >> 2);
406 			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
407 			dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
408 			ioc->RequestNB[req_idx] = RequestNB;
409 		}
410 
411 		sges_left -= sg_done;
412 
413 
414 		/* NOTE: psge points to the beginning of the chain element
415 		 * in current buffer. Get a chain buffer.
416 		 */
417 		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
418 			dfailprintk((MYIOC_s_INFO_FMT
419 			    "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
420  			    ioc->name, pReq->CDB[0], SCpnt));
421 			return FAILED;
422 		}
423 
424 		/* Update the tracking arrays.
425 		 * If chainSge == NULL, update ReqToChain, else ChainToChain
426 		 */
427 		if (chainSge) {
428 			ioc->ChainToChain[chain_idx] = newIndex;
429 		} else {
430 			ioc->ReqToChain[req_idx] = newIndex;
431 		}
432 		chain_idx = newIndex;
433 		chain_dma_off = ioc->req_sz * chain_idx;
434 
435 		/* Populate the chainSGE for the current buffer.
436 		 * - Set chain buffer pointer to psge and fill
437 		 *   out the Address and Flags fields.
438 		 */
439 		chainSge = (char *) psge;
440 		dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",
441 				psge, req_idx));
442 
443 		/* Start the SGE for the next buffer
444 		 */
445 		psge = (char *) (ioc->ChainBuffer + chain_dma_off);
446 		sgeOffset = 0;
447 		sg_done = 0;
448 
449 		dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)\n",
450 				psge, chain_idx));
451 
452 		/* Start the SGE for the next buffer
453 		 */
454 
455 		goto nextSGEset;
456 	}
457 
458 	return SUCCESS;
459 } /* mptscsih_AddSGE() */
460 
461 static void
462 mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget,
463     U32 SlotStatus)
464 {
465 	MPT_FRAME_HDR *mf;
466 	SEPRequest_t 	 *SEPMsg;
467 
468 	if (ioc->bus_type == FC)
469 		return;
470 
471 	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
472 		dfailprintk((MYIOC_s_WARN_FMT "%s: no msg frames!!\n",
473 		    ioc->name,__FUNCTION__));
474 		return;
475 	}
476 
477 	SEPMsg = (SEPRequest_t *)mf;
478 	SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
479 	SEPMsg->Bus = vtarget->channel;
480 	SEPMsg->TargetID = vtarget->id;
481 	SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;
482 	SEPMsg->SlotStatus = SlotStatus;
483 	devtverboseprintk((MYIOC_s_WARN_FMT
484 	    "Sending SEP cmd=%x channel=%d id=%d\n",
485 	    ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));
486 	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
487 }
488 
489 #ifdef MPT_DEBUG_REPLY
490 /**
491  *	mptscsih_iocstatus_info_scsiio - IOCSTATUS information for SCSIIO
492  *	@ioc: Pointer to MPT_ADAPTER structure
493  *	@ioc_status: U32 IOCStatus word from IOC
494  *	@scsi_status: U8 sam status from target
495  *	@scsi_state: U8 scsi state
496  *	@sc: original scsi cmnd pointer
497  *	@mf: Pointer to MPT request frame
498  *
499  *	Refer to lsi/mpi.h.
500  **/
501 static void
502 mptscsih_iocstatus_info_scsiio(MPT_ADAPTER *ioc, u32 ioc_status,
503     u8 scsi_status, u8 scsi_state, struct scsi_cmnd *sc)
504 {
505 	char extend_desc[EVENT_DESCR_STR_SZ];
506 	char *desc = NULL;
507 
508 	switch (ioc_status) {
509 
510 	case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
511 		desc = "SCSI Invalid Bus";
512 		break;
513 
514 	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
515 		desc = "SCSI Invalid TargetID";
516 		break;
517 
518 	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
519 		/*
520 		 * Inquiry is issued for device scanning
521 		 */
522 		if (sc->cmnd[0] != 0x12)
523 			desc = "SCSI Device Not There";
524 		break;
525 
526 	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
527 		desc = "SCSI Data Overrun";
528 		break;
529 
530 	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
531 		desc = "SCSI I/O Data Error";
532 		break;
533 
534 	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
535 		desc = "SCSI Protocol Error";
536 		break;
537 
538 	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
539 		desc = "SCSI Task Terminated";
540 		break;
541 
542 	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
543 		desc = "SCSI Residual Mismatch";
544 		break;
545 
546 	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
547 		desc = "SCSI Task Management Failed";
548 		break;
549 
550 	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
551 		desc = "SCSI IOC Terminated";
552 		break;
553 
554 	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
555 		desc = "SCSI Ext Terminated";
556 		break;
557 	}
558 
559 	if (!desc)
560 		return;
561 
562 	snprintf(extend_desc, EVENT_DESCR_STR_SZ,
563 	    "[%d:%d:%d:%d] cmd=%02Xh, sam_status=%02Xh state=%02Xh",
564 		sc->device->host->host_no,
565 		sc->device->channel, sc->device->id, sc->device->lun,
566 		sc->cmnd[0], scsi_status, scsi_state);
567 
568 	printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n",
569 	    ioc->name, ioc_status, desc, extend_desc);
570 }
571 #endif
572 
573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
574 /*
575  *	mptscsih_io_done - Main SCSI IO callback routine registered to
576  *	Fusion MPT (base) driver
577  *	@ioc: Pointer to MPT_ADAPTER structure
578  *	@mf: Pointer to original MPT request frame
579  *	@r: Pointer to MPT reply frame (NULL if TurboReply)
580  *
581  *	This routine is called from mpt.c::mpt_interrupt() at the completion
582  *	of any SCSI IO request.
583  *	This routine is registered with the Fusion MPT (base) driver at driver
584  *	load/init time via the mpt_register() API call.
585  *
586  *	Returns 1 indicating alloc'd request frame ptr should be freed.
587  */
588 int
589 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
590 {
591 	struct scsi_cmnd	*sc;
592 	MPT_SCSI_HOST	*hd;
593 	SCSIIORequest_t	*pScsiReq;
594 	SCSIIOReply_t	*pScsiReply;
595 	u16		 req_idx, req_idx_MR;
596 	VirtDevice	 *vdev;
597 	VirtTarget	 *vtarget;
598 
599 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
600 
601 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
602 	req_idx_MR = (mr != NULL) ?
603 	    le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;
604 	if ((req_idx != req_idx_MR) ||
605 	    (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {
606 		printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",
607 		    ioc->name);
608 		printk (MYIOC_s_ERR_FMT
609 		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",
610 		    ioc->name, req_idx, req_idx_MR, mf, mr,
611 		    hd->ScsiLookup[req_idx_MR]);
612 		return 0;
613 	}
614 
615 	sc = hd->ScsiLookup[req_idx];
616 	hd->ScsiLookup[req_idx] = NULL;
617 	if (sc == NULL) {
618 		MPIHeader_t *hdr = (MPIHeader_t *)mf;
619 
620 		/* Remark: writeSDP1 will use the ScsiDoneCtx
621 		 * If a SCSI I/O cmd, device disabled by OS and
622 		 * completion done. Cannot touch sc struct. Just free mem.
623 		 */
624 		if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
625 			printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
626 			ioc->name);
627 
628 		mptscsih_freeChainBuffers(ioc, req_idx);
629 		return 1;
630 	}
631 
632 	if ((unsigned char *)mf != sc->host_scribble) {
633 		mptscsih_freeChainBuffers(ioc, req_idx);
634 		return 1;
635 	}
636 
637 	sc->host_scribble = NULL;
638 	sc->result = DID_OK << 16;		/* Set default reply as OK */
639 	pScsiReq = (SCSIIORequest_t *) mf;
640 	pScsiReply = (SCSIIOReply_t *) mr;
641 
642 	if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
643 		dmfprintk((MYIOC_s_INFO_FMT
644 			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
645 			ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
646 	}else{
647 		dmfprintk((MYIOC_s_INFO_FMT
648 			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
649 			ioc->name, mf, mr, sc, req_idx));
650 	}
651 
652 	if (pScsiReply == NULL) {
653 		/* special context reply handling */
654 		;
655 	} else {
656 		u32	 xfer_cnt;
657 		u16	 status;
658 		u8	 scsi_state, scsi_status;
659 		u32	 log_info;
660 
661 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
662 		scsi_state = pScsiReply->SCSIState;
663 		scsi_status = pScsiReply->SCSIStatus;
664 		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
665 		sc->resid = sc->request_bufflen - xfer_cnt;
666 		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);
667 
668 		/*
669 		 *  if we get a data underrun indication, yet no data was
670 		 *  transferred and the SCSI status indicates that the
671 		 *  command was never started, change the data underrun
672 		 *  to success
673 		 */
674 		if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
675 		    (scsi_status == MPI_SCSI_STATUS_BUSY ||
676 		     scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||
677 		     scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {
678 			status = MPI_IOCSTATUS_SUCCESS;
679 		}
680 
681 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
682 			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
683 
684 		/*
685 		 *  Look for + dump FCP ResponseInfo[]!
686 		 */
687 		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&
688 		    pScsiReply->ResponseInfo) {
689 			printk(KERN_NOTICE "[%d:%d:%d:%d] "
690 			"FCP_ResponseInfo=%08xh\n",
691 			sc->device->host->host_no, sc->device->channel,
692 			sc->device->id, sc->device->lun,
693 			le32_to_cpu(pScsiReply->ResponseInfo));
694 		}
695 
696 		switch(status) {
697 		case MPI_IOCSTATUS_BUSY:			/* 0x0002 */
698 			/* CHECKME!
699 			 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
700 			 * But not: DID_BUS_BUSY lest one risk
701 			 * killing interrupt handler:-(
702 			 */
703 			sc->result = SAM_STAT_BUSY;
704 			break;
705 
706 		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */
707 		case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:	/* 0x0042 */
708 			sc->result = DID_BAD_TARGET << 16;
709 			break;
710 
711 		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
712 			/* Spoof to SCSI Selection Timeout! */
713 			if (ioc->bus_type != FC)
714 				sc->result = DID_NO_CONNECT << 16;
715 			/* else fibre, just stall until rescan event */
716 			else
717 				sc->result = DID_REQUEUE << 16;
718 
719 			if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
720 				hd->sel_timeout[pScsiReq->TargetID]++;
721 
722 			vdev = sc->device->hostdata;
723 			if (!vdev)
724 				break;
725 			vtarget = vdev->vtarget;
726 			if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {
727 				mptscsih_issue_sep_command(ioc, vtarget,
728 				    MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);
729 				vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;
730 			}
731 			break;
732 
733 		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
734 			if ( ioc->bus_type == SAS ) {
735 				u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);
736 				if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
737 					if ((log_info & SAS_LOGINFO_MASK)
738 					    == SAS_LOGINFO_NEXUS_LOSS) {
739 						sc->result = (DID_BUS_BUSY << 16);
740 						break;
741 					}
742 				}
743 			} else if (ioc->bus_type == FC) {
744 				/*
745 				 * The FC IOC may kill a request for variety of
746 				 * reasons, some of which may be recovered by a
747 				 * retry, some which are unlikely to be
748 				 * recovered. Return DID_ERROR instead of
749 				 * DID_RESET to permit retry of the command,
750 				 * just not an infinite number of them
751 				 */
752 				sc->result = DID_ERROR << 16;
753 				break;
754 			}
755 
756 			/*
757 			 * Allow non-SAS & non-NEXUS_LOSS to drop into below code
758 			 */
759 
760 		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
761 		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
762 			/* Linux handles an unsolicited DID_RESET better
763 			 * than an unsolicited DID_ABORT.
764 			 */
765 			sc->result = DID_RESET << 16;
766 
767 			break;
768 
769 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
770 			sc->resid = sc->request_bufflen - xfer_cnt;
771 			if((xfer_cnt==0)||(sc->underflow > xfer_cnt))
772 				sc->result=DID_SOFT_ERROR << 16;
773 			else /* Sufficient data transfer occurred */
774 				sc->result = (DID_OK << 16) | scsi_status;
775 			dreplyprintk((KERN_NOTICE
776 			    "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",
777 			    sc->result, sc->device->channel, sc->device->id));
778 			break;
779 
780 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
781 			/*
782 			 *  Do upfront check for valid SenseData and give it
783 			 *  precedence!
784 			 */
785 			sc->result = (DID_OK << 16) | scsi_status;
786 			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
787 				/* Have already saved the status and sense data
788 				 */
789 				;
790 			} else {
791 				if (xfer_cnt < sc->underflow) {
792 					if (scsi_status == SAM_STAT_BUSY)
793 						sc->result = SAM_STAT_BUSY;
794 					else
795 						sc->result = DID_SOFT_ERROR << 16;
796 				}
797 				if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
798 					/* What to do?
799 				 	*/
800 					sc->result = DID_SOFT_ERROR << 16;
801 				}
802 				else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
803 					/*  Not real sure here either...  */
804 					sc->result = DID_RESET << 16;
805 				}
806 			}
807 
808 			dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
809 					sc->underflow));
810 			dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
811 			/* Report Queue Full
812 			 */
813 			if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
814 				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
815 
816 			break;
817 
818 		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
819 			sc->resid=0;
820 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
821 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
822 			if (scsi_status == MPI_SCSI_STATUS_BUSY)
823 				sc->result = (DID_BUS_BUSY << 16) | scsi_status;
824 			else
825 				sc->result = (DID_OK << 16) | scsi_status;
826 			if (scsi_state == 0) {
827 				;
828 			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
829 				/*
830 				 * If running against circa 200003dd 909 MPT f/w,
831 				 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
832 				 * (QUEUE_FULL) returned from device! --> get 0x0000?128
833 				 * and with SenseBytes set to 0.
834 				 */
835 				if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
836 					mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
837 
838 			}
839 			else if (scsi_state &
840 			         (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
841 			   ) {
842 				/*
843 				 * What to do?
844 				 */
845 				sc->result = DID_SOFT_ERROR << 16;
846 			}
847 			else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
848 				/*  Not real sure here either...  */
849 				sc->result = DID_RESET << 16;
850 			}
851 			else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
852 				/* Device Inq. data indicates that it supports
853 				 * QTags, but rejects QTag messages.
854 				 * This command completed OK.
855 				 *
856 				 * Not real sure here either so do nothing...  */
857 			}
858 
859 			if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
860 				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
861 
862 			/* Add handling of:
863 			 * Reservation Conflict, Busy,
864 			 * Command Terminated, CHECK
865 			 */
866 			break;
867 
868 		case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
869 			sc->result = DID_SOFT_ERROR << 16;
870 			break;
871 
872 		case MPI_IOCSTATUS_INVALID_FUNCTION:		/* 0x0001 */
873 		case MPI_IOCSTATUS_INVALID_SGL:			/* 0x0003 */
874 		case MPI_IOCSTATUS_INTERNAL_ERROR:		/* 0x0004 */
875 		case MPI_IOCSTATUS_RESERVED:			/* 0x0005 */
876 		case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:	/* 0x0006 */
877 		case MPI_IOCSTATUS_INVALID_FIELD:		/* 0x0007 */
878 		case MPI_IOCSTATUS_INVALID_STATE:		/* 0x0008 */
879 		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
880 		case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:	/* 0x004A */
881 		default:
882 			/*
883 			 * What to do?
884 			 */
885 			sc->result = DID_SOFT_ERROR << 16;
886 			break;
887 
888 		}	/* switch(status) */
889 
890 #ifdef MPT_DEBUG_REPLY
891 		if (sc->result) {
892 
893 			mptscsih_iocstatus_info_scsiio(ioc, status,
894 			    scsi_status, scsi_state, sc);
895 
896 			dreplyprintk(("%s: [%d:%d:%d:%d] cmd=0x%02x "
897 			    "result=0x%08x\n\tiocstatus=0x%04X "
898 			    "scsi_state=0x%02X scsi_status=0x%02X "
899 			    "loginfo=0x%08X\n", __FUNCTION__,
900 			    sc->device->host->host_no, sc->device->channel, sc->device->id,
901 			    sc->device->lun, sc->cmnd[0], sc->result, status,
902 			    scsi_state, scsi_status, log_info));
903 
904 			dreplyprintk(("%s: [%d:%d:%d:%d] resid=%d "
905 			    "bufflen=%d xfer_cnt=%d\n", __FUNCTION__,
906 			    sc->device->host->host_no, sc->device->channel, sc->device->id,
907 			    sc->device->lun, sc->resid, sc->request_bufflen,
908 			    xfer_cnt));
909 		}
910 #endif
911 
912 	} /* end of address reply case */
913 
914 	/* Unmap the DMA buffers, if any. */
915 	if (sc->use_sg) {
916 		pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
917 			    sc->use_sg, sc->sc_data_direction);
918 	} else if (sc->request_bufflen) {
919 		pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
920 				sc->request_bufflen, sc->sc_data_direction);
921 	}
922 
923 	sc->scsi_done(sc);		/* Issue the command callback */
924 
925 	/* Free Chain buffers */
926 	mptscsih_freeChainBuffers(ioc, req_idx);
927 	return 1;
928 }
929 
930 /*
931  *	mptscsih_flush_running_cmds - For each command found, search
932  *		Scsi_Host instance taskQ and reply to OS.
933  *		Called only if recovering from a FW reload.
934  *	@hd: Pointer to a SCSI HOST structure
935  *
936  *	Returns: None.
937  *
938  *	Must be called while new I/Os are being queued.
939  */
940 static void
941 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
942 {
943 	MPT_ADAPTER *ioc = hd->ioc;
944 	struct scsi_cmnd	*SCpnt;
945 	MPT_FRAME_HDR	*mf;
946 	int		 ii;
947 	int		 max = ioc->req_depth;
948 
949 	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
950 	for (ii= 0; ii < max; ii++) {
951 		if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
952 
953 			/* Command found.
954 			 */
955 
956 			/* Null ScsiLookup index
957 			 */
958 			hd->ScsiLookup[ii] = NULL;
959 
960 			mf = MPT_INDEX_2_MFPTR(ioc, ii);
961 			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
962 					mf, SCpnt));
963 
964 			/* Free Chain buffers */
965 			mptscsih_freeChainBuffers(ioc, ii);
966 
967 			/* Free Message frames */
968 			mpt_free_msg_frame(ioc, mf);
969 
970 			if ((unsigned char *)mf != SCpnt->host_scribble)
971 				continue;
972 
973 			/* Set status, free OS resources (SG DMA buffers)
974 			 * Do OS callback
975 			 */
976 			if (SCpnt->use_sg) {
977 				pci_unmap_sg(ioc->pcidev,
978 					(struct scatterlist *) SCpnt->request_buffer,
979 					SCpnt->use_sg,
980 					SCpnt->sc_data_direction);
981 			} else if (SCpnt->request_bufflen) {
982 				pci_unmap_single(ioc->pcidev,
983 					SCpnt->SCp.dma_handle,
984 					SCpnt->request_bufflen,
985 					SCpnt->sc_data_direction);
986 			}
987 			SCpnt->result = DID_RESET << 16;
988 			SCpnt->host_scribble = NULL;
989 
990 			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */
991 		}
992 	}
993 
994 	return;
995 }
996 
997 /*
998  *	mptscsih_search_running_cmds - Delete any commands associated
999  *		with the specified target and lun. Function called only
1000  *		when a lun is disable by mid-layer.
1001  *		Do NOT access the referenced scsi_cmnd structure or
1002  *		members. Will cause either a paging or NULL ptr error.
1003  *		(BUT, BUT, BUT, the code does reference it! - mdr)
1004  *      @hd: Pointer to a SCSI HOST structure
1005  *	@vdevice: per device private data
1006  *
1007  *	Returns: None.
1008  *
1009  *	Called from slave_destroy.
1010  */
1011 static void
1012 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
1013 {
1014 	SCSIIORequest_t	*mf = NULL;
1015 	int		 ii;
1016 	int		 max = hd->ioc->req_depth;
1017 	struct scsi_cmnd *sc;
1018 	struct scsi_lun  lun;
1019 
1020 	dsprintk((KERN_INFO MYNAM ": search_running channel %d id %d lun %d max %d\n",
1021 	    vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max));
1022 
1023 	for (ii=0; ii < max; ii++) {
1024 		if ((sc = hd->ScsiLookup[ii]) != NULL) {
1025 
1026 			mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1027 			if (mf == NULL)
1028 				continue;
1029 			int_to_scsilun(vdevice->lun, &lun);
1030 			if ((mf->Bus != vdevice->vtarget->channel) ||
1031 			    (mf->TargetID != vdevice->vtarget->id) ||
1032 			    memcmp(lun.scsi_lun, mf->LUN, 8))
1033 				continue;
1034 			dsprintk(( "search_running: found (sc=%p, mf = %p) "
1035 			    "channel %d id %d, lun %d \n", hd->ScsiLookup[ii],
1036 			    mf, mf->Bus, mf->TargetID, vdevice->lun));
1037 
1038 			/* Cleanup
1039 			 */
1040 			hd->ScsiLookup[ii] = NULL;
1041 			mptscsih_freeChainBuffers(hd->ioc, ii);
1042 			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
1043 			if ((unsigned char *)mf != sc->host_scribble)
1044 				continue;
1045 			if (sc->use_sg) {
1046 				pci_unmap_sg(hd->ioc->pcidev,
1047 				(struct scatterlist *) sc->request_buffer,
1048 					sc->use_sg,
1049 					sc->sc_data_direction);
1050 			} else if (sc->request_bufflen) {
1051 				pci_unmap_single(hd->ioc->pcidev,
1052 					sc->SCp.dma_handle,
1053 					sc->request_bufflen,
1054 					sc->sc_data_direction);
1055 			}
1056 			sc->host_scribble = NULL;
1057 			sc->result = DID_NO_CONNECT << 16;
1058 			sc->scsi_done(sc);
1059 		}
1060 	}
1061 	return;
1062 }
1063 
1064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1065 
1066 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1067 /*
1068  *	mptscsih_report_queue_full - Report QUEUE_FULL status returned
1069  *	from a SCSI target device.
1070  *	@sc: Pointer to scsi_cmnd structure
1071  *	@pScsiReply: Pointer to SCSIIOReply_t
1072  *	@pScsiReq: Pointer to original SCSI request
1073  *
1074  *	This routine periodically reports QUEUE_FULL status returned from a
1075  *	SCSI target device.  It reports this to the console via kernel
1076  *	printk() API call, not more than once every 10 seconds.
1077  */
1078 static void
1079 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1080 {
1081 	long time = jiffies;
1082 	MPT_SCSI_HOST		*hd;
1083 
1084 	if (sc->device == NULL)
1085 		return;
1086 	if (sc->device->host == NULL)
1087 		return;
1088 	if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
1089 		return;
1090 
1091 	if (time - hd->last_queue_full > 10 * HZ) {
1092 		dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1093 				hd->ioc->name, 0, sc->device->id, sc->device->lun));
1094 		hd->last_queue_full = time;
1095 	}
1096 }
1097 
1098 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1099 /*
1100  *	mptscsih_remove - Removed scsi devices
1101  *	@pdev: Pointer to pci_dev structure
1102  *
1103  *
1104  */
1105 void
1106 mptscsih_remove(struct pci_dev *pdev)
1107 {
1108 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
1109 	struct Scsi_Host 	*host = ioc->sh;
1110 	MPT_SCSI_HOST		*hd;
1111 	int sz1;
1112 
1113 	if(!host) {
1114 		mpt_detach(pdev);
1115 		return;
1116 	}
1117 
1118 	scsi_remove_host(host);
1119 
1120 	if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
1121 		return;
1122 
1123 	mptscsih_shutdown(pdev);
1124 
1125 	sz1=0;
1126 
1127 	if (hd->ScsiLookup != NULL) {
1128 		sz1 = hd->ioc->req_depth * sizeof(void *);
1129 		kfree(hd->ScsiLookup);
1130 		hd->ScsiLookup = NULL;
1131 	}
1132 
1133 	dprintk((MYIOC_s_INFO_FMT
1134 	    "Free'd ScsiLookup (%d) memory\n",
1135 	    hd->ioc->name, sz1));
1136 
1137 	kfree(hd->info_kbuf);
1138 
1139 	/* NULL the Scsi_Host pointer
1140 	 */
1141 	hd->ioc->sh = NULL;
1142 
1143 	scsi_host_put(host);
1144 
1145 	mpt_detach(pdev);
1146 
1147 }
1148 
1149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1150 /*
1151  *	mptscsih_shutdown - reboot notifier
1152  *
1153  */
1154 void
1155 mptscsih_shutdown(struct pci_dev *pdev)
1156 {
1157 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
1158 	struct Scsi_Host 	*host = ioc->sh;
1159 	MPT_SCSI_HOST		*hd;
1160 
1161 	if(!host)
1162 		return;
1163 
1164 	hd = (MPT_SCSI_HOST *)host->hostdata;
1165 
1166 }
1167 
1168 #ifdef CONFIG_PM
1169 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1170 /*
1171  *	mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1172  *
1173  *
1174  */
1175 int
1176 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1177 {
1178 	mptscsih_shutdown(pdev);
1179 	return mpt_suspend(pdev,state);
1180 }
1181 
1182 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1183 /*
1184  *	mptscsih_resume - Fusion MPT scsi driver resume routine.
1185  *
1186  *
1187  */
1188 int
1189 mptscsih_resume(struct pci_dev *pdev)
1190 {
1191 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
1192 	struct Scsi_Host 	*host = ioc->sh;
1193 	MPT_SCSI_HOST		*hd;
1194 
1195 	mpt_resume(pdev);
1196 
1197 	if(!host)
1198 		return 0;
1199 
1200 	hd = (MPT_SCSI_HOST *)host->hostdata;
1201 	if(!hd)
1202 		return 0;
1203 
1204 	return 0;
1205 }
1206 
1207 #endif
1208 
1209 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1210 /**
1211  *	mptscsih_info - Return information about MPT adapter
1212  *	@SChost: Pointer to Scsi_Host structure
1213  *
1214  *	(linux scsi_host_template.info routine)
1215  *
1216  *	Returns pointer to buffer where information was written.
1217  */
1218 const char *
1219 mptscsih_info(struct Scsi_Host *SChost)
1220 {
1221 	MPT_SCSI_HOST *h;
1222 	int size = 0;
1223 
1224 	h = (MPT_SCSI_HOST *)SChost->hostdata;
1225 
1226 	if (h) {
1227 		if (h->info_kbuf == NULL)
1228 			if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1229 				return h->info_kbuf;
1230 		h->info_kbuf[0] = '\0';
1231 
1232 		mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1233 		h->info_kbuf[size-1] = '\0';
1234 	}
1235 
1236 	return h->info_kbuf;
1237 }
1238 
1239 struct info_str {
1240 	char *buffer;
1241 	int   length;
1242 	int   offset;
1243 	int   pos;
1244 };
1245 
1246 static void
1247 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1248 {
1249 	if (info->pos + len > info->length)
1250 		len = info->length - info->pos;
1251 
1252 	if (info->pos + len < info->offset) {
1253 		info->pos += len;
1254 		return;
1255 	}
1256 
1257 	if (info->pos < info->offset) {
1258 	        data += (info->offset - info->pos);
1259 	        len  -= (info->offset - info->pos);
1260 	}
1261 
1262 	if (len > 0) {
1263                 memcpy(info->buffer + info->pos, data, len);
1264                 info->pos += len;
1265 	}
1266 }
1267 
1268 static int
1269 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1270 {
1271 	va_list args;
1272 	char buf[81];
1273 	int len;
1274 
1275 	va_start(args, fmt);
1276 	len = vsprintf(buf, fmt, args);
1277 	va_end(args);
1278 
1279 	mptscsih_copy_mem_info(info, buf, len);
1280 	return len;
1281 }
1282 
1283 static int
1284 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1285 {
1286 	struct info_str info;
1287 
1288 	info.buffer	= pbuf;
1289 	info.length	= len;
1290 	info.offset	= offset;
1291 	info.pos	= 0;
1292 
1293 	mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1294 	mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1295 	mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1296 	mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1297 
1298 	return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1299 }
1300 
1301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1302 /**
1303  *	mptscsih_proc_info - Return information about MPT adapter
1304  * 	@host:   scsi host struct
1305  * 	@buffer: if write, user data; if read, buffer for user
1306  *	@start: returns the buffer address
1307  * 	@offset: if write, 0; if read, the current offset into the buffer from
1308  * 		 the previous read.
1309  * 	@length: if write, return length;
1310  *	@func:   write = 1; read = 0
1311  *
1312  *	(linux scsi_host_template.info routine)
1313  */
1314 int
1315 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1316 			int length, int func)
1317 {
1318 	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)host->hostdata;
1319 	MPT_ADAPTER	*ioc = hd->ioc;
1320 	int size = 0;
1321 
1322 	if (func) {
1323 		/*
1324 		 * write is not supported
1325 		 */
1326 	} else {
1327 		if (start)
1328 			*start = buffer;
1329 
1330 		size = mptscsih_host_info(ioc, buffer, offset, length);
1331 	}
1332 
1333 	return size;
1334 }
1335 
1336 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1337 #define ADD_INDEX_LOG(req_ent)	do { } while(0)
1338 
1339 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1340 /**
1341  *	mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1342  *	@SCpnt: Pointer to scsi_cmnd structure
1343  *	@done: Pointer SCSI mid-layer IO completion function
1344  *
1345  *	(linux scsi_host_template.queuecommand routine)
1346  *	This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
1347  *	from a linux scsi_cmnd request and send it to the IOC.
1348  *
1349  *	Returns 0. (rtn value discarded by linux scsi mid-layer)
1350  */
1351 int
1352 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1353 {
1354 	MPT_SCSI_HOST		*hd;
1355 	MPT_FRAME_HDR		*mf;
1356 	SCSIIORequest_t		*pScsiReq;
1357 	VirtDevice		*vdev = SCpnt->device->hostdata;
1358 	int	 lun;
1359 	u32	 datalen;
1360 	u32	 scsictl;
1361 	u32	 scsidir;
1362 	u32	 cmd_len;
1363 	int	 my_idx;
1364 	int	 ii;
1365 
1366 	hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1367 	lun = SCpnt->device->lun;
1368 	SCpnt->scsi_done = done;
1369 
1370 	dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1371 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1372 
1373 	if (hd->resetPending) {
1374 		dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1375 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1376 		return SCSI_MLQUEUE_HOST_BUSY;
1377 	}
1378 
1379 	/*
1380 	 *  Put together a MPT SCSI request...
1381 	 */
1382 	if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1383 		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1384 				hd->ioc->name));
1385 		return SCSI_MLQUEUE_HOST_BUSY;
1386 	}
1387 
1388 	pScsiReq = (SCSIIORequest_t *) mf;
1389 
1390 	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1391 
1392 	ADD_INDEX_LOG(my_idx);
1393 
1394 	/*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1395 	 *    Seems we may receive a buffer (datalen>0) even when there
1396 	 *    will be no data transfer!  GRRRRR...
1397 	 */
1398 	if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1399 		datalen = SCpnt->request_bufflen;
1400 		scsidir = MPI_SCSIIO_CONTROL_READ;	/* DATA IN  (host<--ioc<--dev) */
1401 	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1402 		datalen = SCpnt->request_bufflen;
1403 		scsidir = MPI_SCSIIO_CONTROL_WRITE;	/* DATA OUT (host-->ioc-->dev) */
1404 	} else {
1405 		datalen = 0;
1406 		scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1407 	}
1408 
1409 	/* Default to untagged. Once a target structure has been allocated,
1410 	 * use the Inquiry data to determine if device supports tagged.
1411 	 */
1412 	if (vdev
1413 	    && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1414 	    && (SCpnt->device->tagged_supported)) {
1415 		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1416 	} else {
1417 		scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1418 	}
1419 
1420 	/* Use the above information to set up the message frame
1421 	 */
1422 	pScsiReq->TargetID = (u8) vdev->vtarget->id;
1423 	pScsiReq->Bus = vdev->vtarget->channel;
1424 	pScsiReq->ChainOffset = 0;
1425 	if (vdev->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
1426 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1427 	else
1428 		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1429 	pScsiReq->CDBLength = SCpnt->cmd_len;
1430 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1431 	pScsiReq->Reserved = 0;
1432 	pScsiReq->MsgFlags = mpt_msg_flags();
1433 	int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1434 	pScsiReq->Control = cpu_to_le32(scsictl);
1435 
1436 	/*
1437 	 *  Write SCSI CDB into the message
1438 	 */
1439 	cmd_len = SCpnt->cmd_len;
1440 	for (ii=0; ii < cmd_len; ii++)
1441 		pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1442 
1443 	for (ii=cmd_len; ii < 16; ii++)
1444 		pScsiReq->CDB[ii] = 0;
1445 
1446 	/* DataLength */
1447 	pScsiReq->DataLength = cpu_to_le32(datalen);
1448 
1449 	/* SenseBuffer low address */
1450 	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1451 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1452 
1453 	/* Now add the SG list
1454 	 * Always have a SGE even if null length.
1455 	 */
1456 	if (datalen == 0) {
1457 		/* Add a NULL SGE */
1458 		mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1459 			(dma_addr_t) -1);
1460 	} else {
1461 		/* Add a 32 or 64 bit SGE */
1462 		if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1463 			goto fail;
1464 	}
1465 
1466 	SCpnt->host_scribble = (unsigned char *)mf;
1467 	hd->ScsiLookup[my_idx] = SCpnt;
1468 
1469 	mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1470 	dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1471 			hd->ioc->name, SCpnt, mf, my_idx));
1472 	DBG_DUMP_REQUEST_FRAME(mf)
1473 	return 0;
1474 
1475  fail:
1476 	hd->ScsiLookup[my_idx] = NULL;
1477 	mptscsih_freeChainBuffers(hd->ioc, my_idx);
1478 	mpt_free_msg_frame(hd->ioc, mf);
1479 	return SCSI_MLQUEUE_HOST_BUSY;
1480 }
1481 
1482 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1483 /*
1484  *	mptscsih_freeChainBuffers - Function to free chain buffers associated
1485  *	with a SCSI IO request
1486  *	@hd: Pointer to the MPT_SCSI_HOST instance
1487  *	@req_idx: Index of the SCSI IO request frame.
1488  *
1489  *	Called if SG chain buffer allocation fails and mptscsih callbacks.
1490  *	No return.
1491  */
1492 static void
1493 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1494 {
1495 	MPT_FRAME_HDR *chain;
1496 	unsigned long flags;
1497 	int chain_idx;
1498 	int next;
1499 
1500 	/* Get the first chain index and reset
1501 	 * tracker state.
1502 	 */
1503 	chain_idx = ioc->ReqToChain[req_idx];
1504 	ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1505 
1506 	while (chain_idx != MPT_HOST_NO_CHAIN) {
1507 
1508 		/* Save the next chain buffer index */
1509 		next = ioc->ChainToChain[chain_idx];
1510 
1511 		/* Free this chain buffer and reset
1512 		 * tracker
1513 		 */
1514 		ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1515 
1516 		chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1517 					+ (chain_idx * ioc->req_sz));
1518 
1519 		spin_lock_irqsave(&ioc->FreeQlock, flags);
1520 		list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1521 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1522 
1523 		dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1524 				ioc->name, chain_idx));
1525 
1526 		/* handle next */
1527 		chain_idx = next;
1528 	}
1529 	return;
1530 }
1531 
1532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1533 /*
1534  *	Reset Handling
1535  */
1536 
1537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1538 /**
1539  *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
1540  *	Fall through to mpt_HardResetHandler if: not operational, too many
1541  *	failed TM requests or handshake failure.
1542  *
1543  *	@ioc: Pointer to MPT_ADAPTER structure
1544  *	@type: Task Management type
1545  *	@id: Logical Target ID for reset (if appropriate)
1546  *	@lun: Logical Unit for reset (if appropriate)
1547  *	@ctx2abort: Context for the task to be aborted (if appropriate)
1548  *
1549  *	Remark: Currently invoked from a non-interrupt thread (_bh).
1550  *
1551  *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1552  *	will be active.
1553  *
1554  *	Returns 0 for SUCCESS, or FAILED.
1555  **/
1556 int
1557 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1558 {
1559 	MPT_ADAPTER	*ioc;
1560 	int		 rc = -1;
1561 	u32		 ioc_raw_state;
1562 	unsigned long	 flags;
1563 
1564 	ioc = hd->ioc;
1565 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1566 
1567 	// SJR - CHECKME - Can we avoid this here?
1568 	// (mpt_HardResetHandler has this check...)
1569 	spin_lock_irqsave(&ioc->diagLock, flags);
1570 	if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1571 		spin_unlock_irqrestore(&ioc->diagLock, flags);
1572 		return FAILED;
1573 	}
1574 	spin_unlock_irqrestore(&ioc->diagLock, flags);
1575 
1576 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
1577 	 *  If we time out and not bus reset, then we return a FAILED status
1578 	 *  to the caller.
1579 	 *  The call to mptscsih_tm_pending_wait() will set the pending flag
1580 	 *  if we are
1581 	 *  successful. Otherwise, reload the FW.
1582 	 */
1583 	if (mptscsih_tm_pending_wait(hd) == FAILED) {
1584 		if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1585 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1586 			   "Timed out waiting for last TM (%d) to complete! \n",
1587 			   hd->ioc->name, hd->tmPending));
1588 			return FAILED;
1589 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1590 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
1591 				"reset: Timed out waiting for last TM (%d) "
1592 				"to complete! \n", hd->ioc->name,
1593 				hd->tmPending));
1594 			return FAILED;
1595 		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1596 			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1597 			   "Timed out waiting for last TM (%d) to complete! \n",
1598 			   hd->ioc->name, hd->tmPending));
1599 			return FAILED;
1600 		}
1601 	} else {
1602 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1603 		hd->tmPending |=  (1 << type);
1604 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1605 	}
1606 
1607 	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1608 
1609 	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1610 		printk(MYIOC_s_WARN_FMT
1611 			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
1612 			ioc->name, type, ioc_raw_state);
1613 		printk(KERN_WARNING " Issuing HardReset!!\n");
1614 		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1615 			printk((KERN_WARNING "TMHandler: HardReset "
1616 				"FAILED!!\n"));
1617 		return FAILED;
1618 	}
1619 
1620 	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
1621 		printk(MYIOC_s_WARN_FMT
1622 			"TM Handler for type=%x: ioc_state: "
1623 			"DOORBELL_ACTIVE (0x%x)!\n",
1624 			ioc->name, type, ioc_raw_state);
1625 		return FAILED;
1626 	}
1627 
1628 	/* Isse the Task Mgmt request.
1629 	 */
1630 	if (hd->hard_resets < -1)
1631 		hd->hard_resets++;
1632 
1633 	rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
1634 	    ctx2abort, timeout);
1635 	if (rc)
1636 		printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
1637 		       hd->ioc->name);
1638 	else
1639 		dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
1640 			   hd->ioc->name));
1641 
1642 	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1643 
1644 	return rc;
1645 }
1646 
1647 
1648 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1649 /**
1650  *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
1651  *	@hd: Pointer to MPT_SCSI_HOST structure
1652  *	@type: Task Management type
1653  *	@id: Logical Target ID for reset (if appropriate)
1654  *	@lun: Logical Unit for reset (if appropriate)
1655  *	@ctx2abort: Context for the task to be aborted (if appropriate)
1656  *
1657  *	Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1658  *	or a non-interrupt thread.  In the former, must not call schedule().
1659  *
1660  *	Not all fields are meaningfull for all task types.
1661  *
1662  *	Returns 0 for SUCCESS, or FAILED.
1663  *
1664  **/
1665 static int
1666 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
1667 {
1668 	MPT_FRAME_HDR	*mf;
1669 	SCSITaskMgmt_t	*pScsiTm;
1670 	int		 ii;
1671 	int		 retval;
1672 
1673 	/* Return Fail to calling function if no message frames available.
1674 	 */
1675 	if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1676 		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1677 				hd->ioc->name));
1678 		return FAILED;
1679 	}
1680 	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1681 			hd->ioc->name, mf));
1682 
1683 	/* Format the Request
1684 	 */
1685 	pScsiTm = (SCSITaskMgmt_t *) mf;
1686 	pScsiTm->TargetID = id;
1687 	pScsiTm->Bus = channel;
1688 	pScsiTm->ChainOffset = 0;
1689 	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1690 
1691 	pScsiTm->Reserved = 0;
1692 	pScsiTm->TaskType = type;
1693 	pScsiTm->Reserved1 = 0;
1694 	pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1695                     ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1696 
1697 	int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1698 
1699 	for (ii=0; ii < 7; ii++)
1700 		pScsiTm->Reserved2[ii] = 0;
1701 
1702 	pScsiTm->TaskMsgContext = ctx2abort;
1703 
1704 	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
1705 		"type=%d\n", hd->ioc->name, ctx2abort, type));
1706 
1707 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1708 
1709 	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1710 		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
1711 		dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
1712 			" (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
1713 			hd->ioc, mf, retval));
1714 		goto fail_out;
1715 	}
1716 
1717 	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1718 		dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
1719 			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1720 			hd->ioc, mf));
1721 		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1722 			 hd->ioc->name));
1723 		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1724 		dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
1725 			 hd->ioc->name, retval));
1726 		goto fail_out;
1727 	}
1728 
1729 	/*
1730 	 * Handle success case, see if theres a non-zero ioc_status.
1731 	 */
1732 	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
1733 	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
1734 	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
1735 		retval = 0;
1736 	else
1737 		retval = FAILED;
1738 
1739 	return retval;
1740 
1741  fail_out:
1742 
1743 	/*
1744 	 * Free task managment mf, and corresponding tm flags
1745 	 */
1746 	mpt_free_msg_frame(hd->ioc, mf);
1747 	hd->tmPending = 0;
1748 	hd->tmState = TM_STATE_NONE;
1749 	return FAILED;
1750 }
1751 
1752 static int
1753 mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1754 {
1755 	switch (ioc->bus_type) {
1756 	case FC:
1757 		return 40;
1758 	case SAS:
1759 		return 10;
1760 	case SPI:
1761 	default:
1762 		return 2;
1763 	}
1764 }
1765 
1766 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1767 /**
1768  *	mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1769  *	@SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1770  *
1771  *	(linux scsi_host_template.eh_abort_handler routine)
1772  *
1773  *	Returns SUCCESS or FAILED.
1774  **/
1775 int
1776 mptscsih_abort(struct scsi_cmnd * SCpnt)
1777 {
1778 	MPT_SCSI_HOST	*hd;
1779 	MPT_FRAME_HDR	*mf;
1780 	u32		 ctx2abort;
1781 	int		 scpnt_idx;
1782 	int		 retval;
1783 	VirtDevice	 *vdev;
1784 	ulong	 	 sn = SCpnt->serial_number;
1785 
1786 	/* If we can't locate our host adapter structure, return FAILED status.
1787 	 */
1788 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1789 		SCpnt->result = DID_RESET << 16;
1790 		SCpnt->scsi_done(SCpnt);
1791 		dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: "
1792 			   "Can't locate host! (sc=%p)\n",
1793 			   SCpnt));
1794 		return FAILED;
1795 	}
1796 
1797 	/* Find this command
1798 	 */
1799 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1800 		/* Cmd not found in ScsiLookup.
1801 		 * Do OS callback.
1802 		 */
1803 		SCpnt->result = DID_RESET << 16;
1804 		dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: "
1805 			   "Command not in the active list! (sc=%p)\n",
1806 			   hd->ioc->name, SCpnt));
1807 		return SUCCESS;
1808 	}
1809 
1810 	if (hd->resetPending)
1811 		return FAILED;
1812 
1813 	if (hd->timeouts < -1)
1814 		hd->timeouts++;
1815 
1816 	printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n",
1817 	       hd->ioc->name, SCpnt);
1818 	scsi_print_command(SCpnt);
1819 
1820 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
1821 	 * (the IO to be ABORT'd)
1822 	 *
1823 	 * NOTE: Since we do not byteswap MsgContext, we do not
1824 	 *	 swap it here either.  It is an opaque cookie to
1825 	 *	 the controller, so it does not matter. -DaveM
1826 	 */
1827 	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1828 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1829 
1830 	hd->abortSCpnt = SCpnt;
1831 
1832 	vdev = SCpnt->device->hostdata;
1833 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1834 		vdev->vtarget->channel, vdev->vtarget->id, vdev->lun,
1835 		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
1836 
1837 	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
1838 	    SCpnt->serial_number == sn)
1839 		retval = FAILED;
1840 
1841 	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
1842 		hd->ioc->name,
1843 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1844 
1845 	if (retval == 0)
1846 		return SUCCESS;
1847 	else
1848 		return FAILED;
1849 }
1850 
1851 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1852 /**
1853  *	mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
1854  *	@SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1855  *
1856  *	(linux scsi_host_template.eh_dev_reset_handler routine)
1857  *
1858  *	Returns SUCCESS or FAILED.
1859  **/
1860 int
1861 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1862 {
1863 	MPT_SCSI_HOST	*hd;
1864 	int		 retval;
1865 	VirtDevice	 *vdev;
1866 
1867 	/* If we can't locate our host adapter structure, return FAILED status.
1868 	 */
1869 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1870 		dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: "
1871 			   "Can't locate host! (sc=%p)\n",
1872 			   SCpnt));
1873 		return FAILED;
1874 	}
1875 
1876 	if (hd->resetPending)
1877 		return FAILED;
1878 
1879 	printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n",
1880 	       hd->ioc->name, SCpnt);
1881 	scsi_print_command(SCpnt);
1882 
1883 	vdev = SCpnt->device->hostdata;
1884 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1885 		vdev->vtarget->channel, vdev->vtarget->id,
1886 		0, 0, mptscsih_get_tm_timeout(hd->ioc));
1887 
1888 	printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
1889 		hd->ioc->name,
1890 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1891 
1892 	if (retval == 0)
1893 		return SUCCESS;
1894 	else
1895 		return FAILED;
1896 }
1897 
1898 
1899 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1900 /**
1901  *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
1902  *	@SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1903  *
1904  *	(linux scsi_host_template.eh_bus_reset_handler routine)
1905  *
1906  *	Returns SUCCESS or FAILED.
1907  **/
1908 int
1909 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1910 {
1911 	MPT_SCSI_HOST	*hd;
1912 	int		 retval;
1913 	VirtDevice	 *vdev;
1914 
1915 	/* If we can't locate our host adapter structure, return FAILED status.
1916 	 */
1917 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1918 		dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: "
1919 			   "Can't locate host! (sc=%p)\n",
1920 			   SCpnt ) );
1921 		return FAILED;
1922 	}
1923 
1924 	printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n",
1925 	       hd->ioc->name, SCpnt);
1926 	scsi_print_command(SCpnt);
1927 
1928 	if (hd->timeouts < -1)
1929 		hd->timeouts++;
1930 
1931 	vdev = SCpnt->device->hostdata;
1932 	retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1933 		vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(hd->ioc));
1934 
1935 	printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
1936 		hd->ioc->name,
1937 		((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1938 
1939 	if (retval == 0)
1940 		return SUCCESS;
1941 	else
1942 		return FAILED;
1943 }
1944 
1945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1946 /**
1947  *	mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1948  *	@SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1949  *
1950  *	(linux scsi_host_template.eh_host_reset_handler routine)
1951  *
1952  *	Returns SUCCESS or FAILED.
1953  */
1954 int
1955 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1956 {
1957 	MPT_SCSI_HOST *  hd;
1958 	int              status = SUCCESS;
1959 
1960 	/*  If we can't locate the host to reset, then we failed. */
1961 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1962 		dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1963 			     "Can't locate host! (sc=%p)\n",
1964 			     SCpnt ) );
1965 		return FAILED;
1966 	}
1967 
1968 	printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1969 	       hd->ioc->name, SCpnt);
1970 
1971 	/*  If our attempts to reset the host failed, then return a failed
1972 	 *  status.  The host will be taken off line by the SCSI mid-layer.
1973 	 */
1974 	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1975 		status = FAILED;
1976 	} else {
1977 		/*  Make sure TM pending is cleared and TM state is set to
1978 		 *  NONE.
1979 		 */
1980 		hd->tmPending = 0;
1981 		hd->tmState = TM_STATE_NONE;
1982 	}
1983 
1984 	dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1985 		     "Status = %s\n",
1986 		     (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1987 
1988 	return status;
1989 }
1990 
1991 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1992 /**
1993  *	mptscsih_tm_pending_wait - wait for pending task management request to complete
1994  *	@hd: Pointer to MPT host structure.
1995  *
1996  *	Returns {SUCCESS,FAILED}.
1997  */
1998 static int
1999 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
2000 {
2001 	unsigned long  flags;
2002 	int            loop_count = 4 * 10;  /* Wait 10 seconds */
2003 	int            status = FAILED;
2004 
2005 	do {
2006 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2007 		if (hd->tmState == TM_STATE_NONE) {
2008 			hd->tmState = TM_STATE_IN_PROGRESS;
2009 			hd->tmPending = 1;
2010 			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2011 			status = SUCCESS;
2012 			break;
2013 		}
2014 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2015 		msleep(250);
2016 	} while (--loop_count);
2017 
2018 	return status;
2019 }
2020 
2021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2022 /**
2023  *	mptscsih_tm_wait_for_completion - wait for completion of TM task
2024  *	@hd: Pointer to MPT host structure.
2025  *
2026  *	Returns {SUCCESS,FAILED}.
2027  */
2028 static int
2029 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
2030 {
2031 	unsigned long  flags;
2032 	int            loop_count = 4 * timeout;
2033 	int            status = FAILED;
2034 
2035 	do {
2036 		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2037 		if(hd->tmPending == 0) {
2038 			status = SUCCESS;
2039  			spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2040 			break;
2041 		}
2042 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2043 		msleep(250);
2044 	} while (--loop_count);
2045 
2046 	return status;
2047 }
2048 
2049 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2050 static void
2051 mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2052 {
2053 	char *desc;
2054 
2055 	switch (response_code) {
2056 	case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2057 		desc = "The task completed.";
2058 		break;
2059 	case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2060 		desc = "The IOC received an invalid frame status.";
2061 		break;
2062 	case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2063 		desc = "The task type is not supported.";
2064 		break;
2065 	case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2066 		desc = "The requested task failed.";
2067 		break;
2068 	case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2069 		desc = "The task completed successfully.";
2070 		break;
2071 	case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2072 		desc = "The LUN request is invalid.";
2073 		break;
2074 	case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2075 		desc = "The task is in the IOC queue and has not been sent to target.";
2076 		break;
2077 	default:
2078 		desc = "unknown";
2079 		break;
2080 	}
2081 	printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2082 		ioc->name, response_code, desc);
2083 }
2084 
2085 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2086 /**
2087  *	mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2088  *	@ioc: Pointer to MPT_ADAPTER structure
2089  *	@mf: Pointer to SCSI task mgmt request frame
2090  *	@mr: Pointer to SCSI task mgmt reply frame
2091  *
2092  *	This routine is called from mptbase.c::mpt_interrupt() at the completion
2093  *	of any SCSI task management request.
2094  *	This routine is registered with the MPT (base) driver at driver
2095  *	load/init time via the mpt_register() API call.
2096  *
2097  *	Returns 1 indicating alloc'd request frame ptr should be freed.
2098  **/
2099 int
2100 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2101 {
2102 	SCSITaskMgmtReply_t	*pScsiTmReply;
2103 	SCSITaskMgmt_t		*pScsiTmReq;
2104 	MPT_SCSI_HOST		*hd;
2105 	unsigned long		 flags;
2106 	u16			 iocstatus;
2107 	u8			 tmType;
2108 	u32			 termination_count;
2109 
2110 	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2111 	    ioc->name, mf, mr));
2112 	if (!ioc->sh) {
2113 		dtmprintk((MYIOC_s_WARN_FMT
2114 		    "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
2115 		return 1;
2116 	}
2117 
2118 	if (mr == NULL) {
2119 		dtmprintk((MYIOC_s_WARN_FMT
2120 		    "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
2121 		return 1;
2122 	}
2123 
2124 	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2125 	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2126 	pScsiTmReq = (SCSITaskMgmt_t*)mf;
2127 	tmType = pScsiTmReq->TaskType;
2128 	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2129 	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
2130 
2131 	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
2132 	    pScsiTmReply->ResponseCode)
2133 		mptscsih_taskmgmt_response_code(ioc,
2134 		    pScsiTmReply->ResponseCode);
2135 	DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2136 
2137 #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
2138 	printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
2139 	    "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
2140 	    "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
2141 	    pScsiTmReply->TargetID, pScsiTmReq->TaskType,
2142 	    le16_to_cpu(pScsiTmReply->IOCStatus),
2143 	    le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
2144 	    le32_to_cpu(pScsiTmReply->TerminationCount));
2145 #endif
2146 	if (!iocstatus) {
2147 		dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2148 			hd->abortSCpnt = NULL;
2149 		goto out;
2150 	}
2151 
2152 	/* Error?  (anything non-zero?) */
2153 
2154 	/* clear flags and continue.
2155 	 */
2156 	switch (tmType) {
2157 
2158 	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2159 		if (termination_count == 1)
2160 			iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
2161 		hd->abortSCpnt = NULL;
2162 		break;
2163 
2164 	case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:
2165 
2166 		/* If an internal command is present
2167 		 * or the TM failed - reload the FW.
2168 		 * FC FW may respond FAILED to an ABORT
2169 		 */
2170 		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
2171 		    hd->cmdPtr)
2172 			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
2173 				printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
2174 		break;
2175 
2176 	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2177 	default:
2178 		break;
2179 	}
2180 
2181  out:
2182 	spin_lock_irqsave(&ioc->FreeQlock, flags);
2183 	hd->tmPending = 0;
2184 	hd->tmState = TM_STATE_NONE;
2185 	hd->tm_iocstatus = iocstatus;
2186 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2187 
2188 	return 1;
2189 }
2190 
2191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2192 /*
2193  *	This is anyones guess quite frankly.
2194  */
2195 int
2196 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2197 		sector_t capacity, int geom[])
2198 {
2199 	int		heads;
2200 	int		sectors;
2201 	sector_t	cylinders;
2202 	ulong 		dummy;
2203 
2204 	heads = 64;
2205 	sectors = 32;
2206 
2207 	dummy = heads * sectors;
2208 	cylinders = capacity;
2209 	sector_div(cylinders,dummy);
2210 
2211 	/*
2212 	 * Handle extended translation size for logical drives
2213 	 * > 1Gb
2214 	 */
2215 	if ((ulong)capacity >= 0x200000) {
2216 		heads = 255;
2217 		sectors = 63;
2218 		dummy = heads * sectors;
2219 		cylinders = capacity;
2220 		sector_div(cylinders,dummy);
2221 	}
2222 
2223 	/* return result */
2224 	geom[0] = heads;
2225 	geom[1] = sectors;
2226 	geom[2] = cylinders;
2227 
2228 	dprintk((KERN_NOTICE
2229 		": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2230 		sdev->id, sdev->lun, sdev->channel, (int)cylinders, heads, sectors));
2231 
2232 	return 0;
2233 }
2234 
2235 /* Search IOC page 3 to determine if this is hidden physical disk
2236  *
2237  */
2238 int
2239 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2240 {
2241 	struct inactive_raid_component_info *component_info;
2242 	int i;
2243 	int rc = 0;
2244 
2245 	if (!ioc->raid_data.pIocPg3)
2246 		goto out;
2247 	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2248 		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2249 		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2250 			rc = 1;
2251 			goto out;
2252 		}
2253 	}
2254 
2255 	/*
2256 	 * Check inactive list for matching phys disks
2257 	 */
2258 	if (list_empty(&ioc->raid_data.inactive_list))
2259 		goto out;
2260 
2261 	down(&ioc->raid_data.inactive_list_mutex);
2262 	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2263 	    list) {
2264 		if ((component_info->d.PhysDiskID == id) &&
2265 		    (component_info->d.PhysDiskBus == channel))
2266 			rc = 1;
2267 	}
2268 	up(&ioc->raid_data.inactive_list_mutex);
2269 
2270  out:
2271 	return rc;
2272 }
2273 EXPORT_SYMBOL(mptscsih_is_phys_disk);
2274 
2275 u8
2276 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2277 {
2278 	struct inactive_raid_component_info *component_info;
2279 	int i;
2280 	int rc = -ENXIO;
2281 
2282 	if (!ioc->raid_data.pIocPg3)
2283 		goto out;
2284 	for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2285 		if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2286 		    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2287 			rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2288 			goto out;
2289 		}
2290 	}
2291 
2292 	/*
2293 	 * Check inactive list for matching phys disks
2294 	 */
2295 	if (list_empty(&ioc->raid_data.inactive_list))
2296 		goto out;
2297 
2298 	down(&ioc->raid_data.inactive_list_mutex);
2299 	list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2300 	    list) {
2301 		if ((component_info->d.PhysDiskID == id) &&
2302 		    (component_info->d.PhysDiskBus == channel))
2303 			rc = component_info->d.PhysDiskNum;
2304 	}
2305 	up(&ioc->raid_data.inactive_list_mutex);
2306 
2307  out:
2308 	return rc;
2309 }
2310 EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2311 
2312 /*
2313  *	OS entry point to allow for host driver to free allocated memory
2314  *	Called if no device present or device being unloaded
2315  */
2316 void
2317 mptscsih_slave_destroy(struct scsi_device *sdev)
2318 {
2319 	struct Scsi_Host	*host = sdev->host;
2320 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)host->hostdata;
2321 	VirtTarget		*vtarget;
2322 	VirtDevice		*vdevice;
2323 	struct scsi_target 	*starget;
2324 
2325 	starget = scsi_target(sdev);
2326 	vtarget = starget->hostdata;
2327 	vdevice = sdev->hostdata;
2328 
2329 	mptscsih_search_running_cmds(hd, vdevice);
2330 	vtarget->num_luns--;
2331 	mptscsih_synchronize_cache(hd, vdevice);
2332 	kfree(vdevice);
2333 	sdev->hostdata = NULL;
2334 }
2335 
2336 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2337 /*
2338  *	mptscsih_change_queue_depth - This function will set a devices queue depth
2339  *	@sdev: per scsi_device pointer
2340  *	@qdepth: requested queue depth
2341  *
2342  *	Adding support for new 'change_queue_depth' api.
2343 */
2344 int
2345 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2346 {
2347 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2348 	VirtTarget 		*vtarget;
2349 	struct scsi_target 	*starget;
2350 	int			max_depth;
2351 	int			tagged;
2352 
2353 	starget = scsi_target(sdev);
2354 	vtarget = starget->hostdata;
2355 
2356 	if (hd->ioc->bus_type == SPI) {
2357 		if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2358 			max_depth = 1;
2359 		else if (sdev->type == TYPE_DISK &&
2360 			 vtarget->minSyncFactor <= MPT_ULTRA160)
2361 			max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2362 		else
2363 			max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2364 	} else
2365 		max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2366 
2367 	if (qdepth > max_depth)
2368 		qdepth = max_depth;
2369 	if (qdepth == 1)
2370 		tagged = 0;
2371 	else
2372 		tagged = MSG_SIMPLE_TAG;
2373 
2374 	scsi_adjust_queue_depth(sdev, tagged, qdepth);
2375 	return sdev->queue_depth;
2376 }
2377 
2378 /*
2379  *	OS entry point to adjust the queue_depths on a per-device basis.
2380  *	Called once per device the bus scan. Use it to force the queue_depth
2381  *	member to 1 if a device does not support Q tags.
2382  *	Return non-zero if fails.
2383  */
2384 int
2385 mptscsih_slave_configure(struct scsi_device *sdev)
2386 {
2387 	struct Scsi_Host	*sh = sdev->host;
2388 	VirtTarget		*vtarget;
2389 	VirtDevice		*vdevice;
2390 	struct scsi_target 	*starget;
2391 	MPT_SCSI_HOST		*hd = (MPT_SCSI_HOST *)sh->hostdata;
2392 
2393 	starget = scsi_target(sdev);
2394 	vtarget = starget->hostdata;
2395 	vdevice = sdev->hostdata;
2396 
2397 	dsprintk((MYIOC_s_INFO_FMT
2398 		"device @ %p, channel=%d, id=%d, lun=%d\n",
2399 		hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2400 	if (hd->ioc->bus_type == SPI)
2401 		dsprintk((MYIOC_s_INFO_FMT
2402 		    "sdtr %d wdtr %d ppr %d inq length=%d\n",
2403 		    hd->ioc->name, sdev->sdtr, sdev->wdtr,
2404 		    sdev->ppr, sdev->inquiry_len));
2405 
2406 	if (sdev->id > sh->max_id) {
2407 		/* error case, should never happen */
2408 		scsi_adjust_queue_depth(sdev, 0, 1);
2409 		goto slave_configure_exit;
2410 	}
2411 
2412 	vdevice->configured_lun = 1;
2413 	mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2414 
2415 	dsprintk((MYIOC_s_INFO_FMT
2416 		"Queue depth=%d, tflags=%x\n",
2417 		hd->ioc->name, sdev->queue_depth, vtarget->tflags));
2418 
2419 	if (hd->ioc->bus_type == SPI)
2420 		dsprintk((MYIOC_s_INFO_FMT
2421 		    "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2422 		    hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2423 		    vtarget->minSyncFactor));
2424 
2425 slave_configure_exit:
2426 
2427 	dsprintk((MYIOC_s_INFO_FMT
2428 		"tagged %d, simple %d, ordered %d\n",
2429 		hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
2430 		sdev->ordered_tags));
2431 
2432 	return 0;
2433 }
2434 
2435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2436 /*
2437  *  Private routines...
2438  */
2439 
2440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2441 /* Utility function to copy sense data from the scsi_cmnd buffer
2442  * to the FC and SCSI target structures.
2443  *
2444  */
2445 static void
2446 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2447 {
2448 	VirtDevice	*vdev;
2449 	SCSIIORequest_t	*pReq;
2450 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2451 
2452 	/* Get target structure
2453 	 */
2454 	pReq = (SCSIIORequest_t *) mf;
2455 	vdev = sc->device->hostdata;
2456 
2457 	if (sense_count) {
2458 		u8 *sense_data;
2459 		int req_index;
2460 
2461 		/* Copy the sense received into the scsi command block. */
2462 		req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2463 		sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2464 		memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2465 
2466 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
2467 		 */
2468 		if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2469 			if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
2470 				int idx;
2471 				MPT_ADAPTER *ioc = hd->ioc;
2472 
2473 				idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2474 				ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2475 				ioc->events[idx].eventContext = ioc->eventContext;
2476 
2477 				ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2478 					(MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2479 					(sc->device->channel << 8) || sc->device->id;
2480 
2481 				ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2482 
2483 				ioc->eventContext++;
2484 				if (hd->ioc->pcidev->vendor ==
2485 				    PCI_VENDOR_ID_IBM) {
2486 					mptscsih_issue_sep_command(hd->ioc,
2487 					    vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2488 					vdev->vtarget->tflags |=
2489 					    MPT_TARGET_FLAGS_LED_ON;
2490 				}
2491 			}
2492 		}
2493 	} else {
2494 		dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2495 				hd->ioc->name));
2496 	}
2497 }
2498 
2499 static int
2500 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2501 {
2502 	MPT_SCSI_HOST *hd;
2503 	int i;
2504 
2505 	hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2506 
2507 	for (i = 0; i < hd->ioc->req_depth; i++) {
2508 		if (hd->ScsiLookup[i] == sc) {
2509 			return i;
2510 		}
2511 	}
2512 
2513 	return -1;
2514 }
2515 
2516 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2517 int
2518 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2519 {
2520 	MPT_SCSI_HOST	*hd;
2521 	unsigned long	 flags;
2522 	int 		ii;
2523 
2524 	dtmprintk((KERN_WARNING MYNAM
2525 			": IOC %s_reset routed to SCSI host driver!\n",
2526 			reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2527 			reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2528 
2529 	/* If a FW reload request arrives after base installed but
2530 	 * before all scsi hosts have been attached, then an alt_ioc
2531 	 * may have a NULL sh pointer.
2532 	 */
2533 	if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2534 		return 0;
2535 	else
2536 		hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2537 
2538 	if (reset_phase == MPT_IOC_SETUP_RESET) {
2539 		dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2540 
2541 		/* Clean Up:
2542 		 * 1. Set Hard Reset Pending Flag
2543 		 * All new commands go to doneQ
2544 		 */
2545 		hd->resetPending = 1;
2546 
2547 	} else if (reset_phase == MPT_IOC_PRE_RESET) {
2548 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2549 
2550 		/* 2. Flush running commands
2551 		 *	Clean ScsiLookup (and associated memory)
2552 		 *	AND clean mytaskQ
2553 		 */
2554 
2555 		/* 2b. Reply to OS all known outstanding I/O commands.
2556 		 */
2557 		mptscsih_flush_running_cmds(hd);
2558 
2559 		/* 2c. If there was an internal command that
2560 		 * has not completed, configuration or io request,
2561 		 * free these resources.
2562 		 */
2563 		if (hd->cmdPtr) {
2564 			del_timer(&hd->timer);
2565 			mpt_free_msg_frame(ioc, hd->cmdPtr);
2566 		}
2567 
2568 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2569 
2570 	} else {
2571 		dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2572 
2573 		/* Once a FW reload begins, all new OS commands are
2574 		 * redirected to the doneQ w/ a reset status.
2575 		 * Init all control structures.
2576 		 */
2577 
2578 		/* ScsiLookup initialization
2579 		 */
2580 		for (ii=0; ii < hd->ioc->req_depth; ii++)
2581 			hd->ScsiLookup[ii] = NULL;
2582 
2583 		/* 2. Chain Buffer initialization
2584 		 */
2585 
2586 		/* 4. Renegotiate to all devices, if SPI
2587 		 */
2588 
2589 		/* 5. Enable new commands to be posted
2590 		 */
2591 		spin_lock_irqsave(&ioc->FreeQlock, flags);
2592 		hd->tmPending = 0;
2593 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2594 		hd->resetPending = 0;
2595 		hd->tmState = TM_STATE_NONE;
2596 
2597 		/* 6. If there was an internal command,
2598 		 * wake this process up.
2599 		 */
2600 		if (hd->cmdPtr) {
2601 			/*
2602 			 * Wake up the original calling thread
2603 			 */
2604 			hd->pLocal = &hd->localReply;
2605 			hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2606 			hd->scandv_wait_done = 1;
2607 			wake_up(&hd->scandv_waitq);
2608 			hd->cmdPtr = NULL;
2609 		}
2610 
2611 		dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2612 
2613 	}
2614 
2615 	return 1;		/* currently means nothing really */
2616 }
2617 
2618 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2619 int
2620 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2621 {
2622 	MPT_SCSI_HOST *hd;
2623 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2624 
2625 	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2626 			ioc->name, event));
2627 
2628 	if (ioc->sh == NULL ||
2629 		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
2630 		return 1;
2631 
2632 	switch (event) {
2633 	case MPI_EVENT_UNIT_ATTENTION:			/* 03 */
2634 		/* FIXME! */
2635 		break;
2636 	case MPI_EVENT_IOC_BUS_RESET:			/* 04 */
2637 	case MPI_EVENT_EXT_BUS_RESET:			/* 05 */
2638 		if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
2639 			hd->soft_resets++;
2640 		break;
2641 	case MPI_EVENT_LOGOUT:				/* 09 */
2642 		/* FIXME! */
2643 		break;
2644 
2645 	case MPI_EVENT_RESCAN:				/* 06 */
2646 		break;
2647 
2648 		/*
2649 		 *  CHECKME! Don't think we need to do
2650 		 *  anything for these, but...
2651 		 */
2652 	case MPI_EVENT_LINK_STATUS_CHANGE:		/* 07 */
2653 	case MPI_EVENT_LOOP_STATE_CHANGE:		/* 08 */
2654 		/*
2655 		 *  CHECKME!  Falling thru...
2656 		 */
2657 		break;
2658 
2659 	case MPI_EVENT_INTEGRATED_RAID:			/* 0B */
2660 		break;
2661 
2662 	case MPI_EVENT_NONE:				/* 00 */
2663 	case MPI_EVENT_LOG_DATA:			/* 01 */
2664 	case MPI_EVENT_STATE_CHANGE:			/* 02 */
2665 	case MPI_EVENT_EVENT_CHANGE:			/* 0A */
2666 	default:
2667 		dprintk((KERN_INFO "  Ignoring event (=%02Xh)\n", event));
2668 		break;
2669 	}
2670 
2671 	return 1;		/* currently means nothing really */
2672 }
2673 
2674 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2675 /*
2676  *  Bus Scan and Domain Validation functionality ...
2677  */
2678 
2679 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2680 /*
2681  *	mptscsih_scandv_complete - Scan and DV callback routine registered
2682  *	to Fustion MPT (base) driver.
2683  *
2684  *	@ioc: Pointer to MPT_ADAPTER structure
2685  *	@mf: Pointer to original MPT request frame
2686  *	@mr: Pointer to MPT reply frame (NULL if TurboReply)
2687  *
2688  *	This routine is called from mpt.c::mpt_interrupt() at the completion
2689  *	of any SCSI IO request.
2690  *	This routine is registered with the Fusion MPT (base) driver at driver
2691  *	load/init time via the mpt_register() API call.
2692  *
2693  *	Returns 1 indicating alloc'd request frame ptr should be freed.
2694  *
2695  *	Remark: Sets a completion code and (possibly) saves sense data
2696  *	in the IOC member localReply structure.
2697  *	Used ONLY for DV and other internal commands.
2698  */
2699 int
2700 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2701 {
2702 	MPT_SCSI_HOST	*hd;
2703 	SCSIIORequest_t *pReq;
2704 	int		 completionCode;
2705 	u16		 req_idx;
2706 
2707 	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2708 
2709 	if ((mf == NULL) ||
2710 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
2711 		printk(MYIOC_s_ERR_FMT
2712 			"ScanDvComplete, %s req frame ptr! (=%p)\n",
2713 				ioc->name, mf?"BAD":"NULL", (void *) mf);
2714 		goto wakeup;
2715 	}
2716 
2717 	del_timer(&hd->timer);
2718 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2719 	hd->ScsiLookup[req_idx] = NULL;
2720 	pReq = (SCSIIORequest_t *) mf;
2721 
2722 	if (mf != hd->cmdPtr) {
2723 		printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
2724 				hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
2725 	}
2726 	hd->cmdPtr = NULL;
2727 
2728 	ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
2729 			hd->ioc->name, mf, mr, req_idx));
2730 
2731 	hd->pLocal = &hd->localReply;
2732 	hd->pLocal->scsiStatus = 0;
2733 
2734 	/* If target struct exists, clear sense valid flag.
2735 	 */
2736 	if (mr == NULL) {
2737 		completionCode = MPT_SCANDV_GOOD;
2738 	} else {
2739 		SCSIIOReply_t	*pReply;
2740 		u16		 status;
2741 		u8		 scsi_status;
2742 
2743 		pReply = (SCSIIOReply_t *) mr;
2744 
2745 		status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2746 		scsi_status = pReply->SCSIStatus;
2747 
2748 		ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
2749 			     status, pReply->SCSIState, scsi_status,
2750 			     le32_to_cpu(pReply->IOCLogInfo)));
2751 
2752 		switch(status) {
2753 
2754 		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */
2755 			completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
2756 			break;
2757 
2758 		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
2759 		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */
2760 		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */
2761 		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */
2762 			completionCode = MPT_SCANDV_DID_RESET;
2763 			break;
2764 
2765 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
2766 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
2767 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
2768 			if (pReply->Function == MPI_FUNCTION_CONFIG) {
2769 				ConfigReply_t *pr = (ConfigReply_t *)mr;
2770 				completionCode = MPT_SCANDV_GOOD;
2771 				hd->pLocal->header.PageVersion = pr->Header.PageVersion;
2772 				hd->pLocal->header.PageLength = pr->Header.PageLength;
2773 				hd->pLocal->header.PageNumber = pr->Header.PageNumber;
2774 				hd->pLocal->header.PageType = pr->Header.PageType;
2775 
2776 			} else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2777 				/* If the RAID Volume request is successful,
2778 				 * return GOOD, else indicate that
2779 				 * some type of error occurred.
2780 				 */
2781 				MpiRaidActionReply_t	*pr = (MpiRaidActionReply_t *)mr;
2782 				if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
2783 					completionCode = MPT_SCANDV_GOOD;
2784 				else
2785 					completionCode = MPT_SCANDV_SOME_ERROR;
2786 				memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense));
2787 
2788 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
2789 				u8		*sense_data;
2790 				int		 sz;
2791 
2792 				/* save sense data in global structure
2793 				 */
2794 				completionCode = MPT_SCANDV_SENSE;
2795 				hd->pLocal->scsiStatus = scsi_status;
2796 				sense_data = ((u8 *)hd->ioc->sense_buf_pool +
2797 					(req_idx * MPT_SENSE_BUFFER_ALLOC));
2798 
2799 				sz = min_t(int, pReq->SenseBufferLength,
2800 							SCSI_STD_SENSE_BYTES);
2801 				memcpy(hd->pLocal->sense, sense_data, sz);
2802 
2803 				ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
2804 						sense_data));
2805 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2806 				if (pReq->CDB[0] == INQUIRY)
2807 					completionCode = MPT_SCANDV_ISSUE_SENSE;
2808 				else
2809 					completionCode = MPT_SCANDV_DID_RESET;
2810 			}
2811 			else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2812 				completionCode = MPT_SCANDV_DID_RESET;
2813 			else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2814 				completionCode = MPT_SCANDV_DID_RESET;
2815 			else {
2816 				completionCode = MPT_SCANDV_GOOD;
2817 				hd->pLocal->scsiStatus = scsi_status;
2818 			}
2819 			break;
2820 
2821 		case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		/* 0x0047 */
2822 			if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2823 				completionCode = MPT_SCANDV_DID_RESET;
2824 			else
2825 				completionCode = MPT_SCANDV_SOME_ERROR;
2826 			break;
2827 
2828 		default:
2829 			completionCode = MPT_SCANDV_SOME_ERROR;
2830 			break;
2831 
2832 		}	/* switch(status) */
2833 
2834 		ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
2835 				completionCode));
2836 	} /* end of address reply case */
2837 
2838 	hd->pLocal->completion = completionCode;
2839 
2840 	/* MF and RF are freed in mpt_interrupt
2841 	 */
2842 wakeup:
2843 	/* Free Chain buffers (will never chain) in scan or dv */
2844 	//mptscsih_freeChainBuffers(ioc, req_idx);
2845 
2846 	/*
2847 	 * Wake up the original calling thread
2848 	 */
2849 	hd->scandv_wait_done = 1;
2850 	wake_up(&hd->scandv_waitq);
2851 
2852 	return 1;
2853 }
2854 
2855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2856 /*	mptscsih_timer_expired - Call back for timer process.
2857  *	Used only for dv functionality.
2858  *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
2859  *
2860  */
2861 void
2862 mptscsih_timer_expired(unsigned long data)
2863 {
2864 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
2865 
2866 	ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
2867 
2868 	if (hd->cmdPtr) {
2869 		MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
2870 
2871 		if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
2872 			/* Desire to issue a task management request here.
2873 			 * TM requests MUST be single threaded.
2874 			 * If old eh code and no TM current, issue request.
2875 			 * If new eh code, do nothing. Wait for OS cmd timeout
2876 			 *	for bus reset.
2877 			 */
2878 			ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
2879 		} else {
2880 			/* Perform a FW reload */
2881 			if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
2882 				printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
2883 			}
2884 		}
2885 	} else {
2886 		/* This should NEVER happen */
2887 		printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
2888 	}
2889 
2890 	/* No more processing.
2891 	 * TM call will generate an interrupt for SCSI TM Management.
2892 	 * The FW will reply to all outstanding commands, callback will finish cleanup.
2893 	 * Hard reset clean-up will free all resources.
2894 	 */
2895 	ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
2896 
2897 	return;
2898 }
2899 
2900 
2901 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2902 /**
2903  *	mptscsih_do_cmd - Do internal command.
2904  *	@hd: MPT_SCSI_HOST pointer
2905  *	@io: INTERNAL_CMD pointer.
2906  *
2907  *	Issue the specified internally generated command and do command
2908  *	specific cleanup. For bus scan / DV only.
2909  *	NOTES: If command is Inquiry and status is good,
2910  *	initialize a target structure, save the data
2911  *
2912  *	Remark: Single threaded access only.
2913  *
2914  *	Return:
2915  *		< 0 if an illegal command or no resources
2916  *
2917  *		   0 if good
2918  *
2919  *		 > 0 if command complete but some type of completion error.
2920  */
2921 static int
2922 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2923 {
2924 	MPT_FRAME_HDR	*mf;
2925 	SCSIIORequest_t	*pScsiReq;
2926 	SCSIIORequest_t	 ReqCopy;
2927 	int		 my_idx, ii, dir;
2928 	int		 rc, cmdTimeout;
2929 	int		in_isr;
2930 	char		 cmdLen;
2931 	char		 CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2932 	char		 cmd = io->cmd;
2933 
2934 	in_isr = in_interrupt();
2935 	if (in_isr) {
2936 		dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
2937        				hd->ioc->name));
2938 		return -EPERM;
2939 	}
2940 
2941 
2942 	/* Set command specific information
2943 	 */
2944 	switch (cmd) {
2945 	case INQUIRY:
2946 		cmdLen = 6;
2947 		dir = MPI_SCSIIO_CONTROL_READ;
2948 		CDB[0] = cmd;
2949 		CDB[4] = io->size;
2950 		cmdTimeout = 10;
2951 		break;
2952 
2953 	case TEST_UNIT_READY:
2954 		cmdLen = 6;
2955 		dir = MPI_SCSIIO_CONTROL_READ;
2956 		cmdTimeout = 10;
2957 		break;
2958 
2959 	case START_STOP:
2960 		cmdLen = 6;
2961 		dir = MPI_SCSIIO_CONTROL_READ;
2962 		CDB[0] = cmd;
2963 		CDB[4] = 1;	/*Spin up the disk */
2964 		cmdTimeout = 15;
2965 		break;
2966 
2967 	case REQUEST_SENSE:
2968 		cmdLen = 6;
2969 		CDB[0] = cmd;
2970 		CDB[4] = io->size;
2971 		dir = MPI_SCSIIO_CONTROL_READ;
2972 		cmdTimeout = 10;
2973 		break;
2974 
2975 	case READ_BUFFER:
2976 		cmdLen = 10;
2977 		dir = MPI_SCSIIO_CONTROL_READ;
2978 		CDB[0] = cmd;
2979 		if (io->flags & MPT_ICFLAG_ECHO) {
2980 			CDB[1] = 0x0A;
2981 		} else {
2982 			CDB[1] = 0x02;
2983 		}
2984 
2985 		if (io->flags & MPT_ICFLAG_BUF_CAP) {
2986 			CDB[1] |= 0x01;
2987 		}
2988 		CDB[6] = (io->size >> 16) & 0xFF;
2989 		CDB[7] = (io->size >>  8) & 0xFF;
2990 		CDB[8] = io->size & 0xFF;
2991 		cmdTimeout = 10;
2992 		break;
2993 
2994 	case WRITE_BUFFER:
2995 		cmdLen = 10;
2996 		dir = MPI_SCSIIO_CONTROL_WRITE;
2997 		CDB[0] = cmd;
2998 		if (io->flags & MPT_ICFLAG_ECHO) {
2999 			CDB[1] = 0x0A;
3000 		} else {
3001 			CDB[1] = 0x02;
3002 		}
3003 		CDB[6] = (io->size >> 16) & 0xFF;
3004 		CDB[7] = (io->size >>  8) & 0xFF;
3005 		CDB[8] = io->size & 0xFF;
3006 		cmdTimeout = 10;
3007 		break;
3008 
3009 	case RESERVE:
3010 		cmdLen = 6;
3011 		dir = MPI_SCSIIO_CONTROL_READ;
3012 		CDB[0] = cmd;
3013 		cmdTimeout = 10;
3014 		break;
3015 
3016 	case RELEASE:
3017 		cmdLen = 6;
3018 		dir = MPI_SCSIIO_CONTROL_READ;
3019 		CDB[0] = cmd;
3020 		cmdTimeout = 10;
3021 		break;
3022 
3023 	case SYNCHRONIZE_CACHE:
3024 		cmdLen = 10;
3025 		dir = MPI_SCSIIO_CONTROL_READ;
3026 		CDB[0] = cmd;
3027 //		CDB[1] = 0x02;	/* set immediate bit */
3028 		cmdTimeout = 10;
3029 		break;
3030 
3031 	default:
3032 		/* Error Case */
3033 		return -EFAULT;
3034 	}
3035 
3036 	/* Get and Populate a free Frame
3037 	 */
3038 	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3039 		ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3040 					hd->ioc->name));
3041 		return -EBUSY;
3042 	}
3043 
3044 	pScsiReq = (SCSIIORequest_t *) mf;
3045 
3046 	/* Get the request index */
3047 	my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3048 	ADD_INDEX_LOG(my_idx); /* for debug */
3049 
3050 	if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3051 		pScsiReq->TargetID = io->physDiskNum;
3052 		pScsiReq->Bus = 0;
3053 		pScsiReq->ChainOffset = 0;
3054 		pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3055 	} else {
3056 		pScsiReq->TargetID = io->id;
3057 		pScsiReq->Bus = io->channel;
3058 		pScsiReq->ChainOffset = 0;
3059 		pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3060 	}
3061 
3062 	pScsiReq->CDBLength = cmdLen;
3063 	pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3064 
3065 	pScsiReq->Reserved = 0;
3066 
3067 	pScsiReq->MsgFlags = mpt_msg_flags();
3068 	/* MsgContext set in mpt_get_msg_fram call  */
3069 
3070 	int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
3071 
3072 	if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3073 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3074 	else
3075 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3076 
3077 	if (cmd == REQUEST_SENSE) {
3078 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3079 		ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3080 			hd->ioc->name, cmd));
3081 	}
3082 
3083 	for (ii=0; ii < 16; ii++)
3084 		pScsiReq->CDB[ii] = CDB[ii];
3085 
3086 	pScsiReq->DataLength = cpu_to_le32(io->size);
3087 	pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3088 					   + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3089 
3090 	ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3091 			hd->ioc->name, cmd, io->channel, io->id, io->lun));
3092 
3093 	if (dir == MPI_SCSIIO_CONTROL_READ) {
3094 		mpt_add_sge((char *) &pScsiReq->SGL,
3095 			MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3096 			io->data_dma);
3097 	} else {
3098 		mpt_add_sge((char *) &pScsiReq->SGL,
3099 			MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3100 			io->data_dma);
3101 	}
3102 
3103 	/* The ISR will free the request frame, but we need
3104 	 * the information to initialize the target. Duplicate.
3105 	 */
3106 	memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3107 
3108 	/* Issue this command after:
3109 	 *	finish init
3110 	 *	add timer
3111 	 * Wait until the reply has been received
3112 	 *  ScsiScanDvCtx callback function will
3113 	 *	set hd->pLocal;
3114 	 *	set scandv_wait_done and call wake_up
3115 	 */
3116 	hd->pLocal = NULL;
3117 	hd->timer.expires = jiffies + HZ*cmdTimeout;
3118 	hd->scandv_wait_done = 0;
3119 
3120 	/* Save cmd pointer, for resource free if timeout or
3121 	 * FW reload occurs
3122 	 */
3123 	hd->cmdPtr = mf;
3124 
3125 	add_timer(&hd->timer);
3126 	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3127 	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3128 
3129 	if (hd->pLocal) {
3130 		rc = hd->pLocal->completion;
3131 		hd->pLocal->skip = 0;
3132 
3133 		/* Always set fatal error codes in some cases.
3134 		 */
3135 		if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3136 			rc = -ENXIO;
3137 		else if (rc == MPT_SCANDV_SOME_ERROR)
3138 			rc =  -rc;
3139 	} else {
3140 		rc = -EFAULT;
3141 		/* This should never happen. */
3142 		ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3143 				hd->ioc->name));
3144 	}
3145 
3146 	return rc;
3147 }
3148 
3149 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3150 /**
3151  *	mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3152  *	@hd: Pointer to a SCSI HOST structure
3153  *	@vdevice: virtual target device
3154  *
3155  *	Uses the ISR, but with special processing.
3156  *	MUST be single-threaded.
3157  *
3158  */
3159 static void
3160 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3161 {
3162 	INTERNAL_CMD		 iocmd;
3163 
3164 	/* Following parameters will not change
3165 	 * in this routine.
3166 	 */
3167 	iocmd.cmd = SYNCHRONIZE_CACHE;
3168 	iocmd.flags = 0;
3169 	iocmd.physDiskNum = -1;
3170 	iocmd.data = NULL;
3171 	iocmd.data_dma = -1;
3172 	iocmd.size = 0;
3173 	iocmd.rsvd = iocmd.rsvd2 = 0;
3174 	iocmd.channel = vdevice->vtarget->channel;
3175 	iocmd.id = vdevice->vtarget->id;
3176 	iocmd.lun = vdevice->lun;
3177 
3178 	if ((vdevice->vtarget->type == TYPE_DISK) &&
3179 	    (vdevice->configured_lun))
3180 		mptscsih_do_cmd(hd, &iocmd);
3181 }
3182 
3183 EXPORT_SYMBOL(mptscsih_remove);
3184 EXPORT_SYMBOL(mptscsih_shutdown);
3185 #ifdef CONFIG_PM
3186 EXPORT_SYMBOL(mptscsih_suspend);
3187 EXPORT_SYMBOL(mptscsih_resume);
3188 #endif
3189 EXPORT_SYMBOL(mptscsih_proc_info);
3190 EXPORT_SYMBOL(mptscsih_info);
3191 EXPORT_SYMBOL(mptscsih_qcmd);
3192 EXPORT_SYMBOL(mptscsih_slave_destroy);
3193 EXPORT_SYMBOL(mptscsih_slave_configure);
3194 EXPORT_SYMBOL(mptscsih_abort);
3195 EXPORT_SYMBOL(mptscsih_dev_reset);
3196 EXPORT_SYMBOL(mptscsih_bus_reset);
3197 EXPORT_SYMBOL(mptscsih_host_reset);
3198 EXPORT_SYMBOL(mptscsih_bios_param);
3199 EXPORT_SYMBOL(mptscsih_io_done);
3200 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3201 EXPORT_SYMBOL(mptscsih_scandv_complete);
3202 EXPORT_SYMBOL(mptscsih_event_process);
3203 EXPORT_SYMBOL(mptscsih_ioc_reset);
3204 EXPORT_SYMBOL(mptscsih_change_queue_depth);
3205 EXPORT_SYMBOL(mptscsih_timer_expired);
3206 EXPORT_SYMBOL(mptscsih_TMHandler);
3207 
3208 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3209