11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/drivers/message/fusion/mptscsih.c 3f36789e2SPrakash, Sathya * For use with LSI PCI chip/adapter(s) 4f36789e2SPrakash, Sathya * running LSI Fusion MPT (Message Passing Technology) firmware. 51da177e4SLinus Torvalds * 6cddc0ab7SPrakash, Sathya * Copyright (c) 1999-2008 LSI Corporation 716d20101SEric Moore * (mailto:DL-MPTFusionLinux@lsi.com) 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 111da177e4SLinus Torvalds /* 121da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 131da177e4SLinus Torvalds it under the terms of the GNU General Public License as published by 141da177e4SLinus Torvalds the Free Software Foundation; version 2 of the License. 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds This program is distributed in the hope that it will be useful, 171da177e4SLinus Torvalds but WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4SLinus Torvalds MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 191da177e4SLinus Torvalds GNU General Public License for more details. 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds NO WARRANTY 221da177e4SLinus Torvalds THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 231da177e4SLinus Torvalds CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 241da177e4SLinus Torvalds LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 251da177e4SLinus Torvalds MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 261da177e4SLinus Torvalds solely responsible for determining the appropriateness of using and 271da177e4SLinus Torvalds distributing the Program and assumes all risks associated with its 281da177e4SLinus Torvalds exercise of rights under this Agreement, including but not limited to 291da177e4SLinus Torvalds the risks and costs of program errors, damage to or loss of data, 301da177e4SLinus Torvalds programs or equipment, and unavailability or interruption of operations. 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds DISCLAIMER OF LIABILITY 331da177e4SLinus Torvalds NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 341da177e4SLinus Torvalds DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 351da177e4SLinus Torvalds DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 361da177e4SLinus Torvalds ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 371da177e4SLinus Torvalds TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 381da177e4SLinus Torvalds USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 391da177e4SLinus Torvalds HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds You should have received a copy of the GNU General Public License 421da177e4SLinus Torvalds along with this program; if not, write to the Free Software 431da177e4SLinus Torvalds Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 441da177e4SLinus Torvalds */ 451da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds #include <linux/module.h> 481da177e4SLinus Torvalds #include <linux/kernel.h> 495a0e3ad6STejun Heo #include <linux/slab.h> 501da177e4SLinus Torvalds #include <linux/init.h> 511da177e4SLinus Torvalds #include <linux/errno.h> 521da177e4SLinus Torvalds #include <linux/kdev_t.h> 531da177e4SLinus Torvalds #include <linux/blkdev.h> 541da177e4SLinus Torvalds #include <linux/delay.h> /* for mdelay */ 551da177e4SLinus Torvalds #include <linux/interrupt.h> /* needed for in_interrupt() proto */ 561da177e4SLinus Torvalds #include <linux/reboot.h> /* notifier code */ 571da177e4SLinus Torvalds #include <linux/workqueue.h> 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds #include <scsi/scsi.h> 601da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 611da177e4SLinus Torvalds #include <scsi/scsi_device.h> 621da177e4SLinus Torvalds #include <scsi/scsi_host.h> 631da177e4SLinus Torvalds #include <scsi/scsi_tcq.h> 64e0fc15beSMoore, Eric Dean #include <scsi/scsi_dbg.h> 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds #include "mptbase.h" 671da177e4SLinus Torvalds #include "mptscsih.h" 68bf451522SEric Moore #include "lsi/mpi_log_sas.h" 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 711da177e4SLinus Torvalds #define my_NAME "Fusion MPT SCSI Host driver" 721da177e4SLinus Torvalds #define my_VERSION MPT_LINUX_VERSION_COMMON 731da177e4SLinus Torvalds #define MYNAM "mptscsih" 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds MODULE_AUTHOR(MODULEAUTHOR); 761da177e4SLinus Torvalds MODULE_DESCRIPTION(my_NAME); 771da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 789f4203b3SEric Moore MODULE_VERSION(my_VERSION); 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 811da177e4SLinus Torvalds /* 821da177e4SLinus Torvalds * Other private/forward protos... 831da177e4SLinus Torvalds */ 84db7051b2SKashyap, Desai struct scsi_cmnd *mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); 85e8206381SEric Moore static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); 86e8206381SEric Moore static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); 87e8206381SEric Moore static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); 880d0c7974SMoore, Eric Dean int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 891da177e4SLinus Torvalds static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); 900d0c7974SMoore, Eric Dean int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, 931da177e4SLinus Torvalds SCSIIORequest_t *pReq, int req_idx); 941da177e4SLinus Torvalds static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); 950d0c7974SMoore, Eric Dean static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); 961da177e4SLinus Torvalds 971ba9ab2eSKashyap, Desai int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, 989cb78c16SHannes Reinecke u64 lun, int ctx2abort, ulong timeout); 991da177e4SLinus Torvalds 1000d0c7974SMoore, Eric Dean int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); 1010d0c7974SMoore, Eric Dean int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); 1021da177e4SLinus Torvalds 103e7deff33SKashyap, Desai void 1041ba9ab2eSKashyap, Desai mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code); 10537c60f37SKashyap, Desai static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, 10637c60f37SKashyap, Desai MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); 1070d0c7974SMoore, Eric Dean int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); 1081da177e4SLinus Torvalds static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); 109c7c82987SMoore, Eric Dean static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); 1101da177e4SLinus Torvalds 1111ba9ab2eSKashyap, Desai static int 1121ba9ab2eSKashyap, Desai mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, 1131ba9ab2eSKashyap, Desai SCSITaskMgmtReply_t *pScsiTmReply); 1140d0c7974SMoore, Eric Dean void mptscsih_remove(struct pci_dev *); 115d18c3db5SGreg Kroah-Hartman void mptscsih_shutdown(struct pci_dev *); 1161da177e4SLinus Torvalds #ifdef CONFIG_PM 1170d0c7974SMoore, Eric Dean int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state); 1180d0c7974SMoore, Eric Dean int mptscsih_resume(struct pci_dev *pdev); 1191da177e4SLinus Torvalds #endif 1201da177e4SLinus Torvalds 121b80ca4f7SFUJITA Tomonori #define SNS_LEN(scp) SCSI_SENSE_BUFFERSIZE 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1251da177e4SLinus Torvalds /* 1261da177e4SLinus Torvalds * mptscsih_getFreeChainBuffer - Function to get a free chain 1271da177e4SLinus Torvalds * from the MPT_SCSI_HOST FreeChainQ. 1281da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 1291da177e4SLinus Torvalds * @req_idx: Index of the SCSI IO request frame. (output) 1301da177e4SLinus Torvalds * 1311da177e4SLinus Torvalds * return SUCCESS or FAILED 1321da177e4SLinus Torvalds */ 1331da177e4SLinus Torvalds static inline int 1341da177e4SLinus Torvalds mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) 1351da177e4SLinus Torvalds { 1361da177e4SLinus Torvalds MPT_FRAME_HDR *chainBuf; 1371da177e4SLinus Torvalds unsigned long flags; 1381da177e4SLinus Torvalds int rc; 1391da177e4SLinus Torvalds int chain_idx; 1401da177e4SLinus Torvalds 1416757d6b4SPrakash, Sathya dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n", 1421da177e4SLinus Torvalds ioc->name)); 1431da177e4SLinus Torvalds spin_lock_irqsave(&ioc->FreeQlock, flags); 1441da177e4SLinus Torvalds if (!list_empty(&ioc->FreeChainQ)) { 1451da177e4SLinus Torvalds int offset; 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR, 1481da177e4SLinus Torvalds u.frame.linkage.list); 1491da177e4SLinus Torvalds list_del(&chainBuf->u.frame.linkage.list); 1501da177e4SLinus Torvalds offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; 1511da177e4SLinus Torvalds chain_idx = offset / ioc->req_sz; 1521da177e4SLinus Torvalds rc = SUCCESS; 15329dd3609SEric Moore dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT 15429dd3609SEric Moore "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", 155c6678e0cSChristoph Hellwig ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx)); 1561da177e4SLinus Torvalds } else { 1571da177e4SLinus Torvalds rc = FAILED; 1581da177e4SLinus Torvalds chain_idx = MPT_HOST_NO_CHAIN; 15929dd3609SEric Moore dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n", 1601da177e4SLinus Torvalds ioc->name)); 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds spin_unlock_irqrestore(&ioc->FreeQlock, flags); 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds *retIndex = chain_idx; 1651da177e4SLinus Torvalds return rc; 1661da177e4SLinus Torvalds } /* mptscsih_getFreeChainBuffer() */ 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1691da177e4SLinus Torvalds /* 1701da177e4SLinus Torvalds * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the 1711da177e4SLinus Torvalds * SCSIIORequest_t Message Frame. 1721da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 1731da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure 1741da177e4SLinus Torvalds * @pReq: Pointer to SCSIIORequest_t structure 1751da177e4SLinus Torvalds * 1761da177e4SLinus Torvalds * Returns ... 1771da177e4SLinus Torvalds */ 1781da177e4SLinus Torvalds static int 1791da177e4SLinus Torvalds mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, 1801da177e4SLinus Torvalds SCSIIORequest_t *pReq, int req_idx) 1811da177e4SLinus Torvalds { 1821da177e4SLinus Torvalds char *psge; 1831da177e4SLinus Torvalds char *chainSge; 1841da177e4SLinus Torvalds struct scatterlist *sg; 1851da177e4SLinus Torvalds int frm_sz; 1861da177e4SLinus Torvalds int sges_left, sg_done; 1871da177e4SLinus Torvalds int chain_idx = MPT_HOST_NO_CHAIN; 1881da177e4SLinus Torvalds int sgeOffset; 1891da177e4SLinus Torvalds int numSgeSlots, numSgeThisFrame; 1901da177e4SLinus Torvalds u32 sgflags, sgdir, thisxfer = 0; 1911da177e4SLinus Torvalds int chain_dma_off = 0; 1921da177e4SLinus Torvalds int newIndex; 1931da177e4SLinus Torvalds int ii; 1941da177e4SLinus Torvalds dma_addr_t v2; 1951da177e4SLinus Torvalds u32 RequestNB; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK; 1981da177e4SLinus Torvalds if (sgdir == MPI_SCSIIO_CONTROL_WRITE) { 1991da177e4SLinus Torvalds sgdir = MPT_TRANSFER_HOST_TO_IOC; 2001da177e4SLinus Torvalds } else { 2011da177e4SLinus Torvalds sgdir = MPT_TRANSFER_IOC_TO_HOST; 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds psge = (char *) &pReq->SGL; 2051da177e4SLinus Torvalds frm_sz = ioc->req_sz; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* Map the data portion, if any. 2081da177e4SLinus Torvalds * sges_left = 0 if no data transfer. 2091da177e4SLinus Torvalds */ 2101928d73fSFUJITA Tomonori sges_left = scsi_dma_map(SCpnt); 2111928d73fSFUJITA Tomonori if (sges_left < 0) 2121da177e4SLinus Torvalds return FAILED; 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds /* Handle the SG case. 2151da177e4SLinus Torvalds */ 2161928d73fSFUJITA Tomonori sg = scsi_sglist(SCpnt); 2171da177e4SLinus Torvalds sg_done = 0; 2181da177e4SLinus Torvalds sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION); 2191da177e4SLinus Torvalds chainSge = NULL; 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds /* Prior to entering this loop - the following must be set 2221da177e4SLinus Torvalds * current MF: sgeOffset (bytes) 2231da177e4SLinus Torvalds * chainSge (Null if original MF is not a chain buffer) 2241da177e4SLinus Torvalds * sg_done (num SGE done for this MF) 2251da177e4SLinus Torvalds */ 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds nextSGEset: 22814d0f0b0SKashyap, Desai numSgeSlots = ((frm_sz - sgeOffset) / ioc->SGE_size); 2291da177e4SLinus Torvalds numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots; 2301da177e4SLinus Torvalds 23114d0f0b0SKashyap, Desai sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | sgdir; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds /* Get first (num - 1) SG elements 2341da177e4SLinus Torvalds * Skip any SG entries with a length of 0 2351da177e4SLinus Torvalds * NOTE: at finish, sg and psge pointed to NEXT data/location positions 2361da177e4SLinus Torvalds */ 2371da177e4SLinus Torvalds for (ii=0; ii < (numSgeThisFrame-1); ii++) { 2381da177e4SLinus Torvalds thisxfer = sg_dma_len(sg); 2391da177e4SLinus Torvalds if (thisxfer == 0) { 2402f187862SKashyap, Desai /* Get next SG element from the OS */ 2412f187862SKashyap, Desai sg = sg_next(sg); 2421da177e4SLinus Torvalds sg_done++; 2431da177e4SLinus Torvalds continue; 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds v2 = sg_dma_address(sg); 24714d0f0b0SKashyap, Desai ioc->add_sge(psge, sgflags | thisxfer, v2); 2481da177e4SLinus Torvalds 2492f187862SKashyap, Desai /* Get next SG element from the OS */ 2502f187862SKashyap, Desai sg = sg_next(sg); 25114d0f0b0SKashyap, Desai psge += ioc->SGE_size; 25214d0f0b0SKashyap, Desai sgeOffset += ioc->SGE_size; 2531da177e4SLinus Torvalds sg_done++; 2541da177e4SLinus Torvalds } 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds if (numSgeThisFrame == sges_left) { 2571da177e4SLinus Torvalds /* Add last element, end of buffer and end of list flags. 2581da177e4SLinus Torvalds */ 2591da177e4SLinus Torvalds sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT | 2601da177e4SLinus Torvalds MPT_SGE_FLAGS_END_OF_BUFFER | 2611da177e4SLinus Torvalds MPT_SGE_FLAGS_END_OF_LIST; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds /* Add last SGE and set termination flags. 2641da177e4SLinus Torvalds * Note: Last SGE may have a length of 0 - which should be ok. 2651da177e4SLinus Torvalds */ 2661da177e4SLinus Torvalds thisxfer = sg_dma_len(sg); 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds v2 = sg_dma_address(sg); 26914d0f0b0SKashyap, Desai ioc->add_sge(psge, sgflags | thisxfer, v2); 27014d0f0b0SKashyap, Desai sgeOffset += ioc->SGE_size; 2711da177e4SLinus Torvalds sg_done++; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds if (chainSge) { 2741da177e4SLinus Torvalds /* The current buffer is a chain buffer, 2751da177e4SLinus Torvalds * but there is not another one. 2761da177e4SLinus Torvalds * Update the chain element 2771da177e4SLinus Torvalds * Offset and Length fields. 2781da177e4SLinus Torvalds */ 27914d0f0b0SKashyap, Desai ioc->add_chain((char *)chainSge, 0, sgeOffset, 28014d0f0b0SKashyap, Desai ioc->ChainBufferDMA + chain_dma_off); 2811da177e4SLinus Torvalds } else { 2821da177e4SLinus Torvalds /* The current buffer is the original MF 2831da177e4SLinus Torvalds * and there is no Chain buffer. 2841da177e4SLinus Torvalds */ 2851da177e4SLinus Torvalds pReq->ChainOffset = 0; 2861da177e4SLinus Torvalds RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; 2876757d6b4SPrakash, Sathya dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2881da177e4SLinus Torvalds "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); 2891da177e4SLinus Torvalds ioc->RequestNB[req_idx] = RequestNB; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds } else { 2921da177e4SLinus Torvalds /* At least one chain buffer is needed. 2931da177e4SLinus Torvalds * Complete the first MF 2941da177e4SLinus Torvalds * - last SGE element, set the LastElement bit 2951da177e4SLinus Torvalds * - set ChainOffset (words) for orig MF 2961da177e4SLinus Torvalds * (OR finish previous MF chain buffer) 2971da177e4SLinus Torvalds * - update MFStructPtr ChainIndex 2981da177e4SLinus Torvalds * - Populate chain element 2991da177e4SLinus Torvalds * Also 3001da177e4SLinus Torvalds * Loop until done. 3011da177e4SLinus Torvalds */ 3021da177e4SLinus Torvalds 3036757d6b4SPrakash, Sathya dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SG: Chain Required! sg done %d\n", 3041da177e4SLinus Torvalds ioc->name, sg_done)); 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds /* Set LAST_ELEMENT flag for last non-chain element 3071da177e4SLinus Torvalds * in the buffer. Since psge points at the NEXT 3081da177e4SLinus Torvalds * SGE element, go back one SGE element, update the flags 3091da177e4SLinus Torvalds * and reset the pointer. (Note: sgflags & thisxfer are already 3101da177e4SLinus Torvalds * set properly). 3111da177e4SLinus Torvalds */ 3121da177e4SLinus Torvalds if (sg_done) { 31314d0f0b0SKashyap, Desai u32 *ptmp = (u32 *) (psge - ioc->SGE_size); 3141da177e4SLinus Torvalds sgflags = le32_to_cpu(*ptmp); 3151da177e4SLinus Torvalds sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT; 3161da177e4SLinus Torvalds *ptmp = cpu_to_le32(sgflags); 3171da177e4SLinus Torvalds } 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds if (chainSge) { 3201da177e4SLinus Torvalds /* The current buffer is a chain buffer. 3211da177e4SLinus Torvalds * chainSge points to the previous Chain Element. 3221da177e4SLinus Torvalds * Update its chain element Offset and Length (must 3231da177e4SLinus Torvalds * include chain element size) fields. 3241da177e4SLinus Torvalds * Old chain element is now complete. 3251da177e4SLinus Torvalds */ 3261da177e4SLinus Torvalds u8 nextChain = (u8) (sgeOffset >> 2); 32714d0f0b0SKashyap, Desai sgeOffset += ioc->SGE_size; 32814d0f0b0SKashyap, Desai ioc->add_chain((char *)chainSge, nextChain, sgeOffset, 32914d0f0b0SKashyap, Desai ioc->ChainBufferDMA + chain_dma_off); 3301da177e4SLinus Torvalds } else { 3311da177e4SLinus Torvalds /* The original MF buffer requires a chain buffer - 3321da177e4SLinus Torvalds * set the offset. 3331da177e4SLinus Torvalds * Last element in this MF is a chain element. 3341da177e4SLinus Torvalds */ 3351da177e4SLinus Torvalds pReq->ChainOffset = (u8) (sgeOffset >> 2); 3361da177e4SLinus Torvalds RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03; 3376757d6b4SPrakash, Sathya dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset)); 3381da177e4SLinus Torvalds ioc->RequestNB[req_idx] = RequestNB; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds sges_left -= sg_done; 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds /* NOTE: psge points to the beginning of the chain element 3451da177e4SLinus Torvalds * in current buffer. Get a chain buffer. 3461da177e4SLinus Torvalds */ 347c6678e0cSChristoph Hellwig if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) { 3486757d6b4SPrakash, Sathya dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 349c6678e0cSChristoph Hellwig "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n", 3501da177e4SLinus Torvalds ioc->name, pReq->CDB[0], SCpnt)); 3511da177e4SLinus Torvalds return FAILED; 352c6678e0cSChristoph Hellwig } 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds /* Update the tracking arrays. 3551da177e4SLinus Torvalds * If chainSge == NULL, update ReqToChain, else ChainToChain 3561da177e4SLinus Torvalds */ 3571da177e4SLinus Torvalds if (chainSge) { 3581da177e4SLinus Torvalds ioc->ChainToChain[chain_idx] = newIndex; 3591da177e4SLinus Torvalds } else { 3601da177e4SLinus Torvalds ioc->ReqToChain[req_idx] = newIndex; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds chain_idx = newIndex; 3631da177e4SLinus Torvalds chain_dma_off = ioc->req_sz * chain_idx; 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds /* Populate the chainSGE for the current buffer. 3661da177e4SLinus Torvalds * - Set chain buffer pointer to psge and fill 3671da177e4SLinus Torvalds * out the Address and Flags fields. 3681da177e4SLinus Torvalds */ 3691da177e4SLinus Torvalds chainSge = (char *) psge; 37029dd3609SEric Moore dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)", 37129dd3609SEric Moore ioc->name, psge, req_idx)); 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds /* Start the SGE for the next buffer 3741da177e4SLinus Torvalds */ 3751da177e4SLinus Torvalds psge = (char *) (ioc->ChainBuffer + chain_dma_off); 3761da177e4SLinus Torvalds sgeOffset = 0; 3771da177e4SLinus Torvalds sg_done = 0; 3781da177e4SLinus Torvalds 37929dd3609SEric Moore dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n", 38029dd3609SEric Moore ioc->name, psge, chain_idx)); 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* Start the SGE for the next buffer 3831da177e4SLinus Torvalds */ 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds goto nextSGEset; 3861da177e4SLinus Torvalds } 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds return SUCCESS; 3891da177e4SLinus Torvalds } /* mptscsih_AddSGE() */ 3901da177e4SLinus Torvalds 391786899b0SEric Moore static void 392786899b0SEric Moore mptscsih_issue_sep_command(MPT_ADAPTER *ioc, VirtTarget *vtarget, 393786899b0SEric Moore U32 SlotStatus) 394786899b0SEric Moore { 395786899b0SEric Moore MPT_FRAME_HDR *mf; 396786899b0SEric Moore SEPRequest_t *SEPMsg; 397786899b0SEric Moore 398cc78d30aSEric Moore if (ioc->bus_type != SAS) 399cc78d30aSEric Moore return; 400cc78d30aSEric Moore 401cc78d30aSEric Moore /* Not supported for hidden raid components 402cc78d30aSEric Moore */ 403cc78d30aSEric Moore if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 404786899b0SEric Moore return; 405786899b0SEric Moore 406786899b0SEric Moore if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { 4076757d6b4SPrakash, Sathya dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n", 408cadbd4a5SHarvey Harrison ioc->name,__func__)); 409786899b0SEric Moore return; 410786899b0SEric Moore } 411786899b0SEric Moore 412786899b0SEric Moore SEPMsg = (SEPRequest_t *)mf; 413786899b0SEric Moore SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; 414793955f5SEric Moore SEPMsg->Bus = vtarget->channel; 415793955f5SEric Moore SEPMsg->TargetID = vtarget->id; 416786899b0SEric Moore SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS; 417786899b0SEric Moore SEPMsg->SlotStatus = SlotStatus; 4186757d6b4SPrakash, Sathya devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 419793955f5SEric Moore "Sending SEP cmd=%x channel=%d id=%d\n", 420793955f5SEric Moore ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID)); 421786899b0SEric Moore mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); 422786899b0SEric Moore } 423786899b0SEric Moore 4246757d6b4SPrakash, Sathya #ifdef CONFIG_FUSION_LOGGING 425c6c727a1SEric Moore /** 4266757d6b4SPrakash, Sathya * mptscsih_info_scsiio - debug print info on reply frame 427c6c727a1SEric Moore * @ioc: Pointer to MPT_ADAPTER structure 428c6c727a1SEric Moore * @sc: original scsi cmnd pointer 4296757d6b4SPrakash, Sathya * @pScsiReply: Pointer to MPT reply frame 4306757d6b4SPrakash, Sathya * 4316757d6b4SPrakash, Sathya * MPT_DEBUG_REPLY needs to be enabled to obtain this info 432c6c727a1SEric Moore * 433c6c727a1SEric Moore * Refer to lsi/mpi.h. 434c6c727a1SEric Moore **/ 435c6c727a1SEric Moore static void 4366757d6b4SPrakash, Sathya mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply) 437c6c727a1SEric Moore { 438c6c727a1SEric Moore char *desc = NULL; 4396757d6b4SPrakash, Sathya char *desc1 = NULL; 4406757d6b4SPrakash, Sathya u16 ioc_status; 4416757d6b4SPrakash, Sathya u8 skey, asc, ascq; 4426757d6b4SPrakash, Sathya 4436757d6b4SPrakash, Sathya ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; 444c6c727a1SEric Moore 445c6c727a1SEric Moore switch (ioc_status) { 446c6c727a1SEric Moore 4476757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SUCCESS: 4486757d6b4SPrakash, Sathya desc = "success"; 449c6c727a1SEric Moore break; 4506757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_INVALID_BUS: 4516757d6b4SPrakash, Sathya desc = "invalid bus"; 452c6c727a1SEric Moore break; 4536757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: 4546757d6b4SPrakash, Sathya desc = "invalid target_id"; 455c6c727a1SEric Moore break; 4566757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 4576757d6b4SPrakash, Sathya desc = "device not there"; 458c6c727a1SEric Moore break; 4596757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: 4606757d6b4SPrakash, Sathya desc = "data overrun"; 461c6c727a1SEric Moore break; 4626757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: 4636757d6b4SPrakash, Sathya desc = "data underrun"; 464c6c727a1SEric Moore break; 4656757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: 4666757d6b4SPrakash, Sathya desc = "I/O data error"; 467c6c727a1SEric Moore break; 4686757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: 4696757d6b4SPrakash, Sathya desc = "protocol error"; 470c6c727a1SEric Moore break; 4716757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: 4726757d6b4SPrakash, Sathya desc = "task terminated"; 473c6c727a1SEric Moore break; 4746757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 4756757d6b4SPrakash, Sathya desc = "residual mismatch"; 476c6c727a1SEric Moore break; 4776757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 4786757d6b4SPrakash, Sathya desc = "task management failed"; 4796757d6b4SPrakash, Sathya break; 4806757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: 4816757d6b4SPrakash, Sathya desc = "IOC terminated"; 4826757d6b4SPrakash, Sathya break; 4836757d6b4SPrakash, Sathya case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: 4846757d6b4SPrakash, Sathya desc = "ext terminated"; 4856757d6b4SPrakash, Sathya break; 4866757d6b4SPrakash, Sathya default: 4876757d6b4SPrakash, Sathya desc = ""; 488c6c727a1SEric Moore break; 489c6c727a1SEric Moore } 490c6c727a1SEric Moore 4916757d6b4SPrakash, Sathya switch (pScsiReply->SCSIStatus) 4926757d6b4SPrakash, Sathya { 493c6c727a1SEric Moore 4946757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_SUCCESS: 4956757d6b4SPrakash, Sathya desc1 = "success"; 4966757d6b4SPrakash, Sathya break; 4976757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_CHECK_CONDITION: 4986757d6b4SPrakash, Sathya desc1 = "check condition"; 4996757d6b4SPrakash, Sathya break; 5006757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_CONDITION_MET: 5016757d6b4SPrakash, Sathya desc1 = "condition met"; 5026757d6b4SPrakash, Sathya break; 5036757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_BUSY: 5046757d6b4SPrakash, Sathya desc1 = "busy"; 5056757d6b4SPrakash, Sathya break; 5066757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_INTERMEDIATE: 5076757d6b4SPrakash, Sathya desc1 = "intermediate"; 5086757d6b4SPrakash, Sathya break; 5096757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET: 5106757d6b4SPrakash, Sathya desc1 = "intermediate condmet"; 5116757d6b4SPrakash, Sathya break; 5126757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_RESERVATION_CONFLICT: 5136757d6b4SPrakash, Sathya desc1 = "reservation conflict"; 5146757d6b4SPrakash, Sathya break; 5156757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_COMMAND_TERMINATED: 5166757d6b4SPrakash, Sathya desc1 = "command terminated"; 5176757d6b4SPrakash, Sathya break; 5186757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_TASK_SET_FULL: 5196757d6b4SPrakash, Sathya desc1 = "task set full"; 5206757d6b4SPrakash, Sathya break; 5216757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_ACA_ACTIVE: 5226757d6b4SPrakash, Sathya desc1 = "aca active"; 5236757d6b4SPrakash, Sathya break; 5246757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT: 5256757d6b4SPrakash, Sathya desc1 = "fcpext device logged out"; 5266757d6b4SPrakash, Sathya break; 5276757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_FCPEXT_NO_LINK: 5286757d6b4SPrakash, Sathya desc1 = "fcpext no link"; 5296757d6b4SPrakash, Sathya break; 5306757d6b4SPrakash, Sathya case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED: 5316757d6b4SPrakash, Sathya desc1 = "fcpext unassigned"; 5326757d6b4SPrakash, Sathya break; 5336757d6b4SPrakash, Sathya default: 5346757d6b4SPrakash, Sathya desc1 = ""; 5356757d6b4SPrakash, Sathya break; 5366757d6b4SPrakash, Sathya } 537c6c727a1SEric Moore 5386757d6b4SPrakash, Sathya scsi_print_command(sc); 5399cb78c16SHannes Reinecke printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %llu\n", 5402f187862SKashyap, Desai ioc->name, pScsiReply->Bus, pScsiReply->TargetID, sc->device->lun); 54129dd3609SEric Moore printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " 54229dd3609SEric Moore "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, 54329dd3609SEric Moore scsi_get_resid(sc)); 54429dd3609SEric Moore printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " 54529dd3609SEric Moore "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), 5466757d6b4SPrakash, Sathya le32_to_cpu(pScsiReply->TransferCount), sc->result); 5472f187862SKashyap, Desai 54829dd3609SEric Moore printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " 5496757d6b4SPrakash, Sathya "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", 55029dd3609SEric Moore ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, 5516757d6b4SPrakash, Sathya pScsiReply->SCSIState); 5526757d6b4SPrakash, Sathya 5536757d6b4SPrakash, Sathya if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { 5546757d6b4SPrakash, Sathya skey = sc->sense_buffer[2] & 0x0F; 5556757d6b4SPrakash, Sathya asc = sc->sense_buffer[12]; 5566757d6b4SPrakash, Sathya ascq = sc->sense_buffer[13]; 5576757d6b4SPrakash, Sathya 55829dd3609SEric Moore printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: " 55929dd3609SEric Moore "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq); 5606757d6b4SPrakash, Sathya } 5616757d6b4SPrakash, Sathya 5626757d6b4SPrakash, Sathya /* 5636757d6b4SPrakash, Sathya * Look for + dump FCP ResponseInfo[]! 5646757d6b4SPrakash, Sathya */ 5656757d6b4SPrakash, Sathya if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID && 5666757d6b4SPrakash, Sathya pScsiReply->ResponseInfo) 56729dd3609SEric Moore printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n", 56829dd3609SEric Moore ioc->name, le32_to_cpu(pScsiReply->ResponseInfo)); 569c6c727a1SEric Moore } 570c6c727a1SEric Moore #endif 571c6c727a1SEric Moore 5721da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 5731da177e4SLinus Torvalds /* 5741da177e4SLinus Torvalds * mptscsih_io_done - Main SCSI IO callback routine registered to 5751da177e4SLinus Torvalds * Fusion MPT (base) driver 5761da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 5771da177e4SLinus Torvalds * @mf: Pointer to original MPT request frame 5781da177e4SLinus Torvalds * @r: Pointer to MPT reply frame (NULL if TurboReply) 5791da177e4SLinus Torvalds * 5801da177e4SLinus Torvalds * This routine is called from mpt.c::mpt_interrupt() at the completion 5811da177e4SLinus Torvalds * of any SCSI IO request. 5821da177e4SLinus Torvalds * This routine is registered with the Fusion MPT (base) driver at driver 5831da177e4SLinus Torvalds * load/init time via the mpt_register() API call. 5841da177e4SLinus Torvalds * 5851da177e4SLinus Torvalds * Returns 1 indicating alloc'd request frame ptr should be freed. 5861da177e4SLinus Torvalds */ 5870d0c7974SMoore, Eric Dean int 5881da177e4SLinus Torvalds mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) 5891da177e4SLinus Torvalds { 5901da177e4SLinus Torvalds struct scsi_cmnd *sc; 5911da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 5921da177e4SLinus Torvalds SCSIIORequest_t *pScsiReq; 5931da177e4SLinus Torvalds SCSIIOReply_t *pScsiReply; 5942254c86dSMoore, Eric u16 req_idx, req_idx_MR; 595a69de507SEric Moore VirtDevice *vdevice; 596786899b0SEric Moore VirtTarget *vtarget; 5971da177e4SLinus Torvalds 598e7eae9f6SEric Moore hd = shost_priv(ioc->sh); 5991da177e4SLinus Torvalds req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 6002254c86dSMoore, Eric req_idx_MR = (mr != NULL) ? 6012254c86dSMoore, Eric le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; 6022f187862SKashyap, Desai 6032f187862SKashyap, Desai /* Special case, where already freed message frame is received from 6042f187862SKashyap, Desai * Firmware. It happens with Resetting IOC. 6052f187862SKashyap, Desai * Return immediately. Do not care 6062f187862SKashyap, Desai */ 6072254c86dSMoore, Eric if ((req_idx != req_idx_MR) || 6082f187862SKashyap, Desai (le32_to_cpu(mf->u.frame.linkage.arg1) == 0xdeadbeaf)) 6092254c86dSMoore, Eric return 0; 6102254c86dSMoore, Eric 611e8206381SEric Moore sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); 6121da177e4SLinus Torvalds if (sc == NULL) { 6131da177e4SLinus Torvalds MPIHeader_t *hdr = (MPIHeader_t *)mf; 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds /* Remark: writeSDP1 will use the ScsiDoneCtx 6161da177e4SLinus Torvalds * If a SCSI I/O cmd, device disabled by OS and 6171da177e4SLinus Torvalds * completion done. Cannot touch sc struct. Just free mem. 6181da177e4SLinus Torvalds */ 6191da177e4SLinus Torvalds if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) 6201da177e4SLinus Torvalds printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n", 6211da177e4SLinus Torvalds ioc->name); 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds mptscsih_freeChainBuffers(ioc, req_idx); 6241da177e4SLinus Torvalds return 1; 6251da177e4SLinus Torvalds } 6261da177e4SLinus Torvalds 6273dc0b03fSEric Moore if ((unsigned char *)mf != sc->host_scribble) { 6283dc0b03fSEric Moore mptscsih_freeChainBuffers(ioc, req_idx); 6293dc0b03fSEric Moore return 1; 6303dc0b03fSEric Moore } 6313dc0b03fSEric Moore 632fea98403SKashyap, Desai if (ioc->bus_type == SAS) { 633fea98403SKashyap, Desai VirtDevice *vdevice = sc->device->hostdata; 634fea98403SKashyap, Desai 635fea98403SKashyap, Desai if (!vdevice || !vdevice->vtarget || 636fea98403SKashyap, Desai vdevice->vtarget->deleted) { 637fea98403SKashyap, Desai sc->result = DID_NO_CONNECT << 16; 638fea98403SKashyap, Desai goto out; 639fea98403SKashyap, Desai } 640fea98403SKashyap, Desai } 641fea98403SKashyap, Desai 6423dc0b03fSEric Moore sc->host_scribble = NULL; 6431da177e4SLinus Torvalds sc->result = DID_OK << 16; /* Set default reply as OK */ 6441da177e4SLinus Torvalds pScsiReq = (SCSIIORequest_t *) mf; 6451da177e4SLinus Torvalds pScsiReply = (SCSIIOReply_t *) mr; 6461da177e4SLinus Torvalds 647c6678e0cSChristoph Hellwig if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){ 6486757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT 649c6678e0cSChristoph Hellwig "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n", 650c6678e0cSChristoph Hellwig ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag)); 651c6678e0cSChristoph Hellwig }else{ 6526757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT 653c6678e0cSChristoph Hellwig "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n", 654c6678e0cSChristoph Hellwig ioc->name, mf, mr, sc, req_idx)); 655c6678e0cSChristoph Hellwig } 656c6678e0cSChristoph Hellwig 6571da177e4SLinus Torvalds if (pScsiReply == NULL) { 6581da177e4SLinus Torvalds /* special context reply handling */ 6591da177e4SLinus Torvalds ; 6601da177e4SLinus Torvalds } else { 6611da177e4SLinus Torvalds u32 xfer_cnt; 6621da177e4SLinus Torvalds u16 status; 6631da177e4SLinus Torvalds u8 scsi_state, scsi_status; 664c6c727a1SEric Moore u32 log_info; 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK; 667c9de7dc4SKashyap, Desai 6681da177e4SLinus Torvalds scsi_state = pScsiReply->SCSIState; 6691da177e4SLinus Torvalds scsi_status = pScsiReply->SCSIStatus; 6701da177e4SLinus Torvalds xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); 6711928d73fSFUJITA Tomonori scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); 672c6c727a1SEric Moore log_info = le32_to_cpu(pScsiReply->IOCLogInfo); 6731da177e4SLinus Torvalds 674466544d8SMoore, Eric Dean /* 675466544d8SMoore, Eric Dean * if we get a data underrun indication, yet no data was 676466544d8SMoore, Eric Dean * transferred and the SCSI status indicates that the 677466544d8SMoore, Eric Dean * command was never started, change the data underrun 678466544d8SMoore, Eric Dean * to success 679466544d8SMoore, Eric Dean */ 680466544d8SMoore, Eric Dean if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && 681466544d8SMoore, Eric Dean (scsi_status == MPI_SCSI_STATUS_BUSY || 682466544d8SMoore, Eric Dean scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT || 683466544d8SMoore, Eric Dean scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) { 684466544d8SMoore, Eric Dean status = MPI_IOCSTATUS_SUCCESS; 685466544d8SMoore, Eric Dean } 686466544d8SMoore, Eric Dean 6871da177e4SLinus Torvalds if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) 6880d0c7974SMoore, Eric Dean mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds /* 6911da177e4SLinus Torvalds * Look for + dump FCP ResponseInfo[]! 6921da177e4SLinus Torvalds */ 693466544d8SMoore, Eric Dean if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && 694466544d8SMoore, Eric Dean pScsiReply->ResponseInfo) { 6959cb78c16SHannes Reinecke printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%llu] " 69629dd3609SEric Moore "FCP_ResponseInfo=%08xh\n", ioc->name, 697c6c727a1SEric Moore sc->device->host->host_no, sc->device->channel, 698c6c727a1SEric Moore sc->device->id, sc->device->lun, 6991da177e4SLinus Torvalds le32_to_cpu(pScsiReply->ResponseInfo)); 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds 7021da177e4SLinus Torvalds switch(status) { 7031da177e4SLinus Torvalds case MPI_IOCSTATUS_BUSY: /* 0x0002 */ 704d23321b4SKashyap, Desai case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ 7051da177e4SLinus Torvalds /* CHECKME! 7061da177e4SLinus Torvalds * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry) 7071da177e4SLinus Torvalds * But not: DID_BUS_BUSY lest one risk 7081da177e4SLinus Torvalds * killing interrupt handler:-( 7091da177e4SLinus Torvalds */ 7101da177e4SLinus Torvalds sc->result = SAM_STAT_BUSY; 7111da177e4SLinus Torvalds break; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ 7141da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ 7151da177e4SLinus Torvalds sc->result = DID_BAD_TARGET << 16; 7161da177e4SLinus Torvalds break; 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 7191da177e4SLinus Torvalds /* Spoof to SCSI Selection Timeout! */ 72065207fedSMoore, Eric if (ioc->bus_type != FC) 7211da177e4SLinus Torvalds sc->result = DID_NO_CONNECT << 16; 72265207fedSMoore, Eric /* else fibre, just stall until rescan event */ 72365207fedSMoore, Eric else 72465207fedSMoore, Eric sc->result = DID_REQUEUE << 16; 7251da177e4SLinus Torvalds 7261da177e4SLinus Torvalds if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) 7271da177e4SLinus Torvalds hd->sel_timeout[pScsiReq->TargetID]++; 728786899b0SEric Moore 729a69de507SEric Moore vdevice = sc->device->hostdata; 730a69de507SEric Moore if (!vdevice) 731786899b0SEric Moore break; 732a69de507SEric Moore vtarget = vdevice->vtarget; 733786899b0SEric Moore if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) { 734786899b0SEric Moore mptscsih_issue_sep_command(ioc, vtarget, 735786899b0SEric Moore MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED); 736786899b0SEric Moore vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON; 737786899b0SEric Moore } 7381da177e4SLinus Torvalds break; 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 741bf451522SEric Moore if ( ioc->bus_type == SAS ) { 742c9de7dc4SKashyap, Desai u16 ioc_status = 743c9de7dc4SKashyap, Desai le16_to_cpu(pScsiReply->IOCStatus); 744c9de7dc4SKashyap, Desai if ((ioc_status & 745c9de7dc4SKashyap, Desai MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) 746c9de7dc4SKashyap, Desai && 747c9de7dc4SKashyap, Desai ((log_info & SAS_LOGINFO_MASK) == 748c9de7dc4SKashyap, Desai SAS_LOGINFO_NEXUS_LOSS)) { 749c9de7dc4SKashyap, Desai VirtDevice *vdevice = 750c9de7dc4SKashyap, Desai sc->device->hostdata; 751c9de7dc4SKashyap, Desai 752c9de7dc4SKashyap, Desai /* flag the device as being in 753c9de7dc4SKashyap, Desai * device removal delay so we can 754c9de7dc4SKashyap, Desai * notify the midlayer to hold off 755c9de7dc4SKashyap, Desai * on timeout eh */ 756c9de7dc4SKashyap, Desai if (vdevice && vdevice-> 757c9de7dc4SKashyap, Desai vtarget && 758c9de7dc4SKashyap, Desai vdevice->vtarget-> 759c9de7dc4SKashyap, Desai raidVolume) 760c9de7dc4SKashyap, Desai printk(KERN_INFO 761c9de7dc4SKashyap, Desai "Skipping Raid Volume" 762c9de7dc4SKashyap, Desai "for inDMD\n"); 763c9de7dc4SKashyap, Desai else if (vdevice && 764c9de7dc4SKashyap, Desai vdevice->vtarget) 765c9de7dc4SKashyap, Desai vdevice->vtarget-> 766c9de7dc4SKashyap, Desai inDMD = 1; 767c9de7dc4SKashyap, Desai 7684d069566SKashyap, Desai sc->result = 7694d069566SKashyap, Desai (DID_TRANSPORT_DISRUPTED 7704d069566SKashyap, Desai << 16); 771bf451522SEric Moore break; 772bf451522SEric Moore } 77386dd4242SEric Moore } else if (ioc->bus_type == FC) { 77486dd4242SEric Moore /* 77586dd4242SEric Moore * The FC IOC may kill a request for variety of 77686dd4242SEric Moore * reasons, some of which may be recovered by a 77786dd4242SEric Moore * retry, some which are unlikely to be 77886dd4242SEric Moore * recovered. Return DID_ERROR instead of 77986dd4242SEric Moore * DID_RESET to permit retry of the command, 78086dd4242SEric Moore * just not an infinite number of them 78186dd4242SEric Moore */ 78286dd4242SEric Moore sc->result = DID_ERROR << 16; 78386dd4242SEric Moore break; 784bf451522SEric Moore } 785bf451522SEric Moore 786bf451522SEric Moore /* 787bf451522SEric Moore * Allow non-SAS & non-NEXUS_LOSS to drop into below code 788bf451522SEric Moore */ 789c2b99750SGustavo A. R. Silva /* Fall through */ 790bf451522SEric Moore 791bf451522SEric Moore case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ 7921da177e4SLinus Torvalds /* Linux handles an unsolicited DID_RESET better 7931da177e4SLinus Torvalds * than an unsolicited DID_ABORT. 7941da177e4SLinus Torvalds */ 7951da177e4SLinus Torvalds sc->result = DID_RESET << 16; 7963012d60bSAlan Cox break; 7971da177e4SLinus Torvalds 7982f187862SKashyap, Desai case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 7992f187862SKashyap, Desai if (ioc->bus_type == FC) 8002f187862SKashyap, Desai sc->result = DID_ERROR << 16; 8012f187862SKashyap, Desai else 8022f187862SKashyap, Desai sc->result = DID_RESET << 16; 8031da177e4SLinus Torvalds break; 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ 8061928d73fSFUJITA Tomonori scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); 807466544d8SMoore, Eric Dean if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) 8081da177e4SLinus Torvalds sc->result=DID_SOFT_ERROR << 16; 809466544d8SMoore, Eric Dean else /* Sufficient data transfer occurred */ 810466544d8SMoore, Eric Dean sc->result = (DID_OK << 16) | scsi_status; 81129dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 812c6c727a1SEric Moore "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", 81329dd3609SEric Moore ioc->name, sc->result, sc->device->channel, sc->device->id)); 8141da177e4SLinus Torvalds break; 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ 8171da177e4SLinus Torvalds /* 8181da177e4SLinus Torvalds * Do upfront check for valid SenseData and give it 8191da177e4SLinus Torvalds * precedence! 8201da177e4SLinus Torvalds */ 8211da177e4SLinus Torvalds sc->result = (DID_OK << 16) | scsi_status; 8229b53b392SKashyap, Desai if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) { 8239b53b392SKashyap, Desai 8249b53b392SKashyap, Desai /* 8259b53b392SKashyap, Desai * For an Errata on LSI53C1030 8269b53b392SKashyap, Desai * When the length of request data 8279b53b392SKashyap, Desai * and transfer data are different 8289b53b392SKashyap, Desai * with result of command (READ or VERIFY), 8299b53b392SKashyap, Desai * DID_SOFT_ERROR is set. 8301da177e4SLinus Torvalds */ 8319b53b392SKashyap, Desai if (ioc->bus_type == SPI) { 832e466e1c6SKashyap, Desai if ((pScsiReq->CDB[0] == READ_6 && ((pScsiReq->CDB[1] & 0x02) == 0)) || 8339b53b392SKashyap, Desai pScsiReq->CDB[0] == READ_10 || 8349b53b392SKashyap, Desai pScsiReq->CDB[0] == READ_12 || 835513382c9Snagalakshmi.nandigama@lsi.com (pScsiReq->CDB[0] == READ_16 && 836513382c9Snagalakshmi.nandigama@lsi.com ((pScsiReq->CDB[1] & 0x02) == 0)) || 8379b53b392SKashyap, Desai pScsiReq->CDB[0] == VERIFY || 8389b53b392SKashyap, Desai pScsiReq->CDB[0] == VERIFY_16) { 8399b53b392SKashyap, Desai if (scsi_bufflen(sc) != 8409b53b392SKashyap, Desai xfer_cnt) { 8419b53b392SKashyap, Desai sc->result = 8429b53b392SKashyap, Desai DID_SOFT_ERROR << 16; 8439b53b392SKashyap, Desai printk(KERN_WARNING "Errata" 8449b53b392SKashyap, Desai "on LSI53C1030 occurred." 8459b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 8469b53b392SKashyap, Desai "xfer_cnt=0x%02x\n", 8479b53b392SKashyap, Desai scsi_bufflen(sc), 8489b53b392SKashyap, Desai xfer_cnt); 8499b53b392SKashyap, Desai } 8509b53b392SKashyap, Desai } 8519b53b392SKashyap, Desai } 8529b53b392SKashyap, Desai 8531da177e4SLinus Torvalds if (xfer_cnt < sc->underflow) { 854466544d8SMoore, Eric Dean if (scsi_status == SAM_STAT_BUSY) 855466544d8SMoore, Eric Dean sc->result = SAM_STAT_BUSY; 856466544d8SMoore, Eric Dean else 8571da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 8581da177e4SLinus Torvalds } 8591da177e4SLinus Torvalds if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { 8601da177e4SLinus Torvalds /* What to do? 8611da177e4SLinus Torvalds */ 8621da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 8631da177e4SLinus Torvalds } 8641da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { 8651da177e4SLinus Torvalds /* Not real sure here either... */ 8661da177e4SLinus Torvalds sc->result = DID_RESET << 16; 8671da177e4SLinus Torvalds } 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds 8706757d6b4SPrakash, Sathya 87129dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 87229dd3609SEric Moore " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", 87329dd3609SEric Moore ioc->name, sc->underflow)); 87429dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 87529dd3609SEric Moore " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt)); 8766757d6b4SPrakash, Sathya 8771da177e4SLinus Torvalds /* Report Queue Full 8781da177e4SLinus Torvalds */ 8791da177e4SLinus Torvalds if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) 8801da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 8811da177e4SLinus Torvalds 8821da177e4SLinus Torvalds break; 8831da177e4SLinus Torvalds 8847e55147fSMoore, Eric case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ 8851928d73fSFUJITA Tomonori scsi_set_resid(sc, 0); 886c2b99750SGustavo A. R. Silva /* Fall through */ 8871da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 8881da177e4SLinus Torvalds case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ 8891da177e4SLinus Torvalds sc->result = (DID_OK << 16) | scsi_status; 8901da177e4SLinus Torvalds if (scsi_state == 0) { 8911da177e4SLinus Torvalds ; 8929b53b392SKashyap, Desai } else if (scsi_state & 8939b53b392SKashyap, Desai MPI_SCSI_STATE_AUTOSENSE_VALID) { 8949b53b392SKashyap, Desai 8959b53b392SKashyap, Desai /* 8969b53b392SKashyap, Desai * For potential trouble on LSI53C1030. 8979b53b392SKashyap, Desai * (date:2007.xx.) 8989b53b392SKashyap, Desai * It is checked whether the length of 8999b53b392SKashyap, Desai * request data is equal to 9009b53b392SKashyap, Desai * the length of transfer and residual. 9019b53b392SKashyap, Desai * MEDIUM_ERROR is set by incorrect data. 9029b53b392SKashyap, Desai */ 9039b53b392SKashyap, Desai if ((ioc->bus_type == SPI) && 9049b53b392SKashyap, Desai (sc->sense_buffer[2] & 0x20)) { 9059b53b392SKashyap, Desai u32 difftransfer; 9069b53b392SKashyap, Desai difftransfer = 9079b53b392SKashyap, Desai sc->sense_buffer[3] << 24 | 9089b53b392SKashyap, Desai sc->sense_buffer[4] << 16 | 9099b53b392SKashyap, Desai sc->sense_buffer[5] << 8 | 9109b53b392SKashyap, Desai sc->sense_buffer[6]; 9119b53b392SKashyap, Desai if (((sc->sense_buffer[3] & 0x80) == 9129b53b392SKashyap, Desai 0x80) && (scsi_bufflen(sc) 9139b53b392SKashyap, Desai != xfer_cnt)) { 9149b53b392SKashyap, Desai sc->sense_buffer[2] = 9159b53b392SKashyap, Desai MEDIUM_ERROR; 9169b53b392SKashyap, Desai sc->sense_buffer[12] = 0xff; 9179b53b392SKashyap, Desai sc->sense_buffer[13] = 0xff; 9189b53b392SKashyap, Desai printk(KERN_WARNING"Errata" 9199b53b392SKashyap, Desai "on LSI53C1030 occurred." 9209b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 9219b53b392SKashyap, Desai "xfer_cnt=0x%02x\n" , 9229b53b392SKashyap, Desai scsi_bufflen(sc), 9239b53b392SKashyap, Desai xfer_cnt); 9249b53b392SKashyap, Desai } 9259b53b392SKashyap, Desai if (((sc->sense_buffer[3] & 0x80) 9269b53b392SKashyap, Desai != 0x80) && 9279b53b392SKashyap, Desai (scsi_bufflen(sc) != 9289b53b392SKashyap, Desai xfer_cnt + difftransfer)) { 9299b53b392SKashyap, Desai sc->sense_buffer[2] = 9309b53b392SKashyap, Desai MEDIUM_ERROR; 9319b53b392SKashyap, Desai sc->sense_buffer[12] = 0xff; 9329b53b392SKashyap, Desai sc->sense_buffer[13] = 0xff; 9339b53b392SKashyap, Desai printk(KERN_WARNING 9349b53b392SKashyap, Desai "Errata on LSI53C1030 occurred" 9359b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 9369b53b392SKashyap, Desai " xfer_cnt=0x%02x," 9379b53b392SKashyap, Desai "difftransfer=0x%02x\n", 9389b53b392SKashyap, Desai scsi_bufflen(sc), 9399b53b392SKashyap, Desai xfer_cnt, 9409b53b392SKashyap, Desai difftransfer); 9419b53b392SKashyap, Desai } 9429b53b392SKashyap, Desai } 9439b53b392SKashyap, Desai 9441da177e4SLinus Torvalds /* 9451da177e4SLinus Torvalds * If running against circa 200003dd 909 MPT f/w, 9461da177e4SLinus Torvalds * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL 9471da177e4SLinus Torvalds * (QUEUE_FULL) returned from device! --> get 0x0000?128 9481da177e4SLinus Torvalds * and with SenseBytes set to 0. 9491da177e4SLinus Torvalds */ 9501da177e4SLinus Torvalds if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL) 9511da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 9521da177e4SLinus Torvalds 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds else if (scsi_state & 9551da177e4SLinus Torvalds (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS) 9561da177e4SLinus Torvalds ) { 9571da177e4SLinus Torvalds /* 9581da177e4SLinus Torvalds * What to do? 9591da177e4SLinus Torvalds */ 9601da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 9611da177e4SLinus Torvalds } 9621da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { 9631da177e4SLinus Torvalds /* Not real sure here either... */ 9641da177e4SLinus Torvalds sc->result = DID_RESET << 16; 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) { 9671da177e4SLinus Torvalds /* Device Inq. data indicates that it supports 9681da177e4SLinus Torvalds * QTags, but rejects QTag messages. 9691da177e4SLinus Torvalds * This command completed OK. 9701da177e4SLinus Torvalds * 9711da177e4SLinus Torvalds * Not real sure here either so do nothing... */ 9721da177e4SLinus Torvalds } 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) 9751da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 9761da177e4SLinus Torvalds 9771da177e4SLinus Torvalds /* Add handling of: 9781da177e4SLinus Torvalds * Reservation Conflict, Busy, 9791da177e4SLinus Torvalds * Command Terminated, CHECK 9801da177e4SLinus Torvalds */ 9811da177e4SLinus Torvalds break; 9821da177e4SLinus Torvalds 9831da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 9841da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 9851da177e4SLinus Torvalds break; 9861da177e4SLinus Torvalds 9871da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ 9881da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ 9891da177e4SLinus Torvalds case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ 9901da177e4SLinus Torvalds case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ 9911da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ 9921da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ 9931da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 9941da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ 9951da177e4SLinus Torvalds default: 9961da177e4SLinus Torvalds /* 9971da177e4SLinus Torvalds * What to do? 9981da177e4SLinus Torvalds */ 9991da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 10001da177e4SLinus Torvalds break; 10011da177e4SLinus Torvalds 10021da177e4SLinus Torvalds } /* switch(status) */ 10031da177e4SLinus Torvalds 10046757d6b4SPrakash, Sathya #ifdef CONFIG_FUSION_LOGGING 10056757d6b4SPrakash, Sathya if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY)) 10066757d6b4SPrakash, Sathya mptscsih_info_scsiio(ioc, sc, pScsiReply); 1007c6c727a1SEric Moore #endif 1008c6c727a1SEric Moore 10091da177e4SLinus Torvalds } /* end of address reply case */ 1010fea98403SKashyap, Desai out: 10111da177e4SLinus Torvalds /* Unmap the DMA buffers, if any. */ 10121928d73fSFUJITA Tomonori scsi_dma_unmap(sc); 10131da177e4SLinus Torvalds 10141da177e4SLinus Torvalds sc->scsi_done(sc); /* Issue the command callback */ 10151da177e4SLinus Torvalds 10161da177e4SLinus Torvalds /* Free Chain buffers */ 10171da177e4SLinus Torvalds mptscsih_freeChainBuffers(ioc, req_idx); 10181da177e4SLinus Torvalds return 1; 10191da177e4SLinus Torvalds } 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds /* 10221da177e4SLinus Torvalds * mptscsih_flush_running_cmds - For each command found, search 10231da177e4SLinus Torvalds * Scsi_Host instance taskQ and reply to OS. 10241da177e4SLinus Torvalds * Called only if recovering from a FW reload. 10251da177e4SLinus Torvalds * @hd: Pointer to a SCSI HOST structure 10261da177e4SLinus Torvalds * 10271da177e4SLinus Torvalds * Returns: None. 10281da177e4SLinus Torvalds * 10291da177e4SLinus Torvalds * Must be called while new I/Os are being queued. 10301da177e4SLinus Torvalds */ 1031e62cca19Skashyap.desai@lsi.com void 10321da177e4SLinus Torvalds mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) 10331da177e4SLinus Torvalds { 10341da177e4SLinus Torvalds MPT_ADAPTER *ioc = hd->ioc; 1035e8206381SEric Moore struct scsi_cmnd *sc; 1036e8206381SEric Moore SCSIIORequest_t *mf = NULL; 10371da177e4SLinus Torvalds int ii; 1038e8206381SEric Moore int channel, id; 10391da177e4SLinus Torvalds 1040e8206381SEric Moore for (ii= 0; ii < ioc->req_depth; ii++) { 1041e8206381SEric Moore sc = mptscsih_getclear_scsi_lookup(ioc, ii); 1042e8206381SEric Moore if (!sc) 10433dc0b03fSEric Moore continue; 1044e8206381SEric Moore mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); 1045e8206381SEric Moore if (!mf) 1046e8206381SEric Moore continue; 1047e8206381SEric Moore channel = mf->Bus; 1048e8206381SEric Moore id = mf->TargetID; 1049e8206381SEric Moore mptscsih_freeChainBuffers(ioc, ii); 1050e8206381SEric Moore mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); 1051e8206381SEric Moore if ((unsigned char *)mf != sc->host_scribble) 1052e8206381SEric Moore continue; 1053e8206381SEric Moore scsi_dma_unmap(sc); 1054e8206381SEric Moore sc->result = DID_RESET << 16; 1055e8206381SEric Moore sc->host_scribble = NULL; 10562f187862SKashyap, Desai dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT 10572f187862SKashyap, Desai "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, " 10582f187862SKashyap, Desai "idx=%x\n", ioc->name, channel, id, sc, mf, ii)); 1059e8206381SEric Moore sc->scsi_done(sc); 10601da177e4SLinus Torvalds } 10611da177e4SLinus Torvalds } 1062e62cca19Skashyap.desai@lsi.com EXPORT_SYMBOL(mptscsih_flush_running_cmds); 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds /* 10651da177e4SLinus Torvalds * mptscsih_search_running_cmds - Delete any commands associated 10661da177e4SLinus Torvalds * with the specified target and lun. Function called only 10671da177e4SLinus Torvalds * when a lun is disable by mid-layer. 10681da177e4SLinus Torvalds * Do NOT access the referenced scsi_cmnd structure or 10691da177e4SLinus Torvalds * members. Will cause either a paging or NULL ptr error. 107005e8ec17SMichael Reed * (BUT, BUT, BUT, the code does reference it! - mdr) 10711da177e4SLinus Torvalds * @hd: Pointer to a SCSI HOST structure 1072c7c82987SMoore, Eric Dean * @vdevice: per device private data 10731da177e4SLinus Torvalds * 10741da177e4SLinus Torvalds * Returns: None. 10751da177e4SLinus Torvalds * 10761da177e4SLinus Torvalds * Called from slave_destroy. 10771da177e4SLinus Torvalds */ 10781da177e4SLinus Torvalds static void 1079c7c82987SMoore, Eric Dean mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) 10801da177e4SLinus Torvalds { 10811da177e4SLinus Torvalds SCSIIORequest_t *mf = NULL; 10821da177e4SLinus Torvalds int ii; 1083466544d8SMoore, Eric Dean struct scsi_cmnd *sc; 1084793955f5SEric Moore struct scsi_lun lun; 1085e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 1086e8206381SEric Moore unsigned long flags; 10871da177e4SLinus Torvalds 1088e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 1089e8206381SEric Moore for (ii = 0; ii < ioc->req_depth; ii++) { 1090e8206381SEric Moore if ((sc = ioc->ScsiLookup[ii]) != NULL) { 10911da177e4SLinus Torvalds 1092e80b002bSEric Moore mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); 10933dc0b03fSEric Moore if (mf == NULL) 10943dc0b03fSEric Moore continue; 1095cc78d30aSEric Moore /* If the device is a hidden raid component, then its 1096cc78d30aSEric Moore * expected that the mf->function will be RAID_SCSI_IO 1097cc78d30aSEric Moore */ 1098cc78d30aSEric Moore if (vdevice->vtarget->tflags & 1099cc78d30aSEric Moore MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function != 1100cc78d30aSEric Moore MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) 1101cc78d30aSEric Moore continue; 1102cc78d30aSEric Moore 1103793955f5SEric Moore int_to_scsilun(vdevice->lun, &lun); 1104793955f5SEric Moore if ((mf->Bus != vdevice->vtarget->channel) || 1105793955f5SEric Moore (mf->TargetID != vdevice->vtarget->id) || 1106793955f5SEric Moore memcmp(lun.scsi_lun, mf->LUN, 8)) 11071da177e4SLinus Torvalds continue; 11081da177e4SLinus Torvalds 11093dc0b03fSEric Moore if ((unsigned char *)mf != sc->host_scribble) 11103dc0b03fSEric Moore continue; 1111e8206381SEric Moore ioc->ScsiLookup[ii] = NULL; 1112e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 1113e8206381SEric Moore mptscsih_freeChainBuffers(ioc, ii); 1114e8206381SEric Moore mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); 11151928d73fSFUJITA Tomonori scsi_dma_unmap(sc); 1116466544d8SMoore, Eric Dean sc->host_scribble = NULL; 1117466544d8SMoore, Eric Dean sc->result = DID_NO_CONNECT << 16; 11182f187862SKashyap, Desai dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, 11192f187862SKashyap, Desai MYIOC_s_FMT "completing cmds: fw_channel %d, " 11202f187862SKashyap, Desai "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, 11212f187862SKashyap, Desai vdevice->vtarget->channel, vdevice->vtarget->id, 11222f187862SKashyap, Desai sc, mf, ii)); 1123466544d8SMoore, Eric Dean sc->scsi_done(sc); 1124e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 11251da177e4SLinus Torvalds } 11261da177e4SLinus Torvalds } 1127e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 11281da177e4SLinus Torvalds return; 11291da177e4SLinus Torvalds } 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11321da177e4SLinus Torvalds 11331da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11341da177e4SLinus Torvalds /* 11351da177e4SLinus Torvalds * mptscsih_report_queue_full - Report QUEUE_FULL status returned 11361da177e4SLinus Torvalds * from a SCSI target device. 11371da177e4SLinus Torvalds * @sc: Pointer to scsi_cmnd structure 11381da177e4SLinus Torvalds * @pScsiReply: Pointer to SCSIIOReply_t 11391da177e4SLinus Torvalds * @pScsiReq: Pointer to original SCSI request 11401da177e4SLinus Torvalds * 11411da177e4SLinus Torvalds * This routine periodically reports QUEUE_FULL status returned from a 11421da177e4SLinus Torvalds * SCSI target device. It reports this to the console via kernel 11431da177e4SLinus Torvalds * printk() API call, not more than once every 10 seconds. 11441da177e4SLinus Torvalds */ 11451da177e4SLinus Torvalds static void 11461da177e4SLinus Torvalds mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq) 11471da177e4SLinus Torvalds { 11481da177e4SLinus Torvalds long time = jiffies; 11491da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1150e80b002bSEric Moore MPT_ADAPTER *ioc; 11511da177e4SLinus Torvalds 11520d0c7974SMoore, Eric Dean if (sc->device == NULL) 11530d0c7974SMoore, Eric Dean return; 11540d0c7974SMoore, Eric Dean if (sc->device->host == NULL) 11550d0c7974SMoore, Eric Dean return; 1156e7eae9f6SEric Moore if ((hd = shost_priv(sc->device->host)) == NULL) 11570d0c7974SMoore, Eric Dean return; 1158e80b002bSEric Moore ioc = hd->ioc; 11590d0c7974SMoore, Eric Dean if (time - hd->last_queue_full > 10 * HZ) { 11609cb78c16SHannes Reinecke dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%llu) reported QUEUE_FULL!\n", 1161e80b002bSEric Moore ioc->name, 0, sc->device->id, sc->device->lun)); 11620d0c7974SMoore, Eric Dean hd->last_queue_full = time; 11631da177e4SLinus Torvalds } 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 11661da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11671da177e4SLinus Torvalds /* 11681da177e4SLinus Torvalds * mptscsih_remove - Removed scsi devices 11691da177e4SLinus Torvalds * @pdev: Pointer to pci_dev structure 11701da177e4SLinus Torvalds * 11711da177e4SLinus Torvalds * 11721da177e4SLinus Torvalds */ 11730d0c7974SMoore, Eric Dean void 11741da177e4SLinus Torvalds mptscsih_remove(struct pci_dev *pdev) 11751da177e4SLinus Torvalds { 11761da177e4SLinus Torvalds MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 11771da177e4SLinus Torvalds struct Scsi_Host *host = ioc->sh; 11781da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 11790d0c7974SMoore, Eric Dean int sz1; 11801da177e4SLinus Torvalds 1181e7eae9f6SEric Moore if((hd = shost_priv(host)) == NULL) 11820d0c7974SMoore, Eric Dean return; 11830d0c7974SMoore, Eric Dean 1184d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(pdev); 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds sz1=0; 11871da177e4SLinus Torvalds 1188e8206381SEric Moore if (ioc->ScsiLookup != NULL) { 1189e80b002bSEric Moore sz1 = ioc->req_depth * sizeof(void *); 1190e8206381SEric Moore kfree(ioc->ScsiLookup); 1191e8206381SEric Moore ioc->ScsiLookup = NULL; 11921da177e4SLinus Torvalds } 11931da177e4SLinus Torvalds 1194e80b002bSEric Moore dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 11951da177e4SLinus Torvalds "Free'd ScsiLookup (%d) memory\n", 1196e80b002bSEric Moore ioc->name, sz1)); 11971da177e4SLinus Torvalds 11980d0c7974SMoore, Eric Dean kfree(hd->info_kbuf); 11990d0c7974SMoore, Eric Dean 12001da177e4SLinus Torvalds /* NULL the Scsi_Host pointer 12011da177e4SLinus Torvalds */ 1202e80b002bSEric Moore ioc->sh = NULL; 12031da177e4SLinus Torvalds 12041da177e4SLinus Torvalds scsi_host_put(host); 12050d0c7974SMoore, Eric Dean 12060d0c7974SMoore, Eric Dean mpt_detach(pdev); 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds } 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12111da177e4SLinus Torvalds /* 12121da177e4SLinus Torvalds * mptscsih_shutdown - reboot notifier 12131da177e4SLinus Torvalds * 12141da177e4SLinus Torvalds */ 12150d0c7974SMoore, Eric Dean void 1216d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(struct pci_dev *pdev) 12171da177e4SLinus Torvalds { 12181da177e4SLinus Torvalds } 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds #ifdef CONFIG_PM 12211da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12221da177e4SLinus Torvalds /* 12230d0c7974SMoore, Eric Dean * mptscsih_suspend - Fusion MPT scsi driver suspend routine. 12241da177e4SLinus Torvalds * 12251da177e4SLinus Torvalds * 12261da177e4SLinus Torvalds */ 12270d0c7974SMoore, Eric Dean int 12288d189f72SPavel Machek mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) 12291da177e4SLinus Torvalds { 12304d4109d0SPrakash, Sathya MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 12314d4109d0SPrakash, Sathya 12324d4109d0SPrakash, Sathya scsi_block_requests(ioc->sh); 12334d4109d0SPrakash, Sathya flush_scheduled_work(); 1234d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(pdev); 12350d0c7974SMoore, Eric Dean return mpt_suspend(pdev,state); 12361da177e4SLinus Torvalds } 12371da177e4SLinus Torvalds 12381da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12391da177e4SLinus Torvalds /* 12401da177e4SLinus Torvalds * mptscsih_resume - Fusion MPT scsi driver resume routine. 12411da177e4SLinus Torvalds * 12421da177e4SLinus Torvalds * 12431da177e4SLinus Torvalds */ 12440d0c7974SMoore, Eric Dean int 12451da177e4SLinus Torvalds mptscsih_resume(struct pci_dev *pdev) 12461da177e4SLinus Torvalds { 12474d4109d0SPrakash, Sathya MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 12484d4109d0SPrakash, Sathya int rc; 12494d4109d0SPrakash, Sathya 12504d4109d0SPrakash, Sathya rc = mpt_resume(pdev); 12514d4109d0SPrakash, Sathya scsi_unblock_requests(ioc->sh); 12524d4109d0SPrakash, Sathya return rc; 12531da177e4SLinus Torvalds } 12541da177e4SLinus Torvalds 12551da177e4SLinus Torvalds #endif 12561da177e4SLinus Torvalds 12571da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12581da177e4SLinus Torvalds /** 12591da177e4SLinus Torvalds * mptscsih_info - Return information about MPT adapter 12601da177e4SLinus Torvalds * @SChost: Pointer to Scsi_Host structure 12611da177e4SLinus Torvalds * 12621da177e4SLinus Torvalds * (linux scsi_host_template.info routine) 12631da177e4SLinus Torvalds * 12641da177e4SLinus Torvalds * Returns pointer to buffer where information was written. 12651da177e4SLinus Torvalds */ 12660d0c7974SMoore, Eric Dean const char * 12671da177e4SLinus Torvalds mptscsih_info(struct Scsi_Host *SChost) 12681da177e4SLinus Torvalds { 12691da177e4SLinus Torvalds MPT_SCSI_HOST *h; 12701da177e4SLinus Torvalds int size = 0; 12711da177e4SLinus Torvalds 1272e7eae9f6SEric Moore h = shost_priv(SChost); 12730d0c7974SMoore, Eric Dean 12740d0c7974SMoore, Eric Dean if (h->info_kbuf == NULL) 12750d0c7974SMoore, Eric Dean if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) 12760d0c7974SMoore, Eric Dean return h->info_kbuf; 12770d0c7974SMoore, Eric Dean h->info_kbuf[0] = '\0'; 12780d0c7974SMoore, Eric Dean 12790d0c7974SMoore, Eric Dean mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); 12800d0c7974SMoore, Eric Dean h->info_kbuf[size-1] = '\0'; 12811da177e4SLinus Torvalds 12820d0c7974SMoore, Eric Dean return h->info_kbuf; 12831da177e4SLinus Torvalds } 12841da177e4SLinus Torvalds 1285cac19703SAl Viro int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host) 12861da177e4SLinus Torvalds { 1287e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 12881da177e4SLinus Torvalds MPT_ADAPTER *ioc = hd->ioc; 12891da177e4SLinus Torvalds 1290cac19703SAl Viro seq_printf(m, "%s: %s, ", ioc->name, ioc->prod_name); 1291cac19703SAl Viro seq_printf(m, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); 1292cac19703SAl Viro seq_printf(m, "Ports=%d, ", ioc->facts.NumberOfPorts); 1293cac19703SAl Viro seq_printf(m, "MaxQ=%d\n", ioc->req_depth); 12941da177e4SLinus Torvalds 1295cac19703SAl Viro return 0; 12961da177e4SLinus Torvalds } 12971da177e4SLinus Torvalds 12981da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12991da177e4SLinus Torvalds #define ADD_INDEX_LOG(req_ent) do { } while(0) 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13021da177e4SLinus Torvalds /** 13031da177e4SLinus Torvalds * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. 13041da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure 13051da177e4SLinus Torvalds * 13061da177e4SLinus Torvalds * (linux scsi_host_template.queuecommand routine) 13071da177e4SLinus Torvalds * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest 13081da177e4SLinus Torvalds * from a linux scsi_cmnd request and send it to the IOC. 13091da177e4SLinus Torvalds * 13101da177e4SLinus Torvalds * Returns 0. (rtn value discarded by linux scsi mid-layer) 13111da177e4SLinus Torvalds */ 13120d0c7974SMoore, Eric Dean int 1313a48ac9e5SMatthew Wilcox mptscsih_qcmd(struct scsi_cmnd *SCpnt) 13141da177e4SLinus Torvalds { 13151da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 13161da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 13171da177e4SLinus Torvalds SCSIIORequest_t *pScsiReq; 1318a69de507SEric Moore VirtDevice *vdevice = SCpnt->device->hostdata; 13191da177e4SLinus Torvalds u32 datalen; 13201da177e4SLinus Torvalds u32 scsictl; 13211da177e4SLinus Torvalds u32 scsidir; 13221da177e4SLinus Torvalds u32 cmd_len; 13231da177e4SLinus Torvalds int my_idx; 13241da177e4SLinus Torvalds int ii; 13256757d6b4SPrakash, Sathya MPT_ADAPTER *ioc; 13261da177e4SLinus Torvalds 1327e7eae9f6SEric Moore hd = shost_priv(SCpnt->device->host); 13286757d6b4SPrakash, Sathya ioc = hd->ioc; 13291da177e4SLinus Torvalds 1330a48ac9e5SMatthew Wilcox dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p\n", 1331a48ac9e5SMatthew Wilcox ioc->name, SCpnt)); 13321da177e4SLinus Torvalds 133356cee8d5SKashyap, Desai if (ioc->taskmgmt_quiesce_io) 13341da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds /* 13371da177e4SLinus Torvalds * Put together a MPT SCSI request... 13381da177e4SLinus Torvalds */ 1339e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { 13406757d6b4SPrakash, Sathya dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", 13416757d6b4SPrakash, Sathya ioc->name)); 13421da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 13431da177e4SLinus Torvalds } 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds pScsiReq = (SCSIIORequest_t *) mf; 13461da177e4SLinus Torvalds 13471da177e4SLinus Torvalds my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 13481da177e4SLinus Torvalds 13491da177e4SLinus Torvalds ADD_INDEX_LOG(my_idx); 13501da177e4SLinus Torvalds 13510d0c7974SMoore, Eric Dean /* TUR's being issued with scsictl=0x02000000 (DATA_IN)! 13521da177e4SLinus Torvalds * Seems we may receive a buffer (datalen>0) even when there 13531da177e4SLinus Torvalds * will be no data transfer! GRRRRR... 13541da177e4SLinus Torvalds */ 13551da177e4SLinus Torvalds if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { 13561928d73fSFUJITA Tomonori datalen = scsi_bufflen(SCpnt); 13571da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ 13581da177e4SLinus Torvalds } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { 13591928d73fSFUJITA Tomonori datalen = scsi_bufflen(SCpnt); 13601da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ 13611da177e4SLinus Torvalds } else { 13621da177e4SLinus Torvalds datalen = 0; 13631da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER; 13641da177e4SLinus Torvalds } 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds /* Default to untagged. Once a target structure has been allocated, 13671da177e4SLinus Torvalds * use the Inquiry data to determine if device supports tagged. 13681da177e4SLinus Torvalds */ 13694e6f767dSChristoph Hellwig if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) && 13704e6f767dSChristoph Hellwig SCpnt->device->tagged_supported) 13711da177e4SLinus Torvalds scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; 13724e6f767dSChristoph Hellwig else 137365f89c23SKashyap, Desai scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; 137465f89c23SKashyap, Desai 13751da177e4SLinus Torvalds 13761da177e4SLinus Torvalds /* Use the above information to set up the message frame 13771da177e4SLinus Torvalds */ 1378a69de507SEric Moore pScsiReq->TargetID = (u8) vdevice->vtarget->id; 1379a69de507SEric Moore pScsiReq->Bus = vdevice->vtarget->channel; 13801da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 1381a69de507SEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 1382c92f222eSJames Bottomley pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; 1383c92f222eSJames Bottomley else 13841da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; 13851da177e4SLinus Torvalds pScsiReq->CDBLength = SCpnt->cmd_len; 13861da177e4SLinus Torvalds pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; 13871da177e4SLinus Torvalds pScsiReq->Reserved = 0; 138814d0f0b0SKashyap, Desai pScsiReq->MsgFlags = mpt_msg_flags(ioc); 1389793955f5SEric Moore int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); 13901da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(scsictl); 13911da177e4SLinus Torvalds 13921da177e4SLinus Torvalds /* 13931da177e4SLinus Torvalds * Write SCSI CDB into the message 13941da177e4SLinus Torvalds */ 13951da177e4SLinus Torvalds cmd_len = SCpnt->cmd_len; 13961da177e4SLinus Torvalds for (ii=0; ii < cmd_len; ii++) 13971da177e4SLinus Torvalds pScsiReq->CDB[ii] = SCpnt->cmnd[ii]; 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds for (ii=cmd_len; ii < 16; ii++) 14001da177e4SLinus Torvalds pScsiReq->CDB[ii] = 0; 14011da177e4SLinus Torvalds 14021da177e4SLinus Torvalds /* DataLength */ 14031da177e4SLinus Torvalds pScsiReq->DataLength = cpu_to_le32(datalen); 14041da177e4SLinus Torvalds 14051da177e4SLinus Torvalds /* SenseBuffer low address */ 1406e80b002bSEric Moore pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma 14071da177e4SLinus Torvalds + (my_idx * MPT_SENSE_BUFFER_ALLOC)); 14081da177e4SLinus Torvalds 14091da177e4SLinus Torvalds /* Now add the SG list 14101da177e4SLinus Torvalds * Always have a SGE even if null length. 14111da177e4SLinus Torvalds */ 14121da177e4SLinus Torvalds if (datalen == 0) { 14131da177e4SLinus Torvalds /* Add a NULL SGE */ 141414d0f0b0SKashyap, Desai ioc->add_sge((char *)&pScsiReq->SGL, 141514d0f0b0SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_READ | 0, 14161da177e4SLinus Torvalds (dma_addr_t) -1); 14171da177e4SLinus Torvalds } else { 14181da177e4SLinus Torvalds /* Add a 32 or 64 bit SGE */ 1419e80b002bSEric Moore if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) 14201da177e4SLinus Torvalds goto fail; 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 14233dc0b03fSEric Moore SCpnt->host_scribble = (unsigned char *)mf; 1424e8206381SEric Moore mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt); 14251da177e4SLinus Torvalds 1426e80b002bSEric Moore mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); 14276757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", 14286757d6b4SPrakash, Sathya ioc->name, SCpnt, mf, my_idx)); 142929dd3609SEric Moore DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf); 14301da177e4SLinus Torvalds return 0; 14311da177e4SLinus Torvalds 14321da177e4SLinus Torvalds fail: 1433e80b002bSEric Moore mptscsih_freeChainBuffers(ioc, my_idx); 1434e80b002bSEric Moore mpt_free_msg_frame(ioc, mf); 14351da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 14361da177e4SLinus Torvalds } 14371da177e4SLinus Torvalds 14381da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 14391da177e4SLinus Torvalds /* 14401da177e4SLinus Torvalds * mptscsih_freeChainBuffers - Function to free chain buffers associated 14411da177e4SLinus Torvalds * with a SCSI IO request 14421da177e4SLinus Torvalds * @hd: Pointer to the MPT_SCSI_HOST instance 14431da177e4SLinus Torvalds * @req_idx: Index of the SCSI IO request frame. 14441da177e4SLinus Torvalds * 14451da177e4SLinus Torvalds * Called if SG chain buffer allocation fails and mptscsih callbacks. 14461da177e4SLinus Torvalds * No return. 14471da177e4SLinus Torvalds */ 14481da177e4SLinus Torvalds static void 14491da177e4SLinus Torvalds mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) 14501da177e4SLinus Torvalds { 14511da177e4SLinus Torvalds MPT_FRAME_HDR *chain; 14521da177e4SLinus Torvalds unsigned long flags; 14531da177e4SLinus Torvalds int chain_idx; 14541da177e4SLinus Torvalds int next; 14551da177e4SLinus Torvalds 14561da177e4SLinus Torvalds /* Get the first chain index and reset 14571da177e4SLinus Torvalds * tracker state. 14581da177e4SLinus Torvalds */ 14591da177e4SLinus Torvalds chain_idx = ioc->ReqToChain[req_idx]; 14601da177e4SLinus Torvalds ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN; 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds while (chain_idx != MPT_HOST_NO_CHAIN) { 14631da177e4SLinus Torvalds 14641da177e4SLinus Torvalds /* Save the next chain buffer index */ 14651da177e4SLinus Torvalds next = ioc->ChainToChain[chain_idx]; 14661da177e4SLinus Torvalds 14671da177e4SLinus Torvalds /* Free this chain buffer and reset 14681da177e4SLinus Torvalds * tracker 14691da177e4SLinus Torvalds */ 14701da177e4SLinus Torvalds ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN; 14711da177e4SLinus Torvalds 14721da177e4SLinus Torvalds chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer 14731da177e4SLinus Torvalds + (chain_idx * ioc->req_sz)); 14741da177e4SLinus Torvalds 14751da177e4SLinus Torvalds spin_lock_irqsave(&ioc->FreeQlock, flags); 14761da177e4SLinus Torvalds list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ); 14771da177e4SLinus Torvalds spin_unlock_irqrestore(&ioc->FreeQlock, flags); 14781da177e4SLinus Torvalds 14796757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n", 14801da177e4SLinus Torvalds ioc->name, chain_idx)); 14811da177e4SLinus Torvalds 14821da177e4SLinus Torvalds /* handle next */ 14831da177e4SLinus Torvalds chain_idx = next; 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds return; 14861da177e4SLinus Torvalds } 14871da177e4SLinus Torvalds 14881da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 14891da177e4SLinus Torvalds /* 14901da177e4SLinus Torvalds * Reset Handling 14911da177e4SLinus Torvalds */ 14921da177e4SLinus Torvalds 14931da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1494cd2c6191SEric Moore /** 14951da177e4SLinus Torvalds * mptscsih_IssueTaskMgmt - Generic send Task Management function. 14961da177e4SLinus Torvalds * @hd: Pointer to MPT_SCSI_HOST structure 14971da177e4SLinus Torvalds * @type: Task Management type 14981544d677SRandy Dunlap * @channel: channel number for task management 1499793955f5SEric Moore * @id: Logical Target ID for reset (if appropriate) 15001da177e4SLinus Torvalds * @lun: Logical Unit for reset (if appropriate) 15011da177e4SLinus Torvalds * @ctx2abort: Context for the task to be aborted (if appropriate) 15021544d677SRandy Dunlap * @timeout: timeout for task management control 15031da177e4SLinus Torvalds * 15041da177e4SLinus Torvalds * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) 15051da177e4SLinus Torvalds * or a non-interrupt thread. In the former, must not call schedule(). 15061da177e4SLinus Torvalds * 15071da177e4SLinus Torvalds * Not all fields are meaningfull for all task types. 15081da177e4SLinus Torvalds * 1509cd2c6191SEric Moore * Returns 0 for SUCCESS, or FAILED. 1510cd2c6191SEric Moore * 1511cd2c6191SEric Moore **/ 15121ba9ab2eSKashyap, Desai int 15139cb78c16SHannes Reinecke mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u64 lun, 15141ba9ab2eSKashyap, Desai int ctx2abort, ulong timeout) 15151da177e4SLinus Torvalds { 15161da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 15171da177e4SLinus Torvalds SCSITaskMgmt_t *pScsiTm; 15181da177e4SLinus Torvalds int ii; 15191da177e4SLinus Torvalds int retval; 1520e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 15211ba9ab2eSKashyap, Desai unsigned long timeleft; 15221ba9ab2eSKashyap, Desai u8 issue_hard_reset; 15231ba9ab2eSKashyap, Desai u32 ioc_raw_state; 15241ba9ab2eSKashyap, Desai unsigned long time_count; 15251ba9ab2eSKashyap, Desai 15261ba9ab2eSKashyap, Desai issue_hard_reset = 0; 15271ba9ab2eSKashyap, Desai ioc_raw_state = mpt_GetIocState(ioc, 0); 15281ba9ab2eSKashyap, Desai 15291ba9ab2eSKashyap, Desai if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { 15301ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT 15311ba9ab2eSKashyap, Desai "TaskMgmt type=%x: IOC Not operational (0x%x)!\n", 15321ba9ab2eSKashyap, Desai ioc->name, type, ioc_raw_state); 15331ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", 15341ba9ab2eSKashyap, Desai ioc->name, __func__); 15351ba9ab2eSKashyap, Desai if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) 15361ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset " 15371ba9ab2eSKashyap, Desai "FAILED!!\n", ioc->name); 15381ba9ab2eSKashyap, Desai return 0; 15391ba9ab2eSKashyap, Desai } 15401ba9ab2eSKashyap, Desai 154198cbe371Skashyap.desai@lsi.com /* DOORBELL ACTIVE check is not required if 154298cbe371Skashyap.desai@lsi.com * MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported. 154398cbe371Skashyap.desai@lsi.com */ 154498cbe371Skashyap.desai@lsi.com 154598cbe371Skashyap.desai@lsi.com if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) 154698cbe371Skashyap.desai@lsi.com && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) && 154798cbe371Skashyap.desai@lsi.com (ioc_raw_state & MPI_DOORBELL_ACTIVE)) { 15481ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT 15491ba9ab2eSKashyap, Desai "TaskMgmt type=%x: ioc_state: " 15501ba9ab2eSKashyap, Desai "DOORBELL_ACTIVE (0x%x)!\n", 15511ba9ab2eSKashyap, Desai ioc->name, type, ioc_raw_state); 15521ba9ab2eSKashyap, Desai return FAILED; 15531ba9ab2eSKashyap, Desai } 15541ba9ab2eSKashyap, Desai 15551ba9ab2eSKashyap, Desai mutex_lock(&ioc->taskmgmt_cmds.mutex); 15561ba9ab2eSKashyap, Desai if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { 15571ba9ab2eSKashyap, Desai mf = NULL; 15581ba9ab2eSKashyap, Desai retval = FAILED; 15591ba9ab2eSKashyap, Desai goto out; 15601ba9ab2eSKashyap, Desai } 15611da177e4SLinus Torvalds 15621da177e4SLinus Torvalds /* Return Fail to calling function if no message frames available. 15631da177e4SLinus Torvalds */ 1564e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { 15651ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 15661ba9ab2eSKashyap, Desai "TaskMgmt no msg frames!!\n", ioc->name)); 15671ba9ab2eSKashyap, Desai retval = FAILED; 15681ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 15691ba9ab2eSKashyap, Desai goto out; 15701da177e4SLinus Torvalds } 15711ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", 1572e80b002bSEric Moore ioc->name, mf)); 15731da177e4SLinus Torvalds 15741da177e4SLinus Torvalds /* Format the Request 15751da177e4SLinus Torvalds */ 15761da177e4SLinus Torvalds pScsiTm = (SCSITaskMgmt_t *) mf; 1577793955f5SEric Moore pScsiTm->TargetID = id; 15781da177e4SLinus Torvalds pScsiTm->Bus = channel; 15791da177e4SLinus Torvalds pScsiTm->ChainOffset = 0; 15801da177e4SLinus Torvalds pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; 15811da177e4SLinus Torvalds 15821da177e4SLinus Torvalds pScsiTm->Reserved = 0; 15831da177e4SLinus Torvalds pScsiTm->TaskType = type; 15841da177e4SLinus Torvalds pScsiTm->Reserved1 = 0; 15851da177e4SLinus Torvalds pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) 15861da177e4SLinus Torvalds ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; 15871da177e4SLinus Torvalds 1588793955f5SEric Moore int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); 15891da177e4SLinus Torvalds 15901da177e4SLinus Torvalds for (ii=0; ii < 7; ii++) 15911da177e4SLinus Torvalds pScsiTm->Reserved2[ii] = 0; 15921da177e4SLinus Torvalds 15931da177e4SLinus Torvalds pScsiTm->TaskMsgContext = ctx2abort; 15941da177e4SLinus Torvalds 15951ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) " 15961ba9ab2eSKashyap, Desai "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort, 15971ba9ab2eSKashyap, Desai type, timeout)); 15981da177e4SLinus Torvalds 15996757d6b4SPrakash, Sathya DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); 16001da177e4SLinus Torvalds 16011ba9ab2eSKashyap, Desai INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) 16021ba9ab2eSKashyap, Desai time_count = jiffies; 1603e80b002bSEric Moore if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && 1604e80b002bSEric Moore (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) 1605e80b002bSEric Moore mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); 16067a195f46SPrakash, Sathya else { 1607e80b002bSEric Moore retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, 16087a195f46SPrakash, Sathya sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); 16097a195f46SPrakash, Sathya if (retval) { 16101ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 16111ba9ab2eSKashyap, Desai "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n", 16121ba9ab2eSKashyap, Desai ioc->name, mf, retval)); 1613e80b002bSEric Moore mpt_free_msg_frame(ioc, mf); 16141ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 16151ba9ab2eSKashyap, Desai goto out; 16161da177e4SLinus Torvalds } 16171ba9ab2eSKashyap, Desai } 16181ba9ab2eSKashyap, Desai 16191ba9ab2eSKashyap, Desai timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, 16201ba9ab2eSKashyap, Desai timeout*HZ); 16211ba9ab2eSKashyap, Desai if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 16221ba9ab2eSKashyap, Desai retval = FAILED; 16231ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_ERR_FMT 16241ba9ab2eSKashyap, Desai "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf)); 16251ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 16261ba9ab2eSKashyap, Desai if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) 16271ba9ab2eSKashyap, Desai goto out; 16281ba9ab2eSKashyap, Desai issue_hard_reset = 1; 16291ba9ab2eSKashyap, Desai goto out; 16301ba9ab2eSKashyap, Desai } 16311ba9ab2eSKashyap, Desai 16321ba9ab2eSKashyap, Desai retval = mptscsih_taskmgmt_reply(ioc, type, 16331ba9ab2eSKashyap, Desai (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply); 16341ba9ab2eSKashyap, Desai 16351ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 16361ba9ab2eSKashyap, Desai "TaskMgmt completed (%d seconds)\n", 16371ba9ab2eSKashyap, Desai ioc->name, jiffies_to_msecs(jiffies - time_count)/1000)); 16381ba9ab2eSKashyap, Desai 16391ba9ab2eSKashyap, Desai out: 16401ba9ab2eSKashyap, Desai 16411ba9ab2eSKashyap, Desai CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) 16421ba9ab2eSKashyap, Desai if (issue_hard_reset) { 164397009a29SKei Tokunaga printk(MYIOC_s_WARN_FMT 164497009a29SKei Tokunaga "Issuing Reset from %s!! doorbell=0x%08x\n", 164597009a29SKei Tokunaga ioc->name, __func__, mpt_GetIocState(ioc, 0)); 164698cbe371Skashyap.desai@lsi.com retval = (ioc->bus_type == SAS) ? 164798cbe371Skashyap.desai@lsi.com mpt_HardResetHandler(ioc, CAN_SLEEP) : 164898cbe371Skashyap.desai@lsi.com mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); 16491ba9ab2eSKashyap, Desai mpt_free_msg_frame(ioc, mf); 16501ba9ab2eSKashyap, Desai } 16511ba9ab2eSKashyap, Desai 16521ba9ab2eSKashyap, Desai retval = (retval == 0) ? 0 : FAILED; 16531ba9ab2eSKashyap, Desai mutex_unlock(&ioc->taskmgmt_cmds.mutex); 16541ba9ab2eSKashyap, Desai return retval; 16551ba9ab2eSKashyap, Desai } 16561ba9ab2eSKashyap, Desai EXPORT_SYMBOL(mptscsih_IssueTaskMgmt); 16571da177e4SLinus Torvalds 1658d66c7a0fSChristoph Hellwig static int 1659d66c7a0fSChristoph Hellwig mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) 1660d66c7a0fSChristoph Hellwig { 1661d66c7a0fSChristoph Hellwig switch (ioc->bus_type) { 1662d66c7a0fSChristoph Hellwig case FC: 1663d66c7a0fSChristoph Hellwig return 40; 1664d66c7a0fSChristoph Hellwig case SAS: 166569b2e9b4SKashyap, Desai return 30; 1666d66c7a0fSChristoph Hellwig case SPI: 1667d66c7a0fSChristoph Hellwig default: 166822ab019bSBernd Schubert return 10; 1669d66c7a0fSChristoph Hellwig } 1670d66c7a0fSChristoph Hellwig } 1671d66c7a0fSChristoph Hellwig 16721da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 16731da177e4SLinus Torvalds /** 16741da177e4SLinus Torvalds * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant 16751da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted 16761da177e4SLinus Torvalds * 16771da177e4SLinus Torvalds * (linux scsi_host_template.eh_abort_handler routine) 16781da177e4SLinus Torvalds * 16791da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1680cd2c6191SEric Moore **/ 16810d0c7974SMoore, Eric Dean int 16821da177e4SLinus Torvalds mptscsih_abort(struct scsi_cmnd * SCpnt) 16831da177e4SLinus Torvalds { 16841da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 16851da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 16861da177e4SLinus Torvalds u32 ctx2abort; 16871da177e4SLinus Torvalds int scpnt_idx; 1688466544d8SMoore, Eric Dean int retval; 1689958d4a32SEric Moore VirtDevice *vdevice; 1690958d4a32SEric Moore MPT_ADAPTER *ioc; 16911da177e4SLinus Torvalds 16921da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 16931da177e4SLinus Torvalds */ 1694e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL) { 16951da177e4SLinus Torvalds SCpnt->result = DID_RESET << 16; 16961da177e4SLinus Torvalds SCpnt->scsi_done(SCpnt); 169729dd3609SEric Moore printk(KERN_ERR MYNAM ": task abort: " 169829dd3609SEric Moore "can't locate host! (sc=%p)\n", SCpnt); 16991da177e4SLinus Torvalds return FAILED; 17001da177e4SLinus Torvalds } 17011da177e4SLinus Torvalds 1702958d4a32SEric Moore ioc = hd->ioc; 1703958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n", 1704958d4a32SEric Moore ioc->name, SCpnt); 1705958d4a32SEric Moore scsi_print_command(SCpnt); 1706958d4a32SEric Moore 1707958d4a32SEric Moore vdevice = SCpnt->device->hostdata; 1708958d4a32SEric Moore if (!vdevice || !vdevice->vtarget) { 170929dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 171029dd3609SEric Moore "task abort: device has been deleted (sc=%p)\n", 171129dd3609SEric Moore ioc->name, SCpnt)); 1712958d4a32SEric Moore SCpnt->result = DID_NO_CONNECT << 16; 1713958d4a32SEric Moore SCpnt->scsi_done(SCpnt); 171469b2e9b4SKashyap, Desai retval = SUCCESS; 1715958d4a32SEric Moore goto out; 1716958d4a32SEric Moore } 1717958d4a32SEric Moore 1718cc78d30aSEric Moore /* Task aborts are not supported for hidden raid components. 1719cc78d30aSEric Moore */ 1720cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 172129dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 172229dd3609SEric Moore "task abort: hidden raid component (sc=%p)\n", 172329dd3609SEric Moore ioc->name, SCpnt)); 1724cc78d30aSEric Moore SCpnt->result = DID_RESET << 16; 1725cc78d30aSEric Moore retval = FAILED; 1726cc78d30aSEric Moore goto out; 1727cc78d30aSEric Moore } 1728cc78d30aSEric Moore 172969b2e9b4SKashyap, Desai /* Task aborts are not supported for volumes. 173069b2e9b4SKashyap, Desai */ 173169b2e9b4SKashyap, Desai if (vdevice->vtarget->raidVolume) { 173269b2e9b4SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 173369b2e9b4SKashyap, Desai "task abort: raid volume (sc=%p)\n", 173469b2e9b4SKashyap, Desai ioc->name, SCpnt)); 173569b2e9b4SKashyap, Desai SCpnt->result = DID_RESET << 16; 173669b2e9b4SKashyap, Desai retval = FAILED; 173769b2e9b4SKashyap, Desai goto out; 173869b2e9b4SKashyap, Desai } 173969b2e9b4SKashyap, Desai 17401da177e4SLinus Torvalds /* Find this command 17411da177e4SLinus Torvalds */ 1742e8206381SEric Moore if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { 17431da177e4SLinus Torvalds /* Cmd not found in ScsiLookup. 17441da177e4SLinus Torvalds * Do OS callback. 17451da177e4SLinus Torvalds */ 17461da177e4SLinus Torvalds SCpnt->result = DID_RESET << 16; 174729dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " 1748958d4a32SEric Moore "Command not in the active list! (sc=%p)\n", ioc->name, 1749958d4a32SEric Moore SCpnt)); 17509858ae38SKashyap, Desai retval = SUCCESS; 1751958d4a32SEric Moore goto out; 17521da177e4SLinus Torvalds } 17531da177e4SLinus Torvalds 17542f187862SKashyap, Desai if (ioc->timeouts < -1) 17552f187862SKashyap, Desai ioc->timeouts++; 175665207fedSMoore, Eric 17572f4c782cSKashyap, Desai if (mpt_fwfault_debug) 17582f4c782cSKashyap, Desai mpt_halt_firmware(ioc); 17592f4c782cSKashyap, Desai 17601da177e4SLinus Torvalds /* Most important! Set TaskMsgContext to SCpnt's MsgContext! 17611da177e4SLinus Torvalds * (the IO to be ABORT'd) 17621da177e4SLinus Torvalds * 17631da177e4SLinus Torvalds * NOTE: Since we do not byteswap MsgContext, we do not 17641da177e4SLinus Torvalds * swap it here either. It is an opaque cookie to 17651da177e4SLinus Torvalds * the controller, so it does not matter. -DaveM 17661da177e4SLinus Torvalds */ 1767e80b002bSEric Moore mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx); 17681da177e4SLinus Torvalds ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; 17691ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 17701ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 17711ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 17721ba9ab2eSKashyap, Desai vdevice->vtarget->id, vdevice->lun, 1773958d4a32SEric Moore ctx2abort, mptscsih_get_tm_timeout(ioc)); 17741da177e4SLinus Torvalds 1775aeaeb5ceSChristoph Hellwig if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx) { 17762f187862SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 17772f187862SKashyap, Desai "task abort: command still in active list! (sc=%p)\n", 17782f187862SKashyap, Desai ioc->name, SCpnt)); 17793dc0b03fSEric Moore retval = FAILED; 17802f187862SKashyap, Desai } else { 17812f187862SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 17822f187862SKashyap, Desai "task abort: command cleared from active list! (sc=%p)\n", 17832f187862SKashyap, Desai ioc->name, SCpnt)); 17842f187862SKashyap, Desai retval = SUCCESS; 17852f187862SKashyap, Desai } 17863dc0b03fSEric Moore 1787958d4a32SEric Moore out: 1788aeaeb5ceSChristoph Hellwig printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p)\n", 1789bcfe42e9SKashyap, Desai ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval, 1790aeaeb5ceSChristoph Hellwig SCpnt); 17911da177e4SLinus Torvalds 17922f187862SKashyap, Desai return retval; 17931da177e4SLinus Torvalds } 17941da177e4SLinus Torvalds 17951da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 17961da177e4SLinus Torvalds /** 17971da177e4SLinus Torvalds * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant 17981da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 17991da177e4SLinus Torvalds * 18001da177e4SLinus Torvalds * (linux scsi_host_template.eh_dev_reset_handler routine) 18011da177e4SLinus Torvalds * 18021da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1803cd2c6191SEric Moore **/ 18040d0c7974SMoore, Eric Dean int 18051da177e4SLinus Torvalds mptscsih_dev_reset(struct scsi_cmnd * SCpnt) 18061da177e4SLinus Torvalds { 18071da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1808466544d8SMoore, Eric Dean int retval; 1809958d4a32SEric Moore VirtDevice *vdevice; 1810958d4a32SEric Moore MPT_ADAPTER *ioc; 18111da177e4SLinus Torvalds 18121da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 18131da177e4SLinus Torvalds */ 1814e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 181529dd3609SEric Moore printk(KERN_ERR MYNAM ": target reset: " 181629dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 18171da177e4SLinus Torvalds return FAILED; 18181da177e4SLinus Torvalds } 18191da177e4SLinus Torvalds 1820958d4a32SEric Moore ioc = hd->ioc; 1821958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n", 1822958d4a32SEric Moore ioc->name, SCpnt); 1823466544d8SMoore, Eric Dean scsi_print_command(SCpnt); 18241da177e4SLinus Torvalds 1825958d4a32SEric Moore vdevice = SCpnt->device->hostdata; 1826958d4a32SEric Moore if (!vdevice || !vdevice->vtarget) { 1827bcfe42e9SKashyap, Desai retval = 0; 1828958d4a32SEric Moore goto out; 1829958d4a32SEric Moore } 1830958d4a32SEric Moore 1831cc78d30aSEric Moore /* Target reset to hidden raid component is not supported 1832cc78d30aSEric Moore */ 1833cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 1834cc78d30aSEric Moore retval = FAILED; 1835cc78d30aSEric Moore goto out; 1836cc78d30aSEric Moore } 1837cc78d30aSEric Moore 18381ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 18391ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 18401ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 18411ba9ab2eSKashyap, Desai vdevice->vtarget->id, 0, 0, 1842958d4a32SEric Moore mptscsih_get_tm_timeout(ioc)); 1843958d4a32SEric Moore 1844958d4a32SEric Moore out: 1845958d4a32SEric Moore printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", 1846958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1847466544d8SMoore, Eric Dean 1848466544d8SMoore, Eric Dean if (retval == 0) 1849466544d8SMoore, Eric Dean return SUCCESS; 1850cd2c6191SEric Moore else 1851466544d8SMoore, Eric Dean return FAILED; 18521da177e4SLinus Torvalds } 18531da177e4SLinus Torvalds 1854cd2c6191SEric Moore 18551da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 18561da177e4SLinus Torvalds /** 18571da177e4SLinus Torvalds * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant 18581da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 18591da177e4SLinus Torvalds * 18601da177e4SLinus Torvalds * (linux scsi_host_template.eh_bus_reset_handler routine) 18611da177e4SLinus Torvalds * 18621da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1863cd2c6191SEric Moore **/ 18640d0c7974SMoore, Eric Dean int 18651da177e4SLinus Torvalds mptscsih_bus_reset(struct scsi_cmnd * SCpnt) 18661da177e4SLinus Torvalds { 18671da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1868466544d8SMoore, Eric Dean int retval; 1869a69de507SEric Moore VirtDevice *vdevice; 1870958d4a32SEric Moore MPT_ADAPTER *ioc; 18711da177e4SLinus Torvalds 18721da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 18731da177e4SLinus Torvalds */ 1874e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 187529dd3609SEric Moore printk(KERN_ERR MYNAM ": bus reset: " 187629dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 18771da177e4SLinus Torvalds return FAILED; 18781da177e4SLinus Torvalds } 18791da177e4SLinus Torvalds 1880958d4a32SEric Moore ioc = hd->ioc; 1881958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n", 1882958d4a32SEric Moore ioc->name, SCpnt); 1883466544d8SMoore, Eric Dean scsi_print_command(SCpnt); 18841da177e4SLinus Torvalds 18852f187862SKashyap, Desai if (ioc->timeouts < -1) 18862f187862SKashyap, Desai ioc->timeouts++; 18871da177e4SLinus Torvalds 1888a69de507SEric Moore vdevice = SCpnt->device->hostdata; 18892f187862SKashyap, Desai if (!vdevice || !vdevice->vtarget) 18902f187862SKashyap, Desai return SUCCESS; 18911ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 18921ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, 18931ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 0, 0, 0, 18941ba9ab2eSKashyap, Desai mptscsih_get_tm_timeout(ioc)); 18951da177e4SLinus Torvalds 1896958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", 1897958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1898466544d8SMoore, Eric Dean 1899466544d8SMoore, Eric Dean if (retval == 0) 1900466544d8SMoore, Eric Dean return SUCCESS; 1901cd2c6191SEric Moore else 1902466544d8SMoore, Eric Dean return FAILED; 19031da177e4SLinus Torvalds } 19041da177e4SLinus Torvalds 19051da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 19061da177e4SLinus Torvalds /** 1907d9489fb6SRandy Dunlap * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant) 19081da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 19091da177e4SLinus Torvalds * 19101da177e4SLinus Torvalds * (linux scsi_host_template.eh_host_reset_handler routine) 19111da177e4SLinus Torvalds * 19121da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 19131da177e4SLinus Torvalds */ 19140d0c7974SMoore, Eric Dean int 19151da177e4SLinus Torvalds mptscsih_host_reset(struct scsi_cmnd *SCpnt) 19161da177e4SLinus Torvalds { 19171da177e4SLinus Torvalds MPT_SCSI_HOST * hd; 19182f187862SKashyap, Desai int status = SUCCESS; 1919958d4a32SEric Moore MPT_ADAPTER *ioc; 19202f187862SKashyap, Desai int retval; 19211da177e4SLinus Torvalds 19221da177e4SLinus Torvalds /* If we can't locate the host to reset, then we failed. */ 1923e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 192429dd3609SEric Moore printk(KERN_ERR MYNAM ": host reset: " 192529dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 19261da177e4SLinus Torvalds return FAILED; 19271da177e4SLinus Torvalds } 19281da177e4SLinus Torvalds 1929a6da74cbSJames Bottomley /* make sure we have no outstanding commands at this stage */ 1930a6da74cbSJames Bottomley mptscsih_flush_running_cmds(hd); 1931a6da74cbSJames Bottomley 1932958d4a32SEric Moore ioc = hd->ioc; 1933958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n", 1934958d4a32SEric Moore ioc->name, SCpnt); 19351da177e4SLinus Torvalds 19361da177e4SLinus Torvalds /* If our attempts to reset the host failed, then return a failed 19371da177e4SLinus Torvalds * status. The host will be taken off line by the SCSI mid-layer. 19381da177e4SLinus Torvalds */ 1939d0f698c4SKashyap, Desai retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); 19402f187862SKashyap, Desai if (retval < 0) 19412f187862SKashyap, Desai status = FAILED; 19422f187862SKashyap, Desai else 19432f187862SKashyap, Desai status = SUCCESS; 19441da177e4SLinus Torvalds 1945958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", 1946958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 19471da177e4SLinus Torvalds 19482f187862SKashyap, Desai return status; 19491da177e4SLinus Torvalds } 19501da177e4SLinus Torvalds 19511da177e4SLinus Torvalds static int 19521ba9ab2eSKashyap, Desai mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, 19531ba9ab2eSKashyap, Desai SCSITaskMgmtReply_t *pScsiTmReply) 19541da177e4SLinus Torvalds { 19551ba9ab2eSKashyap, Desai u16 iocstatus; 19561ba9ab2eSKashyap, Desai u32 termination_count; 19571ba9ab2eSKashyap, Desai int retval; 19581da177e4SLinus Torvalds 19591ba9ab2eSKashyap, Desai if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { 19601ba9ab2eSKashyap, Desai retval = FAILED; 19611ba9ab2eSKashyap, Desai goto out; 19621da177e4SLinus Torvalds } 19631da177e4SLinus Torvalds 19641ba9ab2eSKashyap, Desai DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); 19651da177e4SLinus Torvalds 19661ba9ab2eSKashyap, Desai iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; 19671ba9ab2eSKashyap, Desai termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); 19681ba9ab2eSKashyap, Desai 19691ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 19701ba9ab2eSKashyap, Desai "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n" 19711ba9ab2eSKashyap, Desai "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n" 19721ba9ab2eSKashyap, Desai "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus, 19731ba9ab2eSKashyap, Desai pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus), 19741ba9ab2eSKashyap, Desai le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, 19751ba9ab2eSKashyap, Desai termination_count)); 19761ba9ab2eSKashyap, Desai 19771ba9ab2eSKashyap, Desai if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && 19781ba9ab2eSKashyap, Desai pScsiTmReply->ResponseCode) 19791ba9ab2eSKashyap, Desai mptscsih_taskmgmt_response_code(ioc, 19801ba9ab2eSKashyap, Desai pScsiTmReply->ResponseCode); 19811ba9ab2eSKashyap, Desai 19821ba9ab2eSKashyap, Desai if (iocstatus == MPI_IOCSTATUS_SUCCESS) { 19831ba9ab2eSKashyap, Desai retval = 0; 19841ba9ab2eSKashyap, Desai goto out; 19851da177e4SLinus Torvalds } 19861da177e4SLinus Torvalds 19871ba9ab2eSKashyap, Desai retval = FAILED; 19881ba9ab2eSKashyap, Desai if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { 19891ba9ab2eSKashyap, Desai if (termination_count == 1) 19901ba9ab2eSKashyap, Desai retval = 0; 19911ba9ab2eSKashyap, Desai goto out; 19921ba9ab2eSKashyap, Desai } 19931ba9ab2eSKashyap, Desai 19941ba9ab2eSKashyap, Desai if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || 19951ba9ab2eSKashyap, Desai iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) 19961ba9ab2eSKashyap, Desai retval = 0; 19971ba9ab2eSKashyap, Desai 19981ba9ab2eSKashyap, Desai out: 19991ba9ab2eSKashyap, Desai return retval; 20001da177e4SLinus Torvalds } 20011da177e4SLinus Torvalds 20021da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 2003e7deff33SKashyap, Desai void 20049f63bb73SMoore, Eric mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) 20059f63bb73SMoore, Eric { 20069f63bb73SMoore, Eric char *desc; 20079f63bb73SMoore, Eric 20089f63bb73SMoore, Eric switch (response_code) { 20099f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_COMPLETE: 20109f63bb73SMoore, Eric desc = "The task completed."; 20119f63bb73SMoore, Eric break; 20129f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_INVALID_FRAME: 20139f63bb73SMoore, Eric desc = "The IOC received an invalid frame status."; 20149f63bb73SMoore, Eric break; 20159f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 20169f63bb73SMoore, Eric desc = "The task type is not supported."; 20179f63bb73SMoore, Eric break; 20189f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_FAILED: 20199f63bb73SMoore, Eric desc = "The requested task failed."; 20209f63bb73SMoore, Eric break; 20219f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED: 20229f63bb73SMoore, Eric desc = "The task completed successfully."; 20239f63bb73SMoore, Eric break; 20249f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN: 20259f63bb73SMoore, Eric desc = "The LUN request is invalid."; 20269f63bb73SMoore, Eric break; 20279f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 20289f63bb73SMoore, Eric desc = "The task is in the IOC queue and has not been sent to target."; 20299f63bb73SMoore, Eric break; 20309f63bb73SMoore, Eric default: 20319f63bb73SMoore, Eric desc = "unknown"; 20329f63bb73SMoore, Eric break; 20339f63bb73SMoore, Eric } 20349f63bb73SMoore, Eric printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", 20359f63bb73SMoore, Eric ioc->name, response_code, desc); 20369f63bb73SMoore, Eric } 2037e7deff33SKashyap, Desai EXPORT_SYMBOL(mptscsih_taskmgmt_response_code); 20389f63bb73SMoore, Eric 20399f63bb73SMoore, Eric /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 20401da177e4SLinus Torvalds /** 20411da177e4SLinus Torvalds * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver 20421da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 20431da177e4SLinus Torvalds * @mf: Pointer to SCSI task mgmt request frame 20441da177e4SLinus Torvalds * @mr: Pointer to SCSI task mgmt reply frame 20451da177e4SLinus Torvalds * 20461da177e4SLinus Torvalds * This routine is called from mptbase.c::mpt_interrupt() at the completion 20471da177e4SLinus Torvalds * of any SCSI task management request. 20481da177e4SLinus Torvalds * This routine is registered with the MPT (base) driver at driver 20491da177e4SLinus Torvalds * load/init time via the mpt_register() API call. 20501da177e4SLinus Torvalds * 20511da177e4SLinus Torvalds * Returns 1 indicating alloc'd request frame ptr should be freed. 2052cd2c6191SEric Moore **/ 20530d0c7974SMoore, Eric Dean int 20541ba9ab2eSKashyap, Desai mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, 20551ba9ab2eSKashyap, Desai MPT_FRAME_HDR *mr) 20561da177e4SLinus Torvalds { 20571ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 20581ba9ab2eSKashyap, Desai "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr)); 20591da177e4SLinus Torvalds 20601ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; 20611da177e4SLinus Torvalds 20621ba9ab2eSKashyap, Desai if (!mr) 2063cd2c6191SEric Moore goto out; 2064cd2c6191SEric Moore 20651ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; 20661ba9ab2eSKashyap, Desai memcpy(ioc->taskmgmt_cmds.reply, mr, 20671ba9ab2eSKashyap, Desai min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); 2068cd2c6191SEric Moore out: 20691ba9ab2eSKashyap, Desai if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { 20701ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 20711ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; 20721ba9ab2eSKashyap, Desai complete(&ioc->taskmgmt_cmds.done); 2073b68bf096SKashyap, Desai if (ioc->bus_type == SAS) 2074b68bf096SKashyap, Desai ioc->schedule_target_reset(ioc); 20751da177e4SLinus Torvalds return 1; 20761da177e4SLinus Torvalds } 20771ba9ab2eSKashyap, Desai return 0; 20781ba9ab2eSKashyap, Desai } 20791da177e4SLinus Torvalds 20801da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 20811da177e4SLinus Torvalds /* 20821da177e4SLinus Torvalds * This is anyones guess quite frankly. 20831da177e4SLinus Torvalds */ 20840d0c7974SMoore, Eric Dean int 20851da177e4SLinus Torvalds mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, 20861da177e4SLinus Torvalds sector_t capacity, int geom[]) 20871da177e4SLinus Torvalds { 20881da177e4SLinus Torvalds int heads; 20891da177e4SLinus Torvalds int sectors; 20901da177e4SLinus Torvalds sector_t cylinders; 20911da177e4SLinus Torvalds ulong dummy; 20921da177e4SLinus Torvalds 20931da177e4SLinus Torvalds heads = 64; 20941da177e4SLinus Torvalds sectors = 32; 20951da177e4SLinus Torvalds 20961da177e4SLinus Torvalds dummy = heads * sectors; 20971da177e4SLinus Torvalds cylinders = capacity; 20981da177e4SLinus Torvalds sector_div(cylinders,dummy); 20991da177e4SLinus Torvalds 21001da177e4SLinus Torvalds /* 21011da177e4SLinus Torvalds * Handle extended translation size for logical drives 21021da177e4SLinus Torvalds * > 1Gb 21031da177e4SLinus Torvalds */ 21041da177e4SLinus Torvalds if ((ulong)capacity >= 0x200000) { 21051da177e4SLinus Torvalds heads = 255; 21061da177e4SLinus Torvalds sectors = 63; 21071da177e4SLinus Torvalds dummy = heads * sectors; 21081da177e4SLinus Torvalds cylinders = capacity; 21091da177e4SLinus Torvalds sector_div(cylinders,dummy); 21101da177e4SLinus Torvalds } 21111da177e4SLinus Torvalds 21121da177e4SLinus Torvalds /* return result */ 21131da177e4SLinus Torvalds geom[0] = heads; 21141da177e4SLinus Torvalds geom[1] = sectors; 21151da177e4SLinus Torvalds geom[2] = cylinders; 21161da177e4SLinus Torvalds 21171da177e4SLinus Torvalds return 0; 21181da177e4SLinus Torvalds } 21191da177e4SLinus Torvalds 2120f44e5461SMoore, Eric /* Search IOC page 3 to determine if this is hidden physical disk 2121f44e5461SMoore, Eric * 2122f44e5461SMoore, Eric */ 2123f44e5461SMoore, Eric int 2124793955f5SEric Moore mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) 2125f44e5461SMoore, Eric { 2126b506ade9SEric Moore struct inactive_raid_component_info *component_info; 2127a7938b0bSKashyap, Desai int i, j; 2128a7938b0bSKashyap, Desai RaidPhysDiskPage1_t *phys_disk; 2129793955f5SEric Moore int rc = 0; 2130a7938b0bSKashyap, Desai int num_paths; 2131f44e5461SMoore, Eric 2132793955f5SEric Moore if (!ioc->raid_data.pIocPg3) 2133793955f5SEric Moore goto out; 2134f44e5461SMoore, Eric for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2135793955f5SEric Moore if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && 2136793955f5SEric Moore (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { 2137793955f5SEric Moore rc = 1; 2138793955f5SEric Moore goto out; 2139f44e5461SMoore, Eric } 2140793955f5SEric Moore } 2141793955f5SEric Moore 2142a7938b0bSKashyap, Desai if (ioc->bus_type != SAS) 2143a7938b0bSKashyap, Desai goto out; 2144a7938b0bSKashyap, Desai 2145a7938b0bSKashyap, Desai /* 2146a7938b0bSKashyap, Desai * Check if dual path 2147a7938b0bSKashyap, Desai */ 2148a7938b0bSKashyap, Desai for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2149a7938b0bSKashyap, Desai num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2150a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2151a7938b0bSKashyap, Desai if (num_paths < 2) 2152a7938b0bSKashyap, Desai continue; 2153a7938b0bSKashyap, Desai phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2154a7938b0bSKashyap, Desai (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2155a7938b0bSKashyap, Desai if (!phys_disk) 2156a7938b0bSKashyap, Desai continue; 2157a7938b0bSKashyap, Desai if ((mpt_raid_phys_disk_pg1(ioc, 2158a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2159a7938b0bSKashyap, Desai phys_disk))) { 2160a7938b0bSKashyap, Desai kfree(phys_disk); 2161a7938b0bSKashyap, Desai continue; 2162a7938b0bSKashyap, Desai } 2163a7938b0bSKashyap, Desai for (j = 0; j < num_paths; j++) { 2164a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2165a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2166a7938b0bSKashyap, Desai continue; 2167a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2168a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2169a7938b0bSKashyap, Desai continue; 2170a7938b0bSKashyap, Desai if ((id == phys_disk->Path[j].PhysDiskID) && 2171a7938b0bSKashyap, Desai (channel == phys_disk->Path[j].PhysDiskBus)) { 2172a7938b0bSKashyap, Desai rc = 1; 2173a7938b0bSKashyap, Desai kfree(phys_disk); 2174a7938b0bSKashyap, Desai goto out; 2175a7938b0bSKashyap, Desai } 2176a7938b0bSKashyap, Desai } 2177a7938b0bSKashyap, Desai kfree(phys_disk); 2178a7938b0bSKashyap, Desai } 2179a7938b0bSKashyap, Desai 2180a7938b0bSKashyap, Desai 2181b506ade9SEric Moore /* 2182b506ade9SEric Moore * Check inactive list for matching phys disks 2183b506ade9SEric Moore */ 2184b506ade9SEric Moore if (list_empty(&ioc->raid_data.inactive_list)) 2185b506ade9SEric Moore goto out; 2186b506ade9SEric Moore 2187ed5f606fSMatthias Kaehlcke mutex_lock(&ioc->raid_data.inactive_list_mutex); 2188b506ade9SEric Moore list_for_each_entry(component_info, &ioc->raid_data.inactive_list, 2189b506ade9SEric Moore list) { 2190b506ade9SEric Moore if ((component_info->d.PhysDiskID == id) && 2191b506ade9SEric Moore (component_info->d.PhysDiskBus == channel)) 2192b506ade9SEric Moore rc = 1; 2193b506ade9SEric Moore } 2194ed5f606fSMatthias Kaehlcke mutex_unlock(&ioc->raid_data.inactive_list_mutex); 2195b506ade9SEric Moore 2196793955f5SEric Moore out: 2197793955f5SEric Moore return rc; 2198f44e5461SMoore, Eric } 2199f44e5461SMoore, Eric EXPORT_SYMBOL(mptscsih_is_phys_disk); 2200f44e5461SMoore, Eric 2201793955f5SEric Moore u8 2202793955f5SEric Moore mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 2203c92f222eSJames Bottomley { 2204b506ade9SEric Moore struct inactive_raid_component_info *component_info; 2205a7938b0bSKashyap, Desai int i, j; 2206a7938b0bSKashyap, Desai RaidPhysDiskPage1_t *phys_disk; 2207793955f5SEric Moore int rc = -ENXIO; 2208a7938b0bSKashyap, Desai int num_paths; 2209c92f222eSJames Bottomley 2210793955f5SEric Moore if (!ioc->raid_data.pIocPg3) 2211793955f5SEric Moore goto out; 2212793955f5SEric Moore for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2213793955f5SEric Moore if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && 2214793955f5SEric Moore (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { 2215793955f5SEric Moore rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; 2216793955f5SEric Moore goto out; 2217793955f5SEric Moore } 2218c92f222eSJames Bottomley } 2219c92f222eSJames Bottomley 2220a7938b0bSKashyap, Desai if (ioc->bus_type != SAS) 2221a7938b0bSKashyap, Desai goto out; 2222a7938b0bSKashyap, Desai 2223a7938b0bSKashyap, Desai /* 2224a7938b0bSKashyap, Desai * Check if dual path 2225a7938b0bSKashyap, Desai */ 2226a7938b0bSKashyap, Desai for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2227a7938b0bSKashyap, Desai num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2228a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2229a7938b0bSKashyap, Desai if (num_paths < 2) 2230a7938b0bSKashyap, Desai continue; 2231a7938b0bSKashyap, Desai phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2232a7938b0bSKashyap, Desai (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2233a7938b0bSKashyap, Desai if (!phys_disk) 2234a7938b0bSKashyap, Desai continue; 2235a7938b0bSKashyap, Desai if ((mpt_raid_phys_disk_pg1(ioc, 2236a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2237a7938b0bSKashyap, Desai phys_disk))) { 2238a7938b0bSKashyap, Desai kfree(phys_disk); 2239a7938b0bSKashyap, Desai continue; 2240a7938b0bSKashyap, Desai } 2241a7938b0bSKashyap, Desai for (j = 0; j < num_paths; j++) { 2242a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2243a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2244a7938b0bSKashyap, Desai continue; 2245a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2246a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2247a7938b0bSKashyap, Desai continue; 2248a7938b0bSKashyap, Desai if ((id == phys_disk->Path[j].PhysDiskID) && 2249a7938b0bSKashyap, Desai (channel == phys_disk->Path[j].PhysDiskBus)) { 2250a7938b0bSKashyap, Desai rc = phys_disk->PhysDiskNum; 2251a7938b0bSKashyap, Desai kfree(phys_disk); 2252a7938b0bSKashyap, Desai goto out; 2253a7938b0bSKashyap, Desai } 2254a7938b0bSKashyap, Desai } 2255a7938b0bSKashyap, Desai kfree(phys_disk); 2256a7938b0bSKashyap, Desai } 2257a7938b0bSKashyap, Desai 2258b506ade9SEric Moore /* 2259b506ade9SEric Moore * Check inactive list for matching phys disks 2260b506ade9SEric Moore */ 2261b506ade9SEric Moore if (list_empty(&ioc->raid_data.inactive_list)) 2262b506ade9SEric Moore goto out; 2263b506ade9SEric Moore 2264ed5f606fSMatthias Kaehlcke mutex_lock(&ioc->raid_data.inactive_list_mutex); 2265b506ade9SEric Moore list_for_each_entry(component_info, &ioc->raid_data.inactive_list, 2266b506ade9SEric Moore list) { 2267b506ade9SEric Moore if ((component_info->d.PhysDiskID == id) && 2268b506ade9SEric Moore (component_info->d.PhysDiskBus == channel)) 2269b506ade9SEric Moore rc = component_info->d.PhysDiskNum; 2270b506ade9SEric Moore } 2271ed5f606fSMatthias Kaehlcke mutex_unlock(&ioc->raid_data.inactive_list_mutex); 2272b506ade9SEric Moore 2273793955f5SEric Moore out: 2274793955f5SEric Moore return rc; 2275c92f222eSJames Bottomley } 2276c92f222eSJames Bottomley EXPORT_SYMBOL(mptscsih_raid_id_to_num); 2277c92f222eSJames Bottomley 2278c7c82987SMoore, Eric Dean /* 2279c7c82987SMoore, Eric Dean * OS entry point to allow for host driver to free allocated memory 2280c7c82987SMoore, Eric Dean * Called if no device present or device being unloaded 2281c7c82987SMoore, Eric Dean */ 2282c7c82987SMoore, Eric Dean void 2283c7c82987SMoore, Eric Dean mptscsih_slave_destroy(struct scsi_device *sdev) 2284c7c82987SMoore, Eric Dean { 2285c7c82987SMoore, Eric Dean struct Scsi_Host *host = sdev->host; 2286e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 2287c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2288c7c82987SMoore, Eric Dean VirtDevice *vdevice; 2289c7c82987SMoore, Eric Dean struct scsi_target *starget; 22901da177e4SLinus Torvalds 2291c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2292c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 2293c7c82987SMoore, Eric Dean vdevice = sdev->hostdata; 229408f5c5c2SKashyap, Desai if (!vdevice) 229508f5c5c2SKashyap, Desai return; 22961da177e4SLinus Torvalds 2297c7c82987SMoore, Eric Dean mptscsih_search_running_cmds(hd, vdevice); 2298c7c82987SMoore, Eric Dean vtarget->num_luns--; 2299c7c82987SMoore, Eric Dean mptscsih_synchronize_cache(hd, vdevice); 2300c7c82987SMoore, Eric Dean kfree(vdevice); 2301c7c82987SMoore, Eric Dean sdev->hostdata = NULL; 23021da177e4SLinus Torvalds } 23031da177e4SLinus Torvalds 23046e3815baSMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 23056e3815baSMoore, Eric Dean /* 23066e3815baSMoore, Eric Dean * mptscsih_change_queue_depth - This function will set a devices queue depth 23076e3815baSMoore, Eric Dean * @sdev: per scsi_device pointer 23086e3815baSMoore, Eric Dean * @qdepth: requested queue depth 23096e3815baSMoore, Eric Dean * 23106e3815baSMoore, Eric Dean * Adding support for new 'change_queue_depth' api. 23116e3815baSMoore, Eric Dean */ 23126e3815baSMoore, Eric Dean int 2313db5ed4dfSChristoph Hellwig mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) 23141da177e4SLinus Torvalds { 2315e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(sdev->host); 2316c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2317c7c82987SMoore, Eric Dean struct scsi_target *starget; 23181da177e4SLinus Torvalds int max_depth; 2319e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 23201da177e4SLinus Torvalds 2321c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2322c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 23236e3815baSMoore, Eric Dean 2324e80b002bSEric Moore if (ioc->bus_type == SPI) { 2325c7c82987SMoore, Eric Dean if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) 23261da177e4SLinus Torvalds max_depth = 1; 2327c92f222eSJames Bottomley else if (sdev->type == TYPE_DISK && 2328c92f222eSJames Bottomley vtarget->minSyncFactor <= MPT_ULTRA160) 23291da177e4SLinus Torvalds max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; 23301da177e4SLinus Torvalds else 23311da177e4SLinus Torvalds max_depth = MPT_SCSI_CMD_PER_DEV_LOW; 23321da177e4SLinus Torvalds } else 233379a3ec1aSKashyap, Desai max_depth = ioc->sh->can_queue; 233479a3ec1aSKashyap, Desai 233579a3ec1aSKashyap, Desai if (!sdev->tagged_supported) 233679a3ec1aSKashyap, Desai max_depth = 1; 23371da177e4SLinus Torvalds 23381da177e4SLinus Torvalds if (qdepth > max_depth) 23391da177e4SLinus Torvalds qdepth = max_depth; 23401da177e4SLinus Torvalds 2341db5ed4dfSChristoph Hellwig return scsi_change_queue_depth(sdev, qdepth); 23421da177e4SLinus Torvalds } 23431da177e4SLinus Torvalds 23441da177e4SLinus Torvalds /* 23451da177e4SLinus Torvalds * OS entry point to adjust the queue_depths on a per-device basis. 23461da177e4SLinus Torvalds * Called once per device the bus scan. Use it to force the queue_depth 23471da177e4SLinus Torvalds * member to 1 if a device does not support Q tags. 23481da177e4SLinus Torvalds * Return non-zero if fails. 23491da177e4SLinus Torvalds */ 23500d0c7974SMoore, Eric Dean int 2351c7c82987SMoore, Eric Dean mptscsih_slave_configure(struct scsi_device *sdev) 23521da177e4SLinus Torvalds { 2353c7c82987SMoore, Eric Dean struct Scsi_Host *sh = sdev->host; 2354c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2355c7c82987SMoore, Eric Dean VirtDevice *vdevice; 2356c7c82987SMoore, Eric Dean struct scsi_target *starget; 2357e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(sh); 2358e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 23591da177e4SLinus Torvalds 2360c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2361c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 2362c7c82987SMoore, Eric Dean vdevice = sdev->hostdata; 23631da177e4SLinus Torvalds 2364e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23659cb78c16SHannes Reinecke "device @ %p, channel=%d, id=%d, lun=%llu\n", 2366e80b002bSEric Moore ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); 2367e80b002bSEric Moore if (ioc->bus_type == SPI) 2368e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23691da177e4SLinus Torvalds "sdtr %d wdtr %d ppr %d inq length=%d\n", 2370e80b002bSEric Moore ioc->name, sdev->sdtr, sdev->wdtr, 2371c7c82987SMoore, Eric Dean sdev->ppr, sdev->inquiry_len)); 23721da177e4SLinus Torvalds 2373c7c82987SMoore, Eric Dean vdevice->configured_lun = 1; 23741da177e4SLinus Torvalds 2375e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23761da177e4SLinus Torvalds "Queue depth=%d, tflags=%x\n", 2377e80b002bSEric Moore ioc->name, sdev->queue_depth, vtarget->tflags)); 23781da177e4SLinus Torvalds 2379e80b002bSEric Moore if (ioc->bus_type == SPI) 2380e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23811da177e4SLinus Torvalds "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", 2382e80b002bSEric Moore ioc->name, vtarget->negoFlags, vtarget->maxOffset, 2383c7c82987SMoore, Eric Dean vtarget->minSyncFactor)); 23841da177e4SLinus Torvalds 2385db5ed4dfSChristoph Hellwig mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); 2386e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2387609aa22fSChristoph Hellwig "tagged %d, simple %d\n", 2388609aa22fSChristoph Hellwig ioc->name,sdev->tagged_supported, sdev->simple_tags)); 23891da177e4SLinus Torvalds 23902a1b7e57SRyan Kuester blk_queue_dma_alignment (sdev->request_queue, 512 - 1); 23912a1b7e57SRyan Kuester 23921da177e4SLinus Torvalds return 0; 23931da177e4SLinus Torvalds } 23941da177e4SLinus Torvalds 23951da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 23961da177e4SLinus Torvalds /* 23971da177e4SLinus Torvalds * Private routines... 23981da177e4SLinus Torvalds */ 23991da177e4SLinus Torvalds 24001da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 24011da177e4SLinus Torvalds /* Utility function to copy sense data from the scsi_cmnd buffer 24021da177e4SLinus Torvalds * to the FC and SCSI target structures. 24031da177e4SLinus Torvalds * 24041da177e4SLinus Torvalds */ 24051da177e4SLinus Torvalds static void 24060d0c7974SMoore, Eric Dean mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) 24071da177e4SLinus Torvalds { 2408a69de507SEric Moore VirtDevice *vdevice; 24091da177e4SLinus Torvalds SCSIIORequest_t *pReq; 24101da177e4SLinus Torvalds u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); 2411e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 24121da177e4SLinus Torvalds 24131da177e4SLinus Torvalds /* Get target structure 24141da177e4SLinus Torvalds */ 24151da177e4SLinus Torvalds pReq = (SCSIIORequest_t *) mf; 2416a69de507SEric Moore vdevice = sc->device->hostdata; 24171da177e4SLinus Torvalds 24181da177e4SLinus Torvalds if (sense_count) { 24191da177e4SLinus Torvalds u8 *sense_data; 24201da177e4SLinus Torvalds int req_index; 24211da177e4SLinus Torvalds 24221da177e4SLinus Torvalds /* Copy the sense received into the scsi command block. */ 24231da177e4SLinus Torvalds req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 2424e80b002bSEric Moore sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); 24251da177e4SLinus Torvalds memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc)); 24261da177e4SLinus Torvalds 24271da177e4SLinus Torvalds /* Log SMART data (asc = 0x5D, non-IM case only) if required. 24281da177e4SLinus Torvalds */ 2429e80b002bSEric Moore if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { 2430a69de507SEric Moore if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) { 24311da177e4SLinus Torvalds int idx; 24321da177e4SLinus Torvalds 24335b5ef4f6SMoore, Eric idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; 24341da177e4SLinus Torvalds ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; 24351da177e4SLinus Torvalds ioc->events[idx].eventContext = ioc->eventContext; 24361da177e4SLinus Torvalds 24373d9780b9SDave Jones ioc->events[idx].data[0] = (pReq->LUN[1] << 24) | 24383d9780b9SDave Jones (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) | 24393d9780b9SDave Jones (sc->device->channel << 8) | sc->device->id; 24401da177e4SLinus Torvalds 24413d9780b9SDave Jones ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12]; 24421da177e4SLinus Torvalds 24431da177e4SLinus Torvalds ioc->eventContext++; 2444e80b002bSEric Moore if (ioc->pcidev->vendor == 2445786899b0SEric Moore PCI_VENDOR_ID_IBM) { 2446e80b002bSEric Moore mptscsih_issue_sep_command(ioc, 2447a69de507SEric Moore vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); 2448a69de507SEric Moore vdevice->vtarget->tflags |= 2449786899b0SEric Moore MPT_TARGET_FLAGS_LED_ON; 2450786899b0SEric Moore } 24511da177e4SLinus Torvalds } 24521da177e4SLinus Torvalds } 24531da177e4SLinus Torvalds } else { 2454e80b002bSEric Moore dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", 2455e80b002bSEric Moore ioc->name)); 24561da177e4SLinus Torvalds } 24571da177e4SLinus Torvalds } 24581da177e4SLinus Torvalds 2459db7051b2SKashyap, Desai /** 2460db7051b2SKashyap, Desai * mptscsih_get_scsi_lookup - retrieves scmd entry 2461db7051b2SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 2462db7051b2SKashyap, Desai * @i: index into the array 2463db7051b2SKashyap, Desai * 2464db7051b2SKashyap, Desai * Returns the scsi_cmd pointer 2465db7051b2SKashyap, Desai */ 2466db7051b2SKashyap, Desai struct scsi_cmnd * 2467db7051b2SKashyap, Desai mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) 2468db7051b2SKashyap, Desai { 2469db7051b2SKashyap, Desai unsigned long flags; 2470db7051b2SKashyap, Desai struct scsi_cmnd *scmd; 2471db7051b2SKashyap, Desai 2472db7051b2SKashyap, Desai spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2473db7051b2SKashyap, Desai scmd = ioc->ScsiLookup[i]; 2474db7051b2SKashyap, Desai spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2475db7051b2SKashyap, Desai 2476db7051b2SKashyap, Desai return scmd; 2477db7051b2SKashyap, Desai } 2478db7051b2SKashyap, Desai EXPORT_SYMBOL(mptscsih_get_scsi_lookup); 2479e8206381SEric Moore 2480e8206381SEric Moore /** 2481fc847ab4SJames Bottomley * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list 24822f187862SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 24832f187862SKashyap, Desai * @i: index into the array 24842f187862SKashyap, Desai * 24857105a387SRandy Dunlap * Returns the scsi_cmd pointer 24862f187862SKashyap, Desai * 2487e8206381SEric Moore **/ 2488e8206381SEric Moore static struct scsi_cmnd * 2489e8206381SEric Moore mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) 2490e8206381SEric Moore { 2491e8206381SEric Moore unsigned long flags; 2492e8206381SEric Moore struct scsi_cmnd *scmd; 2493e8206381SEric Moore 2494e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2495e8206381SEric Moore scmd = ioc->ScsiLookup[i]; 2496e8206381SEric Moore ioc->ScsiLookup[i] = NULL; 2497e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2498e8206381SEric Moore 2499e8206381SEric Moore return scmd; 2500e8206381SEric Moore } 2501e8206381SEric Moore 2502e8206381SEric Moore /** 25039b8f77a1SBen Hutchings * mptscsih_set_scsi_lookup - write a scmd entry into the ScsiLookup[] array list 2504e8206381SEric Moore * 2505e8206381SEric Moore * @ioc: Pointer to MPT_ADAPTER structure 2506e8206381SEric Moore * @i: index into the array 2507e8206381SEric Moore * @scmd: scsi_cmnd pointer 2508e8206381SEric Moore * 2509e8206381SEric Moore **/ 2510e8206381SEric Moore static void 2511e8206381SEric Moore mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd) 2512e8206381SEric Moore { 2513e8206381SEric Moore unsigned long flags; 2514e8206381SEric Moore 2515e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2516e8206381SEric Moore ioc->ScsiLookup[i] = scmd; 2517e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2518e8206381SEric Moore } 2519e8206381SEric Moore 2520e8206381SEric Moore /** 252123f9b75eSRandy Dunlap * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list 2522e8206381SEric Moore * @ioc: Pointer to MPT_ADAPTER structure 252323f9b75eSRandy Dunlap * @sc: scsi_cmnd pointer 252423f9b75eSRandy Dunlap */ 2525e8206381SEric Moore static int 2526e8206381SEric Moore SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc) 2527e8206381SEric Moore { 2528e8206381SEric Moore unsigned long flags; 2529e8206381SEric Moore int i, index=-1; 2530e8206381SEric Moore 2531e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2532e8206381SEric Moore for (i = 0; i < ioc->req_depth; i++) { 2533e8206381SEric Moore if (ioc->ScsiLookup[i] == sc) { 2534e8206381SEric Moore index = i; 2535e8206381SEric Moore goto out; 25361da177e4SLinus Torvalds } 25371da177e4SLinus Torvalds } 25381da177e4SLinus Torvalds 2539e8206381SEric Moore out: 2540e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2541e8206381SEric Moore return index; 25421da177e4SLinus Torvalds } 25431da177e4SLinus Torvalds 25441da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 25450d0c7974SMoore, Eric Dean int 25461da177e4SLinus Torvalds mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) 25471da177e4SLinus Torvalds { 25481da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 25491da177e4SLinus Torvalds 2550e7eae9f6SEric Moore if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) 25511da177e4SLinus Torvalds return 0; 255237c60f37SKashyap, Desai 2553e7eae9f6SEric Moore hd = shost_priv(ioc->sh); 255437c60f37SKashyap, Desai switch (reset_phase) { 255537c60f37SKashyap, Desai case MPT_IOC_SETUP_RESET: 255637c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 255737c60f37SKashyap, Desai "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); 255837c60f37SKashyap, Desai break; 255937c60f37SKashyap, Desai case MPT_IOC_PRE_RESET: 256037c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 256137c60f37SKashyap, Desai "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); 256237c60f37SKashyap, Desai mptscsih_flush_running_cmds(hd); 256337c60f37SKashyap, Desai break; 256437c60f37SKashyap, Desai case MPT_IOC_POST_RESET: 256537c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 256637c60f37SKashyap, Desai "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); 256737c60f37SKashyap, Desai if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) { 256837c60f37SKashyap, Desai ioc->internal_cmds.status |= 256937c60f37SKashyap, Desai MPT_MGMT_STATUS_DID_IOCRESET; 257037c60f37SKashyap, Desai complete(&ioc->internal_cmds.done); 25711da177e4SLinus Torvalds } 257237c60f37SKashyap, Desai break; 257337c60f37SKashyap, Desai default: 257437c60f37SKashyap, Desai break; 25751da177e4SLinus Torvalds } 25761da177e4SLinus Torvalds return 1; /* currently means nothing really */ 25771da177e4SLinus Torvalds } 25781da177e4SLinus Torvalds 25791da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 25800d0c7974SMoore, Eric Dean int 25811da177e4SLinus Torvalds mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) 25821da177e4SLinus Torvalds { 25831da177e4SLinus Torvalds u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; 25841da177e4SLinus Torvalds 258537c60f37SKashyap, Desai devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 258637c60f37SKashyap, Desai "MPT event (=%02Xh) routed to SCSI host driver!\n", 25871da177e4SLinus Torvalds ioc->name, event)); 25881da177e4SLinus Torvalds 25892f187862SKashyap, Desai if ((event == MPI_EVENT_IOC_BUS_RESET || 25902f187862SKashyap, Desai event == MPI_EVENT_EXT_BUS_RESET) && 25912f187862SKashyap, Desai (ioc->bus_type == SPI) && (ioc->soft_resets < -1)) 25922f187862SKashyap, Desai ioc->soft_resets++; 25931da177e4SLinus Torvalds 25941da177e4SLinus Torvalds return 1; /* currently means nothing really */ 25951da177e4SLinus Torvalds } 25961da177e4SLinus Torvalds 25971da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 25981da177e4SLinus Torvalds /* 25991da177e4SLinus Torvalds * Bus Scan and Domain Validation functionality ... 26001da177e4SLinus Torvalds */ 26011da177e4SLinus Torvalds 26021da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26031da177e4SLinus Torvalds /* 26041da177e4SLinus Torvalds * mptscsih_scandv_complete - Scan and DV callback routine registered 26051da177e4SLinus Torvalds * to Fustion MPT (base) driver. 26061da177e4SLinus Torvalds * 26071da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 26081da177e4SLinus Torvalds * @mf: Pointer to original MPT request frame 26091da177e4SLinus Torvalds * @mr: Pointer to MPT reply frame (NULL if TurboReply) 26101da177e4SLinus Torvalds * 26111da177e4SLinus Torvalds * This routine is called from mpt.c::mpt_interrupt() at the completion 26121da177e4SLinus Torvalds * of any SCSI IO request. 26131da177e4SLinus Torvalds * This routine is registered with the Fusion MPT (base) driver at driver 26141da177e4SLinus Torvalds * load/init time via the mpt_register() API call. 26151da177e4SLinus Torvalds * 26161da177e4SLinus Torvalds * Returns 1 indicating alloc'd request frame ptr should be freed. 26171da177e4SLinus Torvalds * 26181da177e4SLinus Torvalds * Remark: Sets a completion code and (possibly) saves sense data 26191da177e4SLinus Torvalds * in the IOC member localReply structure. 26201da177e4SLinus Torvalds * Used ONLY for DV and other internal commands. 26211da177e4SLinus Torvalds */ 26220d0c7974SMoore, Eric Dean int 262337c60f37SKashyap, Desai mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, 262437c60f37SKashyap, Desai MPT_FRAME_HDR *reply) 26251da177e4SLinus Torvalds { 26261da177e4SLinus Torvalds SCSIIORequest_t *pReq; 26271da177e4SLinus Torvalds SCSIIOReply_t *pReply; 262837c60f37SKashyap, Desai u8 cmd; 262937c60f37SKashyap, Desai u16 req_idx; 26301da177e4SLinus Torvalds u8 *sense_data; 26311da177e4SLinus Torvalds int sz; 26321da177e4SLinus Torvalds 263337c60f37SKashyap, Desai ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; 263437c60f37SKashyap, Desai ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD; 263537c60f37SKashyap, Desai if (!reply) 263637c60f37SKashyap, Desai goto out; 263737c60f37SKashyap, Desai 263837c60f37SKashyap, Desai pReply = (SCSIIOReply_t *) reply; 263937c60f37SKashyap, Desai pReq = (SCSIIORequest_t *) req; 264037c60f37SKashyap, Desai ioc->internal_cmds.completion_code = 264137c60f37SKashyap, Desai mptscsih_get_completion_code(ioc, req, reply); 264237c60f37SKashyap, Desai ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID; 264337c60f37SKashyap, Desai memcpy(ioc->internal_cmds.reply, reply, 264437c60f37SKashyap, Desai min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength)); 264537c60f37SKashyap, Desai cmd = reply->u.hdr.Function; 264637c60f37SKashyap, Desai if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || 264737c60f37SKashyap, Desai (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) && 264837c60f37SKashyap, Desai (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) { 264937c60f37SKashyap, Desai req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); 2650e80b002bSEric Moore sense_data = ((u8 *)ioc->sense_buf_pool + 26511da177e4SLinus Torvalds (req_idx * MPT_SENSE_BUFFER_ALLOC)); 26521da177e4SLinus Torvalds sz = min_t(int, pReq->SenseBufferLength, 265337c60f37SKashyap, Desai MPT_SENSE_BUFFER_ALLOC); 265437c60f37SKashyap, Desai memcpy(ioc->internal_cmds.sense, sense_data, sz); 26551da177e4SLinus Torvalds } 265637c60f37SKashyap, Desai out: 265737c60f37SKashyap, Desai if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING)) 265837c60f37SKashyap, Desai return 0; 265937c60f37SKashyap, Desai ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING; 266037c60f37SKashyap, Desai complete(&ioc->internal_cmds.done); 26611da177e4SLinus Torvalds return 1; 26621da177e4SLinus Torvalds } 26631da177e4SLinus Torvalds 26641da177e4SLinus Torvalds 266537c60f37SKashyap, Desai /** 26669b8f77a1SBen Hutchings * mptscsih_get_completion_code - get completion code from MPT request 266737c60f37SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 26689cf46a35SRandy Dunlap * @req: Pointer to original MPT request frame 26699cf46a35SRandy Dunlap * @reply: Pointer to MPT reply frame (NULL if TurboReply) 267037c60f37SKashyap, Desai * 267137c60f37SKashyap, Desai **/ 267237c60f37SKashyap, Desai static int 267337c60f37SKashyap, Desai mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, 267437c60f37SKashyap, Desai MPT_FRAME_HDR *reply) 267537c60f37SKashyap, Desai { 267637c60f37SKashyap, Desai SCSIIOReply_t *pReply; 267737c60f37SKashyap, Desai MpiRaidActionReply_t *pr; 267837c60f37SKashyap, Desai u8 scsi_status; 267937c60f37SKashyap, Desai u16 status; 268037c60f37SKashyap, Desai int completion_code; 268137c60f37SKashyap, Desai 268237c60f37SKashyap, Desai pReply = (SCSIIOReply_t *)reply; 268337c60f37SKashyap, Desai status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; 268437c60f37SKashyap, Desai scsi_status = pReply->SCSIStatus; 268537c60f37SKashyap, Desai 268637c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 268737c60f37SKashyap, Desai "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh," 268837c60f37SKashyap, Desai "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState, 268937c60f37SKashyap, Desai scsi_status, le32_to_cpu(pReply->IOCLogInfo))); 269037c60f37SKashyap, Desai 269137c60f37SKashyap, Desai switch (status) { 269237c60f37SKashyap, Desai 269337c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 269437c60f37SKashyap, Desai completion_code = MPT_SCANDV_SELECTION_TIMEOUT; 269537c60f37SKashyap, Desai break; 269637c60f37SKashyap, Desai 269737c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 269837c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ 269937c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 270037c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 270137c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 270237c60f37SKashyap, Desai break; 270337c60f37SKashyap, Desai 270437c60f37SKashyap, Desai case MPI_IOCSTATUS_BUSY: 270537c60f37SKashyap, Desai case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: 270637c60f37SKashyap, Desai completion_code = MPT_SCANDV_BUSY; 270737c60f37SKashyap, Desai break; 270837c60f37SKashyap, Desai 270937c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ 271037c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 271137c60f37SKashyap, Desai case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ 271237c60f37SKashyap, Desai if (pReply->Function == MPI_FUNCTION_CONFIG) { 271337c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 271437c60f37SKashyap, Desai } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { 271537c60f37SKashyap, Desai pr = (MpiRaidActionReply_t *)reply; 271637c60f37SKashyap, Desai if (le16_to_cpu(pr->ActionStatus) == 271737c60f37SKashyap, Desai MPI_RAID_ACTION_ASTATUS_SUCCESS) 271837c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 271937c60f37SKashyap, Desai else 272037c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 272137c60f37SKashyap, Desai } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) 272237c60f37SKashyap, Desai completion_code = MPT_SCANDV_SENSE; 272337c60f37SKashyap, Desai else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { 272437c60f37SKashyap, Desai if (req->u.scsireq.CDB[0] == INQUIRY) 272537c60f37SKashyap, Desai completion_code = MPT_SCANDV_ISSUE_SENSE; 272637c60f37SKashyap, Desai else 272737c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 272837c60f37SKashyap, Desai } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) 272937c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 273037c60f37SKashyap, Desai else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) 273137c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 273237c60f37SKashyap, Desai else if (scsi_status == MPI_SCSI_STATUS_BUSY) 273337c60f37SKashyap, Desai completion_code = MPT_SCANDV_BUSY; 273437c60f37SKashyap, Desai else 273537c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 273637c60f37SKashyap, Desai break; 273737c60f37SKashyap, Desai 273837c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 273937c60f37SKashyap, Desai if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) 274037c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 274137c60f37SKashyap, Desai else 274237c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 274337c60f37SKashyap, Desai break; 274437c60f37SKashyap, Desai default: 274537c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 274637c60f37SKashyap, Desai break; 274737c60f37SKashyap, Desai 274837c60f37SKashyap, Desai } /* switch(status) */ 274937c60f37SKashyap, Desai 275037c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 275137c60f37SKashyap, Desai " completionCode set to %08xh\n", ioc->name, completion_code)); 275237c60f37SKashyap, Desai return completion_code; 275337c60f37SKashyap, Desai } 27541da177e4SLinus Torvalds 27551da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 27561da177e4SLinus Torvalds /** 27571da177e4SLinus Torvalds * mptscsih_do_cmd - Do internal command. 27581da177e4SLinus Torvalds * @hd: MPT_SCSI_HOST pointer 27591da177e4SLinus Torvalds * @io: INTERNAL_CMD pointer. 27601da177e4SLinus Torvalds * 27611da177e4SLinus Torvalds * Issue the specified internally generated command and do command 27621da177e4SLinus Torvalds * specific cleanup. For bus scan / DV only. 27631da177e4SLinus Torvalds * NOTES: If command is Inquiry and status is good, 27641da177e4SLinus Torvalds * initialize a target structure, save the data 27651da177e4SLinus Torvalds * 27661da177e4SLinus Torvalds * Remark: Single threaded access only. 27671da177e4SLinus Torvalds * 27681da177e4SLinus Torvalds * Return: 27691da177e4SLinus Torvalds * < 0 if an illegal command or no resources 27701da177e4SLinus Torvalds * 27711da177e4SLinus Torvalds * 0 if good 27721da177e4SLinus Torvalds * 27731da177e4SLinus Torvalds * > 0 if command complete but some type of completion error. 27741da177e4SLinus Torvalds */ 27751da177e4SLinus Torvalds static int 27761da177e4SLinus Torvalds mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) 27771da177e4SLinus Torvalds { 27781da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 27791da177e4SLinus Torvalds SCSIIORequest_t *pScsiReq; 27801da177e4SLinus Torvalds int my_idx, ii, dir; 278137c60f37SKashyap, Desai int timeout; 27821da177e4SLinus Torvalds char cmdLen; 27831da177e4SLinus Torvalds char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 278437c60f37SKashyap, Desai u8 cmd = io->cmd; 2785e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 278637c60f37SKashyap, Desai int ret = 0; 278737c60f37SKashyap, Desai unsigned long timeleft; 278837c60f37SKashyap, Desai unsigned long flags; 27891da177e4SLinus Torvalds 27901ba9ab2eSKashyap, Desai /* don't send internal command during diag reset */ 27911ba9ab2eSKashyap, Desai spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 27921ba9ab2eSKashyap, Desai if (ioc->ioc_reset_in_progress) { 27931ba9ab2eSKashyap, Desai spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 27941ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 27951ba9ab2eSKashyap, Desai "%s: busy with host reset\n", ioc->name, __func__)); 27961ba9ab2eSKashyap, Desai return MPT_SCANDV_BUSY; 27971ba9ab2eSKashyap, Desai } 27981ba9ab2eSKashyap, Desai spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 27991ba9ab2eSKashyap, Desai 280037c60f37SKashyap, Desai mutex_lock(&ioc->internal_cmds.mutex); 28011da177e4SLinus Torvalds 28021da177e4SLinus Torvalds /* Set command specific information 28031da177e4SLinus Torvalds */ 28041da177e4SLinus Torvalds switch (cmd) { 28051da177e4SLinus Torvalds case INQUIRY: 28061da177e4SLinus Torvalds cmdLen = 6; 28071da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28081da177e4SLinus Torvalds CDB[0] = cmd; 28091da177e4SLinus Torvalds CDB[4] = io->size; 281037c60f37SKashyap, Desai timeout = 10; 28111da177e4SLinus Torvalds break; 28121da177e4SLinus Torvalds 28131da177e4SLinus Torvalds case TEST_UNIT_READY: 28141da177e4SLinus Torvalds cmdLen = 6; 28151da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 281637c60f37SKashyap, Desai timeout = 10; 28171da177e4SLinus Torvalds break; 28181da177e4SLinus Torvalds 28191da177e4SLinus Torvalds case START_STOP: 28201da177e4SLinus Torvalds cmdLen = 6; 28211da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28221da177e4SLinus Torvalds CDB[0] = cmd; 28231da177e4SLinus Torvalds CDB[4] = 1; /*Spin up the disk */ 282437c60f37SKashyap, Desai timeout = 15; 28251da177e4SLinus Torvalds break; 28261da177e4SLinus Torvalds 28271da177e4SLinus Torvalds case REQUEST_SENSE: 28281da177e4SLinus Torvalds cmdLen = 6; 28291da177e4SLinus Torvalds CDB[0] = cmd; 28301da177e4SLinus Torvalds CDB[4] = io->size; 28311da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 283237c60f37SKashyap, Desai timeout = 10; 28331da177e4SLinus Torvalds break; 28341da177e4SLinus Torvalds 28351da177e4SLinus Torvalds case READ_BUFFER: 28361da177e4SLinus Torvalds cmdLen = 10; 28371da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28381da177e4SLinus Torvalds CDB[0] = cmd; 28391da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_ECHO) { 28401da177e4SLinus Torvalds CDB[1] = 0x0A; 28411da177e4SLinus Torvalds } else { 28421da177e4SLinus Torvalds CDB[1] = 0x02; 28431da177e4SLinus Torvalds } 28441da177e4SLinus Torvalds 28451da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_BUF_CAP) { 28461da177e4SLinus Torvalds CDB[1] |= 0x01; 28471da177e4SLinus Torvalds } 28481da177e4SLinus Torvalds CDB[6] = (io->size >> 16) & 0xFF; 28491da177e4SLinus Torvalds CDB[7] = (io->size >> 8) & 0xFF; 28501da177e4SLinus Torvalds CDB[8] = io->size & 0xFF; 285137c60f37SKashyap, Desai timeout = 10; 28521da177e4SLinus Torvalds break; 28531da177e4SLinus Torvalds 28541da177e4SLinus Torvalds case WRITE_BUFFER: 28551da177e4SLinus Torvalds cmdLen = 10; 28561da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_WRITE; 28571da177e4SLinus Torvalds CDB[0] = cmd; 28581da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_ECHO) { 28591da177e4SLinus Torvalds CDB[1] = 0x0A; 28601da177e4SLinus Torvalds } else { 28611da177e4SLinus Torvalds CDB[1] = 0x02; 28621da177e4SLinus Torvalds } 28631da177e4SLinus Torvalds CDB[6] = (io->size >> 16) & 0xFF; 28641da177e4SLinus Torvalds CDB[7] = (io->size >> 8) & 0xFF; 28651da177e4SLinus Torvalds CDB[8] = io->size & 0xFF; 286637c60f37SKashyap, Desai timeout = 10; 28671da177e4SLinus Torvalds break; 28681da177e4SLinus Torvalds 28691da177e4SLinus Torvalds case RESERVE: 28701da177e4SLinus Torvalds cmdLen = 6; 28711da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28721da177e4SLinus Torvalds CDB[0] = cmd; 287337c60f37SKashyap, Desai timeout = 10; 28741da177e4SLinus Torvalds break; 28751da177e4SLinus Torvalds 28761da177e4SLinus Torvalds case RELEASE: 28771da177e4SLinus Torvalds cmdLen = 6; 28781da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28791da177e4SLinus Torvalds CDB[0] = cmd; 288037c60f37SKashyap, Desai timeout = 10; 28811da177e4SLinus Torvalds break; 28821da177e4SLinus Torvalds 28831da177e4SLinus Torvalds case SYNCHRONIZE_CACHE: 28841da177e4SLinus Torvalds cmdLen = 10; 28851da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28861da177e4SLinus Torvalds CDB[0] = cmd; 28871da177e4SLinus Torvalds // CDB[1] = 0x02; /* set immediate bit */ 288837c60f37SKashyap, Desai timeout = 10; 28891da177e4SLinus Torvalds break; 28901da177e4SLinus Torvalds 28911da177e4SLinus Torvalds default: 28921da177e4SLinus Torvalds /* Error Case */ 289337c60f37SKashyap, Desai ret = -EFAULT; 289437c60f37SKashyap, Desai goto out; 28951da177e4SLinus Torvalds } 28961da177e4SLinus Torvalds 28971da177e4SLinus Torvalds /* Get and Populate a free Frame 289837c60f37SKashyap, Desai * MsgContext set in mpt_get_msg_frame call 28991da177e4SLinus Torvalds */ 2900e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { 290137c60f37SKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n", 290237c60f37SKashyap, Desai ioc->name, __func__)); 290337c60f37SKashyap, Desai ret = MPT_SCANDV_BUSY; 290437c60f37SKashyap, Desai goto out; 29051da177e4SLinus Torvalds } 29061da177e4SLinus Torvalds 29071da177e4SLinus Torvalds pScsiReq = (SCSIIORequest_t *) mf; 29081da177e4SLinus Torvalds 29091da177e4SLinus Torvalds /* Get the request index */ 29101da177e4SLinus Torvalds my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 29111da177e4SLinus Torvalds ADD_INDEX_LOG(my_idx); /* for debug */ 29121da177e4SLinus Torvalds 29131da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_PHYS_DISK) { 29141da177e4SLinus Torvalds pScsiReq->TargetID = io->physDiskNum; 29151da177e4SLinus Torvalds pScsiReq->Bus = 0; 29161da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 29171da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; 29181da177e4SLinus Torvalds } else { 29191da177e4SLinus Torvalds pScsiReq->TargetID = io->id; 2920793955f5SEric Moore pScsiReq->Bus = io->channel; 29211da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 29221da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; 29231da177e4SLinus Torvalds } 29241da177e4SLinus Torvalds 29251da177e4SLinus Torvalds pScsiReq->CDBLength = cmdLen; 29261da177e4SLinus Torvalds pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; 29271da177e4SLinus Torvalds 29281da177e4SLinus Torvalds pScsiReq->Reserved = 0; 29291da177e4SLinus Torvalds 293014d0f0b0SKashyap, Desai pScsiReq->MsgFlags = mpt_msg_flags(ioc); 29311da177e4SLinus Torvalds /* MsgContext set in mpt_get_msg_fram call */ 29321da177e4SLinus Torvalds 2933793955f5SEric Moore int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); 29341da177e4SLinus Torvalds 29351da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_TAGGED_CMD) 29361da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); 29371da177e4SLinus Torvalds else 29381da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); 29391da177e4SLinus Torvalds 29401da177e4SLinus Torvalds if (cmd == REQUEST_SENSE) { 29411da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); 294237c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 294337c60f37SKashyap, Desai "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd)); 29441da177e4SLinus Torvalds } 29451da177e4SLinus Torvalds 29461da177e4SLinus Torvalds for (ii = 0; ii < 16; ii++) 29471da177e4SLinus Torvalds pScsiReq->CDB[ii] = CDB[ii]; 29481da177e4SLinus Torvalds 29491da177e4SLinus Torvalds pScsiReq->DataLength = cpu_to_le32(io->size); 2950e80b002bSEric Moore pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma 29511da177e4SLinus Torvalds + (my_idx * MPT_SENSE_BUFFER_ALLOC)); 29521da177e4SLinus Torvalds 295337c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 29549cb78c16SHannes Reinecke "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%llu\n", 295537c60f37SKashyap, Desai ioc->name, __func__, cmd, io->channel, io->id, io->lun)); 29561da177e4SLinus Torvalds 295737c60f37SKashyap, Desai if (dir == MPI_SCSIIO_CONTROL_READ) 295814d0f0b0SKashyap, Desai ioc->add_sge((char *) &pScsiReq->SGL, 295937c60f37SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma); 296037c60f37SKashyap, Desai else 296114d0f0b0SKashyap, Desai ioc->add_sge((char *) &pScsiReq->SGL, 296237c60f37SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma); 29631da177e4SLinus Torvalds 296437c60f37SKashyap, Desai INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) 2965e80b002bSEric Moore mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); 296637c60f37SKashyap, Desai timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 296737c60f37SKashyap, Desai timeout*HZ); 296837c60f37SKashyap, Desai if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 296937c60f37SKashyap, Desai ret = MPT_SCANDV_DID_RESET; 297037c60f37SKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 297137c60f37SKashyap, Desai "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__, 297237c60f37SKashyap, Desai cmd)); 297337c60f37SKashyap, Desai if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { 297437c60f37SKashyap, Desai mpt_free_msg_frame(ioc, mf); 297537c60f37SKashyap, Desai goto out; 297637c60f37SKashyap, Desai } 297737c60f37SKashyap, Desai if (!timeleft) { 297897009a29SKei Tokunaga printk(MYIOC_s_WARN_FMT 297997009a29SKei Tokunaga "Issuing Reset from %s!! doorbell=0x%08xh" 298097009a29SKei Tokunaga " cmd=0x%02x\n", 298197009a29SKei Tokunaga ioc->name, __func__, mpt_GetIocState(ioc, 0), 298297009a29SKei Tokunaga cmd); 2983d0f698c4SKashyap, Desai mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); 298437c60f37SKashyap, Desai mpt_free_msg_frame(ioc, mf); 298537c60f37SKashyap, Desai } 298637c60f37SKashyap, Desai goto out; 29871da177e4SLinus Torvalds } 29881da177e4SLinus Torvalds 298937c60f37SKashyap, Desai ret = ioc->internal_cmds.completion_code; 299037c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n", 299137c60f37SKashyap, Desai ioc->name, __func__, ret)); 299237c60f37SKashyap, Desai 299337c60f37SKashyap, Desai out: 299437c60f37SKashyap, Desai CLEAR_MGMT_STATUS(ioc->internal_cmds.status) 299537c60f37SKashyap, Desai mutex_unlock(&ioc->internal_cmds.mutex); 299637c60f37SKashyap, Desai return ret; 29971da177e4SLinus Torvalds } 29981da177e4SLinus Torvalds 29991da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 30001da177e4SLinus Torvalds /** 3001c7c82987SMoore, Eric Dean * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. 3002c7c82987SMoore, Eric Dean * @hd: Pointer to a SCSI HOST structure 3003d9489fb6SRandy Dunlap * @vdevice: virtual target device 3004c7c82987SMoore, Eric Dean * 3005c7c82987SMoore, Eric Dean * Uses the ISR, but with special processing. 3006c7c82987SMoore, Eric Dean * MUST be single-threaded. 3007c7c82987SMoore, Eric Dean * 3008c7c82987SMoore, Eric Dean */ 3009c7c82987SMoore, Eric Dean static void 3010c7c82987SMoore, Eric Dean mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) 3011c7c82987SMoore, Eric Dean { 3012c7c82987SMoore, Eric Dean INTERNAL_CMD iocmd; 30131da177e4SLinus Torvalds 3014cc78d30aSEric Moore /* Ignore hidden raid components, this is handled when the command 3015cc78d30aSEric Moore * is sent to the volume 3016cc78d30aSEric Moore */ 3017cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 3018cc78d30aSEric Moore return; 3019cc78d30aSEric Moore 3020cc78d30aSEric Moore if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted || 3021cc78d30aSEric Moore !vdevice->configured_lun) 3022cc78d30aSEric Moore return; 3023cc78d30aSEric Moore 30241da177e4SLinus Torvalds /* Following parameters will not change 30251da177e4SLinus Torvalds * in this routine. 30261da177e4SLinus Torvalds */ 30271da177e4SLinus Torvalds iocmd.cmd = SYNCHRONIZE_CACHE; 30281da177e4SLinus Torvalds iocmd.flags = 0; 30291da177e4SLinus Torvalds iocmd.physDiskNum = -1; 30301da177e4SLinus Torvalds iocmd.data = NULL; 30311da177e4SLinus Torvalds iocmd.data_dma = -1; 30321da177e4SLinus Torvalds iocmd.size = 0; 30331da177e4SLinus Torvalds iocmd.rsvd = iocmd.rsvd2 = 0; 3034793955f5SEric Moore iocmd.channel = vdevice->vtarget->channel; 3035793955f5SEric Moore iocmd.id = vdevice->vtarget->id; 3036793955f5SEric Moore iocmd.lun = vdevice->lun; 30371da177e4SLinus Torvalds 3038c7c82987SMoore, Eric Dean mptscsih_do_cmd(hd, &iocmd); 30391da177e4SLinus Torvalds } 30401da177e4SLinus Torvalds 3041edb9068dSPrakash, Sathya static ssize_t 3042ee959b00STony Jones mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr, 3043ee959b00STony Jones char *buf) 3044edb9068dSPrakash, Sathya { 3045ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3046e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3047edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3048edb9068dSPrakash, Sathya 3049edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", 3050edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, 3051edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, 3052edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, 3053edb9068dSPrakash, Sathya ioc->facts.FWVersion.Word & 0x000000FF); 3054edb9068dSPrakash, Sathya } 3055ee959b00STony Jones static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL); 3056edb9068dSPrakash, Sathya 3057edb9068dSPrakash, Sathya static ssize_t 3058ee959b00STony Jones mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr, 3059ee959b00STony Jones char *buf) 3060edb9068dSPrakash, Sathya { 3061ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3062e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3063edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3064edb9068dSPrakash, Sathya 3065edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", 3066edb9068dSPrakash, Sathya (ioc->biosVersion & 0xFF000000) >> 24, 3067edb9068dSPrakash, Sathya (ioc->biosVersion & 0x00FF0000) >> 16, 3068edb9068dSPrakash, Sathya (ioc->biosVersion & 0x0000FF00) >> 8, 3069edb9068dSPrakash, Sathya ioc->biosVersion & 0x000000FF); 3070edb9068dSPrakash, Sathya } 3071ee959b00STony Jones static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL); 3072edb9068dSPrakash, Sathya 3073edb9068dSPrakash, Sathya static ssize_t 3074ee959b00STony Jones mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr, 3075ee959b00STony Jones char *buf) 3076edb9068dSPrakash, Sathya { 3077ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3078e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3079edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3080edb9068dSPrakash, Sathya 3081edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); 3082edb9068dSPrakash, Sathya } 3083ee959b00STony Jones static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL); 3084edb9068dSPrakash, Sathya 3085edb9068dSPrakash, Sathya static ssize_t 3086ee959b00STony Jones mptscsih_version_product_show(struct device *dev, 3087ee959b00STony Jones struct device_attribute *attr, 3088ee959b00STony Jones char *buf) 3089edb9068dSPrakash, Sathya { 3090ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3091e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3092edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3093edb9068dSPrakash, Sathya 3094edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); 3095edb9068dSPrakash, Sathya } 3096ee959b00STony Jones static DEVICE_ATTR(version_product, S_IRUGO, 3097edb9068dSPrakash, Sathya mptscsih_version_product_show, NULL); 3098edb9068dSPrakash, Sathya 3099edb9068dSPrakash, Sathya static ssize_t 3100ee959b00STony Jones mptscsih_version_nvdata_persistent_show(struct device *dev, 3101ee959b00STony Jones struct device_attribute *attr, 3102ee959b00STony Jones char *buf) 3103edb9068dSPrakash, Sathya { 3104ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3105e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3106edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3107edb9068dSPrakash, Sathya 3108edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02xh\n", 3109edb9068dSPrakash, Sathya ioc->nvdata_version_persistent); 3110edb9068dSPrakash, Sathya } 3111ee959b00STony Jones static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, 3112edb9068dSPrakash, Sathya mptscsih_version_nvdata_persistent_show, NULL); 3113edb9068dSPrakash, Sathya 3114edb9068dSPrakash, Sathya static ssize_t 3115ee959b00STony Jones mptscsih_version_nvdata_default_show(struct device *dev, 3116ee959b00STony Jones struct device_attribute *attr, char *buf) 3117edb9068dSPrakash, Sathya { 3118ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3119e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3120edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3121edb9068dSPrakash, Sathya 3122edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); 3123edb9068dSPrakash, Sathya } 3124ee959b00STony Jones static DEVICE_ATTR(version_nvdata_default, S_IRUGO, 3125edb9068dSPrakash, Sathya mptscsih_version_nvdata_default_show, NULL); 3126edb9068dSPrakash, Sathya 3127edb9068dSPrakash, Sathya static ssize_t 3128ee959b00STony Jones mptscsih_board_name_show(struct device *dev, struct device_attribute *attr, 3129ee959b00STony Jones char *buf) 3130edb9068dSPrakash, Sathya { 3131ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3132e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3133edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3134edb9068dSPrakash, Sathya 3135edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); 3136edb9068dSPrakash, Sathya } 3137ee959b00STony Jones static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL); 3138edb9068dSPrakash, Sathya 3139edb9068dSPrakash, Sathya static ssize_t 3140ee959b00STony Jones mptscsih_board_assembly_show(struct device *dev, 3141ee959b00STony Jones struct device_attribute *attr, char *buf) 3142edb9068dSPrakash, Sathya { 3143ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3144e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3145edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3146edb9068dSPrakash, Sathya 3147edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); 3148edb9068dSPrakash, Sathya } 3149ee959b00STony Jones static DEVICE_ATTR(board_assembly, S_IRUGO, 3150edb9068dSPrakash, Sathya mptscsih_board_assembly_show, NULL); 3151edb9068dSPrakash, Sathya 3152edb9068dSPrakash, Sathya static ssize_t 3153ee959b00STony Jones mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr, 3154ee959b00STony Jones char *buf) 3155edb9068dSPrakash, Sathya { 3156ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3157e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3158edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3159edb9068dSPrakash, Sathya 3160edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); 3161edb9068dSPrakash, Sathya } 3162ee959b00STony Jones static DEVICE_ATTR(board_tracer, S_IRUGO, 3163edb9068dSPrakash, Sathya mptscsih_board_tracer_show, NULL); 3164edb9068dSPrakash, Sathya 3165edb9068dSPrakash, Sathya static ssize_t 3166ee959b00STony Jones mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr, 3167ee959b00STony Jones char *buf) 3168edb9068dSPrakash, Sathya { 3169ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3170e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3171edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3172edb9068dSPrakash, Sathya 3173edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); 3174edb9068dSPrakash, Sathya } 3175ee959b00STony Jones static DEVICE_ATTR(io_delay, S_IRUGO, 3176edb9068dSPrakash, Sathya mptscsih_io_delay_show, NULL); 3177edb9068dSPrakash, Sathya 3178edb9068dSPrakash, Sathya static ssize_t 3179ee959b00STony Jones mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr, 3180ee959b00STony Jones char *buf) 3181edb9068dSPrakash, Sathya { 3182ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3183e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3184edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3185edb9068dSPrakash, Sathya 3186edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); 3187edb9068dSPrakash, Sathya } 3188ee959b00STony Jones static DEVICE_ATTR(device_delay, S_IRUGO, 3189edb9068dSPrakash, Sathya mptscsih_device_delay_show, NULL); 3190edb9068dSPrakash, Sathya 31916757d6b4SPrakash, Sathya static ssize_t 3192ee959b00STony Jones mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr, 3193ee959b00STony Jones char *buf) 31946757d6b4SPrakash, Sathya { 3195ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3196e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 31976757d6b4SPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 31986757d6b4SPrakash, Sathya 31996757d6b4SPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level); 32006757d6b4SPrakash, Sathya } 32016757d6b4SPrakash, Sathya static ssize_t 3202ee959b00STony Jones mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr, 3203ee959b00STony Jones const char *buf, size_t count) 32046757d6b4SPrakash, Sathya { 3205ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3206e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 32076757d6b4SPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 32086757d6b4SPrakash, Sathya int val = 0; 32096757d6b4SPrakash, Sathya 32106757d6b4SPrakash, Sathya if (sscanf(buf, "%x", &val) != 1) 32116757d6b4SPrakash, Sathya return -EINVAL; 32126757d6b4SPrakash, Sathya 32136757d6b4SPrakash, Sathya ioc->debug_level = val; 32146757d6b4SPrakash, Sathya printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n", 32156757d6b4SPrakash, Sathya ioc->name, ioc->debug_level); 32166757d6b4SPrakash, Sathya return strlen(buf); 32176757d6b4SPrakash, Sathya } 3218ee959b00STony Jones static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR, 32196757d6b4SPrakash, Sathya mptscsih_debug_level_show, mptscsih_debug_level_store); 32206757d6b4SPrakash, Sathya 3221ee959b00STony Jones struct device_attribute *mptscsih_host_attrs[] = { 3222ee959b00STony Jones &dev_attr_version_fw, 3223ee959b00STony Jones &dev_attr_version_bios, 3224ee959b00STony Jones &dev_attr_version_mpi, 3225ee959b00STony Jones &dev_attr_version_product, 3226ee959b00STony Jones &dev_attr_version_nvdata_persistent, 3227ee959b00STony Jones &dev_attr_version_nvdata_default, 3228ee959b00STony Jones &dev_attr_board_name, 3229ee959b00STony Jones &dev_attr_board_assembly, 3230ee959b00STony Jones &dev_attr_board_tracer, 3231ee959b00STony Jones &dev_attr_io_delay, 3232ee959b00STony Jones &dev_attr_device_delay, 3233ee959b00STony Jones &dev_attr_debug_level, 3234edb9068dSPrakash, Sathya NULL, 3235edb9068dSPrakash, Sathya }; 323637c60f37SKashyap, Desai 3237edb9068dSPrakash, Sathya EXPORT_SYMBOL(mptscsih_host_attrs); 3238edb9068dSPrakash, Sathya 32390d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_remove); 32400d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_shutdown); 32410d0c7974SMoore, Eric Dean #ifdef CONFIG_PM 32420d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_suspend); 32430d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_resume); 32440d0c7974SMoore, Eric Dean #endif 3245cac19703SAl Viro EXPORT_SYMBOL(mptscsih_show_info); 32460d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_info); 32470d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_qcmd); 32480d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_slave_destroy); 32490d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_slave_configure); 32500d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_abort); 32510d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_dev_reset); 32520d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_bus_reset); 32530d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_host_reset); 32540d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_bios_param); 32550d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_io_done); 32560d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_taskmgmt_complete); 32570d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_scandv_complete); 32580d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_event_process); 32590d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_ioc_reset); 32606e3815baSMoore, Eric Dean EXPORT_SYMBOL(mptscsih_change_queue_depth); 32611da177e4SLinus Torvalds 32620d0c7974SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3263