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