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