File Index
Files and directories
Sign in
FILE

mptscsih.c

File preview with syntax highlighting.

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