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, 981ba9ab2eSKashyap, Desai int 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); 5392f187862SKashyap, Desai printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d, lun = %d\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; 6671da177e4SLinus Torvalds scsi_state = pScsiReply->SCSIState; 6681da177e4SLinus Torvalds scsi_status = pScsiReply->SCSIStatus; 6691da177e4SLinus Torvalds xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); 6701928d73fSFUJITA Tomonori scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); 671c6c727a1SEric Moore log_info = le32_to_cpu(pScsiReply->IOCLogInfo); 6721da177e4SLinus Torvalds 673466544d8SMoore, Eric Dean /* 674466544d8SMoore, Eric Dean * if we get a data underrun indication, yet no data was 675466544d8SMoore, Eric Dean * transferred and the SCSI status indicates that the 676466544d8SMoore, Eric Dean * command was never started, change the data underrun 677466544d8SMoore, Eric Dean * to success 678466544d8SMoore, Eric Dean */ 679466544d8SMoore, Eric Dean if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && 680466544d8SMoore, Eric Dean (scsi_status == MPI_SCSI_STATUS_BUSY || 681466544d8SMoore, Eric Dean scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT || 682466544d8SMoore, Eric Dean scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) { 683466544d8SMoore, Eric Dean status = MPI_IOCSTATUS_SUCCESS; 684466544d8SMoore, Eric Dean } 685466544d8SMoore, Eric Dean 6861da177e4SLinus Torvalds if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) 6870d0c7974SMoore, Eric Dean mptscsih_copy_sense_data(sc, hd, mf, pScsiReply); 6881da177e4SLinus Torvalds 6891da177e4SLinus Torvalds /* 6901da177e4SLinus Torvalds * Look for + dump FCP ResponseInfo[]! 6911da177e4SLinus Torvalds */ 692466544d8SMoore, Eric Dean if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && 693466544d8SMoore, Eric Dean pScsiReply->ResponseInfo) { 69429dd3609SEric Moore printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] " 69529dd3609SEric Moore "FCP_ResponseInfo=%08xh\n", ioc->name, 696c6c727a1SEric Moore sc->device->host->host_no, sc->device->channel, 697c6c727a1SEric Moore sc->device->id, sc->device->lun, 6981da177e4SLinus Torvalds le32_to_cpu(pScsiReply->ResponseInfo)); 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds switch(status) { 7021da177e4SLinus Torvalds case MPI_IOCSTATUS_BUSY: /* 0x0002 */ 703d23321b4SKashyap, Desai case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ 7041da177e4SLinus Torvalds /* CHECKME! 7051da177e4SLinus Torvalds * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry) 7061da177e4SLinus Torvalds * But not: DID_BUS_BUSY lest one risk 7071da177e4SLinus Torvalds * killing interrupt handler:-( 7081da177e4SLinus Torvalds */ 7091da177e4SLinus Torvalds sc->result = SAM_STAT_BUSY; 7101da177e4SLinus Torvalds break; 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ 7131da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ 7141da177e4SLinus Torvalds sc->result = DID_BAD_TARGET << 16; 7151da177e4SLinus Torvalds break; 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 7181da177e4SLinus Torvalds /* Spoof to SCSI Selection Timeout! */ 71965207fedSMoore, Eric if (ioc->bus_type != FC) 7201da177e4SLinus Torvalds sc->result = DID_NO_CONNECT << 16; 72165207fedSMoore, Eric /* else fibre, just stall until rescan event */ 72265207fedSMoore, Eric else 72365207fedSMoore, Eric sc->result = DID_REQUEUE << 16; 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) 7261da177e4SLinus Torvalds hd->sel_timeout[pScsiReq->TargetID]++; 727786899b0SEric Moore 728a69de507SEric Moore vdevice = sc->device->hostdata; 729a69de507SEric Moore if (!vdevice) 730786899b0SEric Moore break; 731a69de507SEric Moore vtarget = vdevice->vtarget; 732786899b0SEric Moore if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) { 733786899b0SEric Moore mptscsih_issue_sep_command(ioc, vtarget, 734786899b0SEric Moore MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED); 735786899b0SEric Moore vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON; 736786899b0SEric Moore } 7371da177e4SLinus Torvalds break; 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 740bf451522SEric Moore if ( ioc->bus_type == SAS ) { 741bf451522SEric Moore u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus); 742bf451522SEric Moore if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { 743c6c727a1SEric Moore if ((log_info & SAS_LOGINFO_MASK) 744c6c727a1SEric Moore == SAS_LOGINFO_NEXUS_LOSS) { 745bf451522SEric Moore sc->result = (DID_BUS_BUSY << 16); 746bf451522SEric Moore break; 747bf451522SEric Moore } 748bf451522SEric Moore } 74986dd4242SEric Moore } else if (ioc->bus_type == FC) { 75086dd4242SEric Moore /* 75186dd4242SEric Moore * The FC IOC may kill a request for variety of 75286dd4242SEric Moore * reasons, some of which may be recovered by a 75386dd4242SEric Moore * retry, some which are unlikely to be 75486dd4242SEric Moore * recovered. Return DID_ERROR instead of 75586dd4242SEric Moore * DID_RESET to permit retry of the command, 75686dd4242SEric Moore * just not an infinite number of them 75786dd4242SEric Moore */ 75886dd4242SEric Moore sc->result = DID_ERROR << 16; 75986dd4242SEric Moore break; 760bf451522SEric Moore } 761bf451522SEric Moore 762bf451522SEric Moore /* 763bf451522SEric Moore * Allow non-SAS & non-NEXUS_LOSS to drop into below code 764bf451522SEric Moore */ 765bf451522SEric Moore 766bf451522SEric Moore case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ 7671da177e4SLinus Torvalds /* Linux handles an unsolicited DID_RESET better 7681da177e4SLinus Torvalds * than an unsolicited DID_ABORT. 7691da177e4SLinus Torvalds */ 7701da177e4SLinus Torvalds sc->result = DID_RESET << 16; 7711da177e4SLinus Torvalds 7722f187862SKashyap, Desai case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 7732f187862SKashyap, Desai if (ioc->bus_type == FC) 7742f187862SKashyap, Desai sc->result = DID_ERROR << 16; 7752f187862SKashyap, Desai else 7762f187862SKashyap, Desai sc->result = DID_RESET << 16; 7771da177e4SLinus Torvalds break; 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ 7801928d73fSFUJITA Tomonori scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt); 781466544d8SMoore, Eric Dean if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) 7821da177e4SLinus Torvalds sc->result=DID_SOFT_ERROR << 16; 783466544d8SMoore, Eric Dean else /* Sufficient data transfer occurred */ 784466544d8SMoore, Eric Dean sc->result = (DID_OK << 16) | scsi_status; 78529dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 786c6c727a1SEric Moore "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", 78729dd3609SEric Moore ioc->name, sc->result, sc->device->channel, sc->device->id)); 7881da177e4SLinus Torvalds break; 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ 7911da177e4SLinus Torvalds /* 7921da177e4SLinus Torvalds * Do upfront check for valid SenseData and give it 7931da177e4SLinus Torvalds * precedence! 7941da177e4SLinus Torvalds */ 7951da177e4SLinus Torvalds sc->result = (DID_OK << 16) | scsi_status; 7969b53b392SKashyap, Desai if (!(scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)) { 7979b53b392SKashyap, Desai 7989b53b392SKashyap, Desai /* 7999b53b392SKashyap, Desai * For an Errata on LSI53C1030 8009b53b392SKashyap, Desai * When the length of request data 8019b53b392SKashyap, Desai * and transfer data are different 8029b53b392SKashyap, Desai * with result of command (READ or VERIFY), 8039b53b392SKashyap, Desai * DID_SOFT_ERROR is set. 8041da177e4SLinus Torvalds */ 8059b53b392SKashyap, Desai if (ioc->bus_type == SPI) { 8069b53b392SKashyap, Desai if (pScsiReq->CDB[0] == READ_6 || 8079b53b392SKashyap, Desai pScsiReq->CDB[0] == READ_10 || 8089b53b392SKashyap, Desai pScsiReq->CDB[0] == READ_12 || 8099b53b392SKashyap, Desai pScsiReq->CDB[0] == READ_16 || 8109b53b392SKashyap, Desai pScsiReq->CDB[0] == VERIFY || 8119b53b392SKashyap, Desai pScsiReq->CDB[0] == VERIFY_16) { 8129b53b392SKashyap, Desai if (scsi_bufflen(sc) != 8139b53b392SKashyap, Desai xfer_cnt) { 8149b53b392SKashyap, Desai sc->result = 8159b53b392SKashyap, Desai DID_SOFT_ERROR << 16; 8169b53b392SKashyap, Desai printk(KERN_WARNING "Errata" 8179b53b392SKashyap, Desai "on LSI53C1030 occurred." 8189b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 8199b53b392SKashyap, Desai "xfer_cnt=0x%02x\n", 8209b53b392SKashyap, Desai scsi_bufflen(sc), 8219b53b392SKashyap, Desai xfer_cnt); 8229b53b392SKashyap, Desai } 8239b53b392SKashyap, Desai } 8249b53b392SKashyap, Desai } 8259b53b392SKashyap, Desai 8261da177e4SLinus Torvalds if (xfer_cnt < sc->underflow) { 827466544d8SMoore, Eric Dean if (scsi_status == SAM_STAT_BUSY) 828466544d8SMoore, Eric Dean sc->result = SAM_STAT_BUSY; 829466544d8SMoore, Eric Dean else 8301da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { 8331da177e4SLinus Torvalds /* What to do? 8341da177e4SLinus Torvalds */ 8351da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 8361da177e4SLinus Torvalds } 8371da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { 8381da177e4SLinus Torvalds /* Not real sure here either... */ 8391da177e4SLinus Torvalds sc->result = DID_RESET << 16; 8401da177e4SLinus Torvalds } 8411da177e4SLinus Torvalds } 8421da177e4SLinus Torvalds 8436757d6b4SPrakash, Sathya 84429dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 84529dd3609SEric Moore " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", 84629dd3609SEric Moore ioc->name, sc->underflow)); 84729dd3609SEric Moore dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT 84829dd3609SEric Moore " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt)); 8496757d6b4SPrakash, Sathya 8501da177e4SLinus Torvalds /* Report Queue Full 8511da177e4SLinus Torvalds */ 8521da177e4SLinus Torvalds if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL) 8531da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds break; 8561da177e4SLinus Torvalds 8577e55147fSMoore, Eric case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ 8581928d73fSFUJITA Tomonori scsi_set_resid(sc, 0); 8591da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 8601da177e4SLinus Torvalds case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ 8611da177e4SLinus Torvalds sc->result = (DID_OK << 16) | scsi_status; 8621da177e4SLinus Torvalds if (scsi_state == 0) { 8631da177e4SLinus Torvalds ; 8649b53b392SKashyap, Desai } else if (scsi_state & 8659b53b392SKashyap, Desai MPI_SCSI_STATE_AUTOSENSE_VALID) { 8669b53b392SKashyap, Desai 8679b53b392SKashyap, Desai /* 8689b53b392SKashyap, Desai * For potential trouble on LSI53C1030. 8699b53b392SKashyap, Desai * (date:2007.xx.) 8709b53b392SKashyap, Desai * It is checked whether the length of 8719b53b392SKashyap, Desai * request data is equal to 8729b53b392SKashyap, Desai * the length of transfer and residual. 8739b53b392SKashyap, Desai * MEDIUM_ERROR is set by incorrect data. 8749b53b392SKashyap, Desai */ 8759b53b392SKashyap, Desai if ((ioc->bus_type == SPI) && 8769b53b392SKashyap, Desai (sc->sense_buffer[2] & 0x20)) { 8779b53b392SKashyap, Desai u32 difftransfer; 8789b53b392SKashyap, Desai difftransfer = 8799b53b392SKashyap, Desai sc->sense_buffer[3] << 24 | 8809b53b392SKashyap, Desai sc->sense_buffer[4] << 16 | 8819b53b392SKashyap, Desai sc->sense_buffer[5] << 8 | 8829b53b392SKashyap, Desai sc->sense_buffer[6]; 8839b53b392SKashyap, Desai if (((sc->sense_buffer[3] & 0x80) == 8849b53b392SKashyap, Desai 0x80) && (scsi_bufflen(sc) 8859b53b392SKashyap, Desai != xfer_cnt)) { 8869b53b392SKashyap, Desai sc->sense_buffer[2] = 8879b53b392SKashyap, Desai MEDIUM_ERROR; 8889b53b392SKashyap, Desai sc->sense_buffer[12] = 0xff; 8899b53b392SKashyap, Desai sc->sense_buffer[13] = 0xff; 8909b53b392SKashyap, Desai printk(KERN_WARNING"Errata" 8919b53b392SKashyap, Desai "on LSI53C1030 occurred." 8929b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 8939b53b392SKashyap, Desai "xfer_cnt=0x%02x\n" , 8949b53b392SKashyap, Desai scsi_bufflen(sc), 8959b53b392SKashyap, Desai xfer_cnt); 8969b53b392SKashyap, Desai } 8979b53b392SKashyap, Desai if (((sc->sense_buffer[3] & 0x80) 8989b53b392SKashyap, Desai != 0x80) && 8999b53b392SKashyap, Desai (scsi_bufflen(sc) != 9009b53b392SKashyap, Desai xfer_cnt + difftransfer)) { 9019b53b392SKashyap, Desai sc->sense_buffer[2] = 9029b53b392SKashyap, Desai MEDIUM_ERROR; 9039b53b392SKashyap, Desai sc->sense_buffer[12] = 0xff; 9049b53b392SKashyap, Desai sc->sense_buffer[13] = 0xff; 9059b53b392SKashyap, Desai printk(KERN_WARNING 9069b53b392SKashyap, Desai "Errata on LSI53C1030 occurred" 9079b53b392SKashyap, Desai "sc->req_bufflen=0x%02x," 9089b53b392SKashyap, Desai " xfer_cnt=0x%02x," 9099b53b392SKashyap, Desai "difftransfer=0x%02x\n", 9109b53b392SKashyap, Desai scsi_bufflen(sc), 9119b53b392SKashyap, Desai xfer_cnt, 9129b53b392SKashyap, Desai difftransfer); 9139b53b392SKashyap, Desai } 9149b53b392SKashyap, Desai } 9159b53b392SKashyap, Desai 9161da177e4SLinus Torvalds /* 9171da177e4SLinus Torvalds * If running against circa 200003dd 909 MPT f/w, 9181da177e4SLinus Torvalds * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL 9191da177e4SLinus Torvalds * (QUEUE_FULL) returned from device! --> get 0x0000?128 9201da177e4SLinus Torvalds * and with SenseBytes set to 0. 9211da177e4SLinus Torvalds */ 9221da177e4SLinus Torvalds if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL) 9231da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds else if (scsi_state & 9271da177e4SLinus Torvalds (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS) 9281da177e4SLinus Torvalds ) { 9291da177e4SLinus Torvalds /* 9301da177e4SLinus Torvalds * What to do? 9311da177e4SLinus Torvalds */ 9321da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_TERMINATED) { 9351da177e4SLinus Torvalds /* Not real sure here either... */ 9361da177e4SLinus Torvalds sc->result = DID_RESET << 16; 9371da177e4SLinus Torvalds } 9381da177e4SLinus Torvalds else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) { 9391da177e4SLinus Torvalds /* Device Inq. data indicates that it supports 9401da177e4SLinus Torvalds * QTags, but rejects QTag messages. 9411da177e4SLinus Torvalds * This command completed OK. 9421da177e4SLinus Torvalds * 9431da177e4SLinus Torvalds * Not real sure here either so do nothing... */ 9441da177e4SLinus Torvalds } 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL) 9471da177e4SLinus Torvalds mptscsih_report_queue_full(sc, pScsiReply, pScsiReq); 9481da177e4SLinus Torvalds 9491da177e4SLinus Torvalds /* Add handling of: 9501da177e4SLinus Torvalds * Reservation Conflict, Busy, 9511da177e4SLinus Torvalds * Command Terminated, CHECK 9521da177e4SLinus Torvalds */ 9531da177e4SLinus Torvalds break; 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 9561da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 9571da177e4SLinus Torvalds break; 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ 9601da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ 9611da177e4SLinus Torvalds case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ 9621da177e4SLinus Torvalds case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ 9631da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ 9641da177e4SLinus Torvalds case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ 9651da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 9661da177e4SLinus Torvalds case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ 9671da177e4SLinus Torvalds default: 9681da177e4SLinus Torvalds /* 9691da177e4SLinus Torvalds * What to do? 9701da177e4SLinus Torvalds */ 9711da177e4SLinus Torvalds sc->result = DID_SOFT_ERROR << 16; 9721da177e4SLinus Torvalds break; 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds } /* switch(status) */ 9751da177e4SLinus Torvalds 9766757d6b4SPrakash, Sathya #ifdef CONFIG_FUSION_LOGGING 9776757d6b4SPrakash, Sathya if (sc->result && (ioc->debug_level & MPT_DEBUG_REPLY)) 9786757d6b4SPrakash, Sathya mptscsih_info_scsiio(ioc, sc, pScsiReply); 979c6c727a1SEric Moore #endif 980c6c727a1SEric Moore 9811da177e4SLinus Torvalds } /* end of address reply case */ 982fea98403SKashyap, Desai out: 9831da177e4SLinus Torvalds /* Unmap the DMA buffers, if any. */ 9841928d73fSFUJITA Tomonori scsi_dma_unmap(sc); 9851da177e4SLinus Torvalds 9861da177e4SLinus Torvalds sc->scsi_done(sc); /* Issue the command callback */ 9871da177e4SLinus Torvalds 9881da177e4SLinus Torvalds /* Free Chain buffers */ 9891da177e4SLinus Torvalds mptscsih_freeChainBuffers(ioc, req_idx); 9901da177e4SLinus Torvalds return 1; 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds /* 9941da177e4SLinus Torvalds * mptscsih_flush_running_cmds - For each command found, search 9951da177e4SLinus Torvalds * Scsi_Host instance taskQ and reply to OS. 9961da177e4SLinus Torvalds * Called only if recovering from a FW reload. 9971da177e4SLinus Torvalds * @hd: Pointer to a SCSI HOST structure 9981da177e4SLinus Torvalds * 9991da177e4SLinus Torvalds * Returns: None. 10001da177e4SLinus Torvalds * 10011da177e4SLinus Torvalds * Must be called while new I/Os are being queued. 10021da177e4SLinus Torvalds */ 10031da177e4SLinus Torvalds static void 10041da177e4SLinus Torvalds mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) 10051da177e4SLinus Torvalds { 10061da177e4SLinus Torvalds MPT_ADAPTER *ioc = hd->ioc; 1007e8206381SEric Moore struct scsi_cmnd *sc; 1008e8206381SEric Moore SCSIIORequest_t *mf = NULL; 10091da177e4SLinus Torvalds int ii; 1010e8206381SEric Moore int channel, id; 10111da177e4SLinus Torvalds 1012e8206381SEric Moore for (ii= 0; ii < ioc->req_depth; ii++) { 1013e8206381SEric Moore sc = mptscsih_getclear_scsi_lookup(ioc, ii); 1014e8206381SEric Moore if (!sc) 10153dc0b03fSEric Moore continue; 1016e8206381SEric Moore mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); 1017e8206381SEric Moore if (!mf) 1018e8206381SEric Moore continue; 1019e8206381SEric Moore channel = mf->Bus; 1020e8206381SEric Moore id = mf->TargetID; 1021e8206381SEric Moore mptscsih_freeChainBuffers(ioc, ii); 1022e8206381SEric Moore mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); 1023e8206381SEric Moore if ((unsigned char *)mf != sc->host_scribble) 1024e8206381SEric Moore continue; 1025e8206381SEric Moore scsi_dma_unmap(sc); 1026e8206381SEric Moore sc->result = DID_RESET << 16; 1027e8206381SEric Moore sc->host_scribble = NULL; 10282f187862SKashyap, Desai dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT 10292f187862SKashyap, Desai "completing cmds: fw_channel %d, fw_id %d, sc=%p, mf = %p, " 10302f187862SKashyap, Desai "idx=%x\n", ioc->name, channel, id, sc, mf, ii)); 1031e8206381SEric Moore sc->scsi_done(sc); 10321da177e4SLinus Torvalds } 10331da177e4SLinus Torvalds } 10341da177e4SLinus Torvalds 10351da177e4SLinus Torvalds /* 10361da177e4SLinus Torvalds * mptscsih_search_running_cmds - Delete any commands associated 10371da177e4SLinus Torvalds * with the specified target and lun. Function called only 10381da177e4SLinus Torvalds * when a lun is disable by mid-layer. 10391da177e4SLinus Torvalds * Do NOT access the referenced scsi_cmnd structure or 10401da177e4SLinus Torvalds * members. Will cause either a paging or NULL ptr error. 104105e8ec17SMichael Reed * (BUT, BUT, BUT, the code does reference it! - mdr) 10421da177e4SLinus Torvalds * @hd: Pointer to a SCSI HOST structure 1043c7c82987SMoore, Eric Dean * @vdevice: per device private data 10441da177e4SLinus Torvalds * 10451da177e4SLinus Torvalds * Returns: None. 10461da177e4SLinus Torvalds * 10471da177e4SLinus Torvalds * Called from slave_destroy. 10481da177e4SLinus Torvalds */ 10491da177e4SLinus Torvalds static void 1050c7c82987SMoore, Eric Dean mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) 10511da177e4SLinus Torvalds { 10521da177e4SLinus Torvalds SCSIIORequest_t *mf = NULL; 10531da177e4SLinus Torvalds int ii; 1054466544d8SMoore, Eric Dean struct scsi_cmnd *sc; 1055793955f5SEric Moore struct scsi_lun lun; 1056e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 1057e8206381SEric Moore unsigned long flags; 10581da177e4SLinus Torvalds 1059e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 1060e8206381SEric Moore for (ii = 0; ii < ioc->req_depth; ii++) { 1061e8206381SEric Moore if ((sc = ioc->ScsiLookup[ii]) != NULL) { 10621da177e4SLinus Torvalds 1063e80b002bSEric Moore mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); 10643dc0b03fSEric Moore if (mf == NULL) 10653dc0b03fSEric Moore continue; 1066cc78d30aSEric Moore /* If the device is a hidden raid component, then its 1067cc78d30aSEric Moore * expected that the mf->function will be RAID_SCSI_IO 1068cc78d30aSEric Moore */ 1069cc78d30aSEric Moore if (vdevice->vtarget->tflags & 1070cc78d30aSEric Moore MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function != 1071cc78d30aSEric Moore MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) 1072cc78d30aSEric Moore continue; 1073cc78d30aSEric Moore 1074793955f5SEric Moore int_to_scsilun(vdevice->lun, &lun); 1075793955f5SEric Moore if ((mf->Bus != vdevice->vtarget->channel) || 1076793955f5SEric Moore (mf->TargetID != vdevice->vtarget->id) || 1077793955f5SEric Moore memcmp(lun.scsi_lun, mf->LUN, 8)) 10781da177e4SLinus Torvalds continue; 10791da177e4SLinus Torvalds 10803dc0b03fSEric Moore if ((unsigned char *)mf != sc->host_scribble) 10813dc0b03fSEric Moore continue; 1082e8206381SEric Moore ioc->ScsiLookup[ii] = NULL; 1083e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 1084e8206381SEric Moore mptscsih_freeChainBuffers(ioc, ii); 1085e8206381SEric Moore mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); 10861928d73fSFUJITA Tomonori scsi_dma_unmap(sc); 1087466544d8SMoore, Eric Dean sc->host_scribble = NULL; 1088466544d8SMoore, Eric Dean sc->result = DID_NO_CONNECT << 16; 10892f187862SKashyap, Desai dtmprintk(ioc, sdev_printk(KERN_INFO, sc->device, 10902f187862SKashyap, Desai MYIOC_s_FMT "completing cmds: fw_channel %d, " 10912f187862SKashyap, Desai "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, 10922f187862SKashyap, Desai vdevice->vtarget->channel, vdevice->vtarget->id, 10932f187862SKashyap, Desai sc, mf, ii)); 1094466544d8SMoore, Eric Dean sc->scsi_done(sc); 1095e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 10961da177e4SLinus Torvalds } 10971da177e4SLinus Torvalds } 1098e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 10991da177e4SLinus Torvalds return; 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11051da177e4SLinus Torvalds /* 11061da177e4SLinus Torvalds * mptscsih_report_queue_full - Report QUEUE_FULL status returned 11071da177e4SLinus Torvalds * from a SCSI target device. 11081da177e4SLinus Torvalds * @sc: Pointer to scsi_cmnd structure 11091da177e4SLinus Torvalds * @pScsiReply: Pointer to SCSIIOReply_t 11101da177e4SLinus Torvalds * @pScsiReq: Pointer to original SCSI request 11111da177e4SLinus Torvalds * 11121da177e4SLinus Torvalds * This routine periodically reports QUEUE_FULL status returned from a 11131da177e4SLinus Torvalds * SCSI target device. It reports this to the console via kernel 11141da177e4SLinus Torvalds * printk() API call, not more than once every 10 seconds. 11151da177e4SLinus Torvalds */ 11161da177e4SLinus Torvalds static void 11171da177e4SLinus Torvalds mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq) 11181da177e4SLinus Torvalds { 11191da177e4SLinus Torvalds long time = jiffies; 11201da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1121e80b002bSEric Moore MPT_ADAPTER *ioc; 11221da177e4SLinus Torvalds 11230d0c7974SMoore, Eric Dean if (sc->device == NULL) 11240d0c7974SMoore, Eric Dean return; 11250d0c7974SMoore, Eric Dean if (sc->device->host == NULL) 11260d0c7974SMoore, Eric Dean return; 1127e7eae9f6SEric Moore if ((hd = shost_priv(sc->device->host)) == NULL) 11280d0c7974SMoore, Eric Dean return; 1129e80b002bSEric Moore ioc = hd->ioc; 11300d0c7974SMoore, Eric Dean if (time - hd->last_queue_full > 10 * HZ) { 1131e80b002bSEric Moore dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", 1132e80b002bSEric Moore ioc->name, 0, sc->device->id, sc->device->lun)); 11330d0c7974SMoore, Eric Dean hd->last_queue_full = time; 11341da177e4SLinus Torvalds } 11351da177e4SLinus Torvalds } 11361da177e4SLinus Torvalds 11371da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11381da177e4SLinus Torvalds /* 11391da177e4SLinus Torvalds * mptscsih_remove - Removed scsi devices 11401da177e4SLinus Torvalds * @pdev: Pointer to pci_dev structure 11411da177e4SLinus Torvalds * 11421da177e4SLinus Torvalds * 11431da177e4SLinus Torvalds */ 11440d0c7974SMoore, Eric Dean void 11451da177e4SLinus Torvalds mptscsih_remove(struct pci_dev *pdev) 11461da177e4SLinus Torvalds { 11471da177e4SLinus Torvalds MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 11481da177e4SLinus Torvalds struct Scsi_Host *host = ioc->sh; 11491da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 11500d0c7974SMoore, Eric Dean int sz1; 11511da177e4SLinus Torvalds 1152466544d8SMoore, Eric Dean if(!host) { 1153466544d8SMoore, Eric Dean mpt_detach(pdev); 11541da177e4SLinus Torvalds return; 1155466544d8SMoore, Eric Dean } 11561da177e4SLinus Torvalds 11571da177e4SLinus Torvalds scsi_remove_host(host); 11581da177e4SLinus Torvalds 1159e7eae9f6SEric Moore if((hd = shost_priv(host)) == NULL) 11600d0c7974SMoore, Eric Dean return; 11610d0c7974SMoore, Eric Dean 1162d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(pdev); 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds sz1=0; 11651da177e4SLinus Torvalds 1166e8206381SEric Moore if (ioc->ScsiLookup != NULL) { 1167e80b002bSEric Moore sz1 = ioc->req_depth * sizeof(void *); 1168e8206381SEric Moore kfree(ioc->ScsiLookup); 1169e8206381SEric Moore ioc->ScsiLookup = NULL; 11701da177e4SLinus Torvalds } 11711da177e4SLinus Torvalds 1172e80b002bSEric Moore dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 11731da177e4SLinus Torvalds "Free'd ScsiLookup (%d) memory\n", 1174e80b002bSEric Moore ioc->name, sz1)); 11751da177e4SLinus Torvalds 11760d0c7974SMoore, Eric Dean kfree(hd->info_kbuf); 11770d0c7974SMoore, Eric Dean 11781da177e4SLinus Torvalds /* NULL the Scsi_Host pointer 11791da177e4SLinus Torvalds */ 1180e80b002bSEric Moore ioc->sh = NULL; 11811da177e4SLinus Torvalds 11821da177e4SLinus Torvalds scsi_host_put(host); 11830d0c7974SMoore, Eric Dean 11840d0c7974SMoore, Eric Dean mpt_detach(pdev); 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds } 11871da177e4SLinus Torvalds 11881da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11891da177e4SLinus Torvalds /* 11901da177e4SLinus Torvalds * mptscsih_shutdown - reboot notifier 11911da177e4SLinus Torvalds * 11921da177e4SLinus Torvalds */ 11930d0c7974SMoore, Eric Dean void 1194d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(struct pci_dev *pdev) 11951da177e4SLinus Torvalds { 11961da177e4SLinus Torvalds } 11971da177e4SLinus Torvalds 11981da177e4SLinus Torvalds #ifdef CONFIG_PM 11991da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12001da177e4SLinus Torvalds /* 12010d0c7974SMoore, Eric Dean * mptscsih_suspend - Fusion MPT scsi driver suspend routine. 12021da177e4SLinus Torvalds * 12031da177e4SLinus Torvalds * 12041da177e4SLinus Torvalds */ 12050d0c7974SMoore, Eric Dean int 12068d189f72SPavel Machek mptscsih_suspend(struct pci_dev *pdev, pm_message_t state) 12071da177e4SLinus Torvalds { 12084d4109d0SPrakash, Sathya MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 12094d4109d0SPrakash, Sathya 12104d4109d0SPrakash, Sathya scsi_block_requests(ioc->sh); 12114d4109d0SPrakash, Sathya flush_scheduled_work(); 1212d18c3db5SGreg Kroah-Hartman mptscsih_shutdown(pdev); 12130d0c7974SMoore, Eric Dean return mpt_suspend(pdev,state); 12141da177e4SLinus Torvalds } 12151da177e4SLinus Torvalds 12161da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12171da177e4SLinus Torvalds /* 12181da177e4SLinus Torvalds * mptscsih_resume - Fusion MPT scsi driver resume routine. 12191da177e4SLinus Torvalds * 12201da177e4SLinus Torvalds * 12211da177e4SLinus Torvalds */ 12220d0c7974SMoore, Eric Dean int 12231da177e4SLinus Torvalds mptscsih_resume(struct pci_dev *pdev) 12241da177e4SLinus Torvalds { 12254d4109d0SPrakash, Sathya MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 12264d4109d0SPrakash, Sathya int rc; 12274d4109d0SPrakash, Sathya 12284d4109d0SPrakash, Sathya rc = mpt_resume(pdev); 12294d4109d0SPrakash, Sathya scsi_unblock_requests(ioc->sh); 12304d4109d0SPrakash, Sathya return rc; 12311da177e4SLinus Torvalds } 12321da177e4SLinus Torvalds 12331da177e4SLinus Torvalds #endif 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12361da177e4SLinus Torvalds /** 12371da177e4SLinus Torvalds * mptscsih_info - Return information about MPT adapter 12381da177e4SLinus Torvalds * @SChost: Pointer to Scsi_Host structure 12391da177e4SLinus Torvalds * 12401da177e4SLinus Torvalds * (linux scsi_host_template.info routine) 12411da177e4SLinus Torvalds * 12421da177e4SLinus Torvalds * Returns pointer to buffer where information was written. 12431da177e4SLinus Torvalds */ 12440d0c7974SMoore, Eric Dean const char * 12451da177e4SLinus Torvalds mptscsih_info(struct Scsi_Host *SChost) 12461da177e4SLinus Torvalds { 12471da177e4SLinus Torvalds MPT_SCSI_HOST *h; 12481da177e4SLinus Torvalds int size = 0; 12491da177e4SLinus Torvalds 1250e7eae9f6SEric Moore h = shost_priv(SChost); 12510d0c7974SMoore, Eric Dean 12521da177e4SLinus Torvalds if (h) { 12530d0c7974SMoore, Eric Dean if (h->info_kbuf == NULL) 12540d0c7974SMoore, Eric Dean if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL) 12550d0c7974SMoore, Eric Dean return h->info_kbuf; 12560d0c7974SMoore, Eric Dean h->info_kbuf[0] = '\0'; 12570d0c7974SMoore, Eric Dean 12580d0c7974SMoore, Eric Dean mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0); 12590d0c7974SMoore, Eric Dean h->info_kbuf[size-1] = '\0'; 12601da177e4SLinus Torvalds } 12611da177e4SLinus Torvalds 12620d0c7974SMoore, Eric Dean return h->info_kbuf; 12631da177e4SLinus Torvalds } 12641da177e4SLinus Torvalds 12651da177e4SLinus Torvalds struct info_str { 12661da177e4SLinus Torvalds char *buffer; 12671da177e4SLinus Torvalds int length; 12681da177e4SLinus Torvalds int offset; 12691da177e4SLinus Torvalds int pos; 12701da177e4SLinus Torvalds }; 12711da177e4SLinus Torvalds 12720d0c7974SMoore, Eric Dean static void 12730d0c7974SMoore, Eric Dean mptscsih_copy_mem_info(struct info_str *info, char *data, int len) 12741da177e4SLinus Torvalds { 12751da177e4SLinus Torvalds if (info->pos + len > info->length) 12761da177e4SLinus Torvalds len = info->length - info->pos; 12771da177e4SLinus Torvalds 12781da177e4SLinus Torvalds if (info->pos + len < info->offset) { 12791da177e4SLinus Torvalds info->pos += len; 12801da177e4SLinus Torvalds return; 12811da177e4SLinus Torvalds } 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds if (info->pos < info->offset) { 12841da177e4SLinus Torvalds data += (info->offset - info->pos); 12851da177e4SLinus Torvalds len -= (info->offset - info->pos); 12861da177e4SLinus Torvalds } 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds if (len > 0) { 12891da177e4SLinus Torvalds memcpy(info->buffer + info->pos, data, len); 12901da177e4SLinus Torvalds info->pos += len; 12911da177e4SLinus Torvalds } 12921da177e4SLinus Torvalds } 12931da177e4SLinus Torvalds 12940d0c7974SMoore, Eric Dean static int 12950d0c7974SMoore, Eric Dean mptscsih_copy_info(struct info_str *info, char *fmt, ...) 12961da177e4SLinus Torvalds { 12971da177e4SLinus Torvalds va_list args; 12981da177e4SLinus Torvalds char buf[81]; 12991da177e4SLinus Torvalds int len; 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvalds va_start(args, fmt); 13021da177e4SLinus Torvalds len = vsprintf(buf, fmt, args); 13031da177e4SLinus Torvalds va_end(args); 13041da177e4SLinus Torvalds 13050d0c7974SMoore, Eric Dean mptscsih_copy_mem_info(info, buf, len); 13061da177e4SLinus Torvalds return len; 13071da177e4SLinus Torvalds } 13081da177e4SLinus Torvalds 13090d0c7974SMoore, Eric Dean static int 13100d0c7974SMoore, Eric Dean mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) 13111da177e4SLinus Torvalds { 13121da177e4SLinus Torvalds struct info_str info; 13131da177e4SLinus Torvalds 13141da177e4SLinus Torvalds info.buffer = pbuf; 13151da177e4SLinus Torvalds info.length = len; 13161da177e4SLinus Torvalds info.offset = offset; 13171da177e4SLinus Torvalds info.pos = 0; 13181da177e4SLinus Torvalds 13190d0c7974SMoore, Eric Dean mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name); 13200d0c7974SMoore, Eric Dean mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word); 13210d0c7974SMoore, Eric Dean mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts); 13220d0c7974SMoore, Eric Dean mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth); 13231da177e4SLinus Torvalds 13241da177e4SLinus Torvalds return ((info.pos > info.offset) ? info.pos - info.offset : 0); 13251da177e4SLinus Torvalds } 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13281da177e4SLinus Torvalds /** 13291da177e4SLinus Torvalds * mptscsih_proc_info - Return information about MPT adapter 1330d9489fb6SRandy Dunlap * @host: scsi host struct 1331d9489fb6SRandy Dunlap * @buffer: if write, user data; if read, buffer for user 1332d9489fb6SRandy Dunlap * @start: returns the buffer address 1333d9489fb6SRandy Dunlap * @offset: if write, 0; if read, the current offset into the buffer from 1334d9489fb6SRandy Dunlap * the previous read. 1335d9489fb6SRandy Dunlap * @length: if write, return length; 1336d9489fb6SRandy Dunlap * @func: write = 1; read = 0 13371da177e4SLinus Torvalds * 13381da177e4SLinus Torvalds * (linux scsi_host_template.info routine) 13391da177e4SLinus Torvalds */ 13400d0c7974SMoore, Eric Dean int 13411da177e4SLinus Torvalds mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, 13421da177e4SLinus Torvalds int length, int func) 13431da177e4SLinus Torvalds { 1344e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 13451da177e4SLinus Torvalds MPT_ADAPTER *ioc = hd->ioc; 13461da177e4SLinus Torvalds int size = 0; 13471da177e4SLinus Torvalds 13481da177e4SLinus Torvalds if (func) { 13491da177e4SLinus Torvalds /* 13501da177e4SLinus Torvalds * write is not supported 13511da177e4SLinus Torvalds */ 13521da177e4SLinus Torvalds } else { 13531da177e4SLinus Torvalds if (start) 13541da177e4SLinus Torvalds *start = buffer; 13551da177e4SLinus Torvalds 13561da177e4SLinus Torvalds size = mptscsih_host_info(ioc, buffer, offset, length); 13571da177e4SLinus Torvalds } 13581da177e4SLinus Torvalds 13591da177e4SLinus Torvalds return size; 13601da177e4SLinus Torvalds } 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13631da177e4SLinus Torvalds #define ADD_INDEX_LOG(req_ent) do { } while(0) 13641da177e4SLinus Torvalds 13651da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13661da177e4SLinus Torvalds /** 13671da177e4SLinus Torvalds * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine. 13681da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure 13691da177e4SLinus Torvalds * @done: Pointer SCSI mid-layer IO completion function 13701da177e4SLinus Torvalds * 13711da177e4SLinus Torvalds * (linux scsi_host_template.queuecommand routine) 13721da177e4SLinus Torvalds * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest 13731da177e4SLinus Torvalds * from a linux scsi_cmnd request and send it to the IOC. 13741da177e4SLinus Torvalds * 13751da177e4SLinus Torvalds * Returns 0. (rtn value discarded by linux scsi mid-layer) 13761da177e4SLinus Torvalds */ 13770d0c7974SMoore, Eric Dean int 13781da177e4SLinus Torvalds mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) 13791da177e4SLinus Torvalds { 13801da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 13811da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 13821da177e4SLinus Torvalds SCSIIORequest_t *pScsiReq; 1383a69de507SEric Moore VirtDevice *vdevice = SCpnt->device->hostdata; 13841da177e4SLinus Torvalds u32 datalen; 13851da177e4SLinus Torvalds u32 scsictl; 13861da177e4SLinus Torvalds u32 scsidir; 13871da177e4SLinus Torvalds u32 cmd_len; 13881da177e4SLinus Torvalds int my_idx; 13891da177e4SLinus Torvalds int ii; 13906757d6b4SPrakash, Sathya MPT_ADAPTER *ioc; 13911da177e4SLinus Torvalds 1392e7eae9f6SEric Moore hd = shost_priv(SCpnt->device->host); 13936757d6b4SPrakash, Sathya ioc = hd->ioc; 13941da177e4SLinus Torvalds SCpnt->scsi_done = done; 13951da177e4SLinus Torvalds 13966757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p, done()=%p\n", 13976757d6b4SPrakash, Sathya ioc->name, SCpnt, done)); 13981da177e4SLinus Torvalds 1399e7deff33SKashyap, Desai if (ioc->taskmgmt_quiesce_io) { 14006757d6b4SPrakash, Sathya dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n", 14016757d6b4SPrakash, Sathya ioc->name, SCpnt)); 14021da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 14031da177e4SLinus Torvalds } 14041da177e4SLinus Torvalds 14051da177e4SLinus Torvalds /* 14061da177e4SLinus Torvalds * Put together a MPT SCSI request... 14071da177e4SLinus Torvalds */ 1408e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { 14096757d6b4SPrakash, Sathya dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", 14106757d6b4SPrakash, Sathya ioc->name)); 14111da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 14121da177e4SLinus Torvalds } 14131da177e4SLinus Torvalds 14141da177e4SLinus Torvalds pScsiReq = (SCSIIORequest_t *) mf; 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds ADD_INDEX_LOG(my_idx); 14191da177e4SLinus Torvalds 14200d0c7974SMoore, Eric Dean /* TUR's being issued with scsictl=0x02000000 (DATA_IN)! 14211da177e4SLinus Torvalds * Seems we may receive a buffer (datalen>0) even when there 14221da177e4SLinus Torvalds * will be no data transfer! GRRRRR... 14231da177e4SLinus Torvalds */ 14241da177e4SLinus Torvalds if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { 14251928d73fSFUJITA Tomonori datalen = scsi_bufflen(SCpnt); 14261da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */ 14271da177e4SLinus Torvalds } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { 14281928d73fSFUJITA Tomonori datalen = scsi_bufflen(SCpnt); 14291da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */ 14301da177e4SLinus Torvalds } else { 14311da177e4SLinus Torvalds datalen = 0; 14321da177e4SLinus Torvalds scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER; 14331da177e4SLinus Torvalds } 14341da177e4SLinus Torvalds 14351da177e4SLinus Torvalds /* Default to untagged. Once a target structure has been allocated, 14361da177e4SLinus Torvalds * use the Inquiry data to determine if device supports tagged. 14371da177e4SLinus Torvalds */ 1438a69de507SEric Moore if (vdevice 1439a69de507SEric Moore && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) 14401da177e4SLinus Torvalds && (SCpnt->device->tagged_supported)) { 14411da177e4SLinus Torvalds scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; 144265f89c23SKashyap, Desai if (SCpnt->request && SCpnt->request->ioprio) { 144365f89c23SKashyap, Desai if (((SCpnt->request->ioprio & 0x7) == 1) || 144465f89c23SKashyap, Desai !(SCpnt->request->ioprio & 0x7)) 144565f89c23SKashyap, Desai scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ; 14461da177e4SLinus Torvalds } 144765f89c23SKashyap, Desai } else 144865f89c23SKashyap, Desai scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED; 144965f89c23SKashyap, Desai 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds /* Use the above information to set up the message frame 14521da177e4SLinus Torvalds */ 1453a69de507SEric Moore pScsiReq->TargetID = (u8) vdevice->vtarget->id; 1454a69de507SEric Moore pScsiReq->Bus = vdevice->vtarget->channel; 14551da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 1456a69de507SEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 1457c92f222eSJames Bottomley pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; 1458c92f222eSJames Bottomley else 14591da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; 14601da177e4SLinus Torvalds pScsiReq->CDBLength = SCpnt->cmd_len; 14611da177e4SLinus Torvalds pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; 14621da177e4SLinus Torvalds pScsiReq->Reserved = 0; 146314d0f0b0SKashyap, Desai pScsiReq->MsgFlags = mpt_msg_flags(ioc); 1464793955f5SEric Moore int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN); 14651da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(scsictl); 14661da177e4SLinus Torvalds 14671da177e4SLinus Torvalds /* 14681da177e4SLinus Torvalds * Write SCSI CDB into the message 14691da177e4SLinus Torvalds */ 14701da177e4SLinus Torvalds cmd_len = SCpnt->cmd_len; 14711da177e4SLinus Torvalds for (ii=0; ii < cmd_len; ii++) 14721da177e4SLinus Torvalds pScsiReq->CDB[ii] = SCpnt->cmnd[ii]; 14731da177e4SLinus Torvalds 14741da177e4SLinus Torvalds for (ii=cmd_len; ii < 16; ii++) 14751da177e4SLinus Torvalds pScsiReq->CDB[ii] = 0; 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds /* DataLength */ 14781da177e4SLinus Torvalds pScsiReq->DataLength = cpu_to_le32(datalen); 14791da177e4SLinus Torvalds 14801da177e4SLinus Torvalds /* SenseBuffer low address */ 1481e80b002bSEric Moore pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma 14821da177e4SLinus Torvalds + (my_idx * MPT_SENSE_BUFFER_ALLOC)); 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds /* Now add the SG list 14851da177e4SLinus Torvalds * Always have a SGE even if null length. 14861da177e4SLinus Torvalds */ 14871da177e4SLinus Torvalds if (datalen == 0) { 14881da177e4SLinus Torvalds /* Add a NULL SGE */ 148914d0f0b0SKashyap, Desai ioc->add_sge((char *)&pScsiReq->SGL, 149014d0f0b0SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_READ | 0, 14911da177e4SLinus Torvalds (dma_addr_t) -1); 14921da177e4SLinus Torvalds } else { 14931da177e4SLinus Torvalds /* Add a 32 or 64 bit SGE */ 1494e80b002bSEric Moore if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) 14951da177e4SLinus Torvalds goto fail; 14961da177e4SLinus Torvalds } 14971da177e4SLinus Torvalds 14983dc0b03fSEric Moore SCpnt->host_scribble = (unsigned char *)mf; 1499e8206381SEric Moore mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt); 15001da177e4SLinus Torvalds 1501e80b002bSEric Moore mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); 15026757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", 15036757d6b4SPrakash, Sathya ioc->name, SCpnt, mf, my_idx)); 150429dd3609SEric Moore DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf); 15051da177e4SLinus Torvalds return 0; 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds fail: 1508e80b002bSEric Moore mptscsih_freeChainBuffers(ioc, my_idx); 1509e80b002bSEric Moore mpt_free_msg_frame(ioc, mf); 15101da177e4SLinus Torvalds return SCSI_MLQUEUE_HOST_BUSY; 15111da177e4SLinus Torvalds } 15121da177e4SLinus Torvalds 15131da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 15141da177e4SLinus Torvalds /* 15151da177e4SLinus Torvalds * mptscsih_freeChainBuffers - Function to free chain buffers associated 15161da177e4SLinus Torvalds * with a SCSI IO request 15171da177e4SLinus Torvalds * @hd: Pointer to the MPT_SCSI_HOST instance 15181da177e4SLinus Torvalds * @req_idx: Index of the SCSI IO request frame. 15191da177e4SLinus Torvalds * 15201da177e4SLinus Torvalds * Called if SG chain buffer allocation fails and mptscsih callbacks. 15211da177e4SLinus Torvalds * No return. 15221da177e4SLinus Torvalds */ 15231da177e4SLinus Torvalds static void 15241da177e4SLinus Torvalds mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) 15251da177e4SLinus Torvalds { 15261da177e4SLinus Torvalds MPT_FRAME_HDR *chain; 15271da177e4SLinus Torvalds unsigned long flags; 15281da177e4SLinus Torvalds int chain_idx; 15291da177e4SLinus Torvalds int next; 15301da177e4SLinus Torvalds 15311da177e4SLinus Torvalds /* Get the first chain index and reset 15321da177e4SLinus Torvalds * tracker state. 15331da177e4SLinus Torvalds */ 15341da177e4SLinus Torvalds chain_idx = ioc->ReqToChain[req_idx]; 15351da177e4SLinus Torvalds ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN; 15361da177e4SLinus Torvalds 15371da177e4SLinus Torvalds while (chain_idx != MPT_HOST_NO_CHAIN) { 15381da177e4SLinus Torvalds 15391da177e4SLinus Torvalds /* Save the next chain buffer index */ 15401da177e4SLinus Torvalds next = ioc->ChainToChain[chain_idx]; 15411da177e4SLinus Torvalds 15421da177e4SLinus Torvalds /* Free this chain buffer and reset 15431da177e4SLinus Torvalds * tracker 15441da177e4SLinus Torvalds */ 15451da177e4SLinus Torvalds ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN; 15461da177e4SLinus Torvalds 15471da177e4SLinus Torvalds chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer 15481da177e4SLinus Torvalds + (chain_idx * ioc->req_sz)); 15491da177e4SLinus Torvalds 15501da177e4SLinus Torvalds spin_lock_irqsave(&ioc->FreeQlock, flags); 15511da177e4SLinus Torvalds list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ); 15521da177e4SLinus Torvalds spin_unlock_irqrestore(&ioc->FreeQlock, flags); 15531da177e4SLinus Torvalds 15546757d6b4SPrakash, Sathya dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n", 15551da177e4SLinus Torvalds ioc->name, chain_idx)); 15561da177e4SLinus Torvalds 15571da177e4SLinus Torvalds /* handle next */ 15581da177e4SLinus Torvalds chain_idx = next; 15591da177e4SLinus Torvalds } 15601da177e4SLinus Torvalds return; 15611da177e4SLinus Torvalds } 15621da177e4SLinus Torvalds 15631da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 15641da177e4SLinus Torvalds /* 15651da177e4SLinus Torvalds * Reset Handling 15661da177e4SLinus Torvalds */ 15671da177e4SLinus Torvalds 15681da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1569cd2c6191SEric Moore /** 15701da177e4SLinus Torvalds * mptscsih_IssueTaskMgmt - Generic send Task Management function. 15711da177e4SLinus Torvalds * @hd: Pointer to MPT_SCSI_HOST structure 15721da177e4SLinus Torvalds * @type: Task Management type 15731544d677SRandy Dunlap * @channel: channel number for task management 1574793955f5SEric Moore * @id: Logical Target ID for reset (if appropriate) 15751da177e4SLinus Torvalds * @lun: Logical Unit for reset (if appropriate) 15761da177e4SLinus Torvalds * @ctx2abort: Context for the task to be aborted (if appropriate) 15771544d677SRandy Dunlap * @timeout: timeout for task management control 15781da177e4SLinus Torvalds * 15791da177e4SLinus Torvalds * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) 15801da177e4SLinus Torvalds * or a non-interrupt thread. In the former, must not call schedule(). 15811da177e4SLinus Torvalds * 15821da177e4SLinus Torvalds * Not all fields are meaningfull for all task types. 15831da177e4SLinus Torvalds * 1584cd2c6191SEric Moore * Returns 0 for SUCCESS, or FAILED. 1585cd2c6191SEric Moore * 1586cd2c6191SEric Moore **/ 15871ba9ab2eSKashyap, Desai int 15881ba9ab2eSKashyap, Desai mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, 15891ba9ab2eSKashyap, Desai int ctx2abort, ulong timeout) 15901da177e4SLinus Torvalds { 15911da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 15921da177e4SLinus Torvalds SCSITaskMgmt_t *pScsiTm; 15931da177e4SLinus Torvalds int ii; 15941da177e4SLinus Torvalds int retval; 1595e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 15961ba9ab2eSKashyap, Desai unsigned long timeleft; 15971ba9ab2eSKashyap, Desai u8 issue_hard_reset; 15981ba9ab2eSKashyap, Desai u32 ioc_raw_state; 15991ba9ab2eSKashyap, Desai unsigned long time_count; 16001ba9ab2eSKashyap, Desai 16011ba9ab2eSKashyap, Desai issue_hard_reset = 0; 16021ba9ab2eSKashyap, Desai ioc_raw_state = mpt_GetIocState(ioc, 0); 16031ba9ab2eSKashyap, Desai 16041ba9ab2eSKashyap, Desai if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { 16051ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT 16061ba9ab2eSKashyap, Desai "TaskMgmt type=%x: IOC Not operational (0x%x)!\n", 16071ba9ab2eSKashyap, Desai ioc->name, type, ioc_raw_state); 16081ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", 16091ba9ab2eSKashyap, Desai ioc->name, __func__); 16101ba9ab2eSKashyap, Desai if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) 16111ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset " 16121ba9ab2eSKashyap, Desai "FAILED!!\n", ioc->name); 16131ba9ab2eSKashyap, Desai return 0; 16141ba9ab2eSKashyap, Desai } 16151ba9ab2eSKashyap, Desai 16161ba9ab2eSKashyap, Desai if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { 16171ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT 16181ba9ab2eSKashyap, Desai "TaskMgmt type=%x: ioc_state: " 16191ba9ab2eSKashyap, Desai "DOORBELL_ACTIVE (0x%x)!\n", 16201ba9ab2eSKashyap, Desai ioc->name, type, ioc_raw_state); 16211ba9ab2eSKashyap, Desai return FAILED; 16221ba9ab2eSKashyap, Desai } 16231ba9ab2eSKashyap, Desai 16241ba9ab2eSKashyap, Desai mutex_lock(&ioc->taskmgmt_cmds.mutex); 16251ba9ab2eSKashyap, Desai if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { 16261ba9ab2eSKashyap, Desai mf = NULL; 16271ba9ab2eSKashyap, Desai retval = FAILED; 16281ba9ab2eSKashyap, Desai goto out; 16291ba9ab2eSKashyap, Desai } 16301da177e4SLinus Torvalds 16311da177e4SLinus Torvalds /* Return Fail to calling function if no message frames available. 16321da177e4SLinus Torvalds */ 1633e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { 16341ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 16351ba9ab2eSKashyap, Desai "TaskMgmt no msg frames!!\n", ioc->name)); 16361ba9ab2eSKashyap, Desai retval = FAILED; 16371ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 16381ba9ab2eSKashyap, Desai goto out; 16391da177e4SLinus Torvalds } 16401ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", 1641e80b002bSEric Moore ioc->name, mf)); 16421da177e4SLinus Torvalds 16431da177e4SLinus Torvalds /* Format the Request 16441da177e4SLinus Torvalds */ 16451da177e4SLinus Torvalds pScsiTm = (SCSITaskMgmt_t *) mf; 1646793955f5SEric Moore pScsiTm->TargetID = id; 16471da177e4SLinus Torvalds pScsiTm->Bus = channel; 16481da177e4SLinus Torvalds pScsiTm->ChainOffset = 0; 16491da177e4SLinus Torvalds pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; 16501da177e4SLinus Torvalds 16511da177e4SLinus Torvalds pScsiTm->Reserved = 0; 16521da177e4SLinus Torvalds pScsiTm->TaskType = type; 16531da177e4SLinus Torvalds pScsiTm->Reserved1 = 0; 16541da177e4SLinus Torvalds pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) 16551da177e4SLinus Torvalds ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0; 16561da177e4SLinus Torvalds 1657793955f5SEric Moore int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN); 16581da177e4SLinus Torvalds 16591da177e4SLinus Torvalds for (ii=0; ii < 7; ii++) 16601da177e4SLinus Torvalds pScsiTm->Reserved2[ii] = 0; 16611da177e4SLinus Torvalds 16621da177e4SLinus Torvalds pScsiTm->TaskMsgContext = ctx2abort; 16631da177e4SLinus Torvalds 16641ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) " 16651ba9ab2eSKashyap, Desai "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort, 16661ba9ab2eSKashyap, Desai type, timeout)); 16671da177e4SLinus Torvalds 16686757d6b4SPrakash, Sathya DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); 16691da177e4SLinus Torvalds 16701ba9ab2eSKashyap, Desai INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) 16711ba9ab2eSKashyap, Desai time_count = jiffies; 1672e80b002bSEric Moore if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && 1673e80b002bSEric Moore (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) 1674e80b002bSEric Moore mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); 16757a195f46SPrakash, Sathya else { 1676e80b002bSEric Moore retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, 16777a195f46SPrakash, Sathya sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); 16787a195f46SPrakash, Sathya if (retval) { 16791ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_ERR_FMT 16801ba9ab2eSKashyap, Desai "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n", 16811ba9ab2eSKashyap, Desai ioc->name, mf, retval)); 1682e80b002bSEric Moore mpt_free_msg_frame(ioc, mf); 16831ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 16841ba9ab2eSKashyap, Desai goto out; 16851da177e4SLinus Torvalds } 16861ba9ab2eSKashyap, Desai } 16871ba9ab2eSKashyap, Desai 16881ba9ab2eSKashyap, Desai timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, 16891ba9ab2eSKashyap, Desai timeout*HZ); 16901ba9ab2eSKashyap, Desai if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 16911ba9ab2eSKashyap, Desai retval = FAILED; 16921ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_ERR_FMT 16931ba9ab2eSKashyap, Desai "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf)); 16941ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 16951ba9ab2eSKashyap, Desai if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) 16961ba9ab2eSKashyap, Desai goto out; 16971ba9ab2eSKashyap, Desai issue_hard_reset = 1; 16981ba9ab2eSKashyap, Desai goto out; 16991ba9ab2eSKashyap, Desai } 17001ba9ab2eSKashyap, Desai 17011ba9ab2eSKashyap, Desai retval = mptscsih_taskmgmt_reply(ioc, type, 17021ba9ab2eSKashyap, Desai (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply); 17031ba9ab2eSKashyap, Desai 17041ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 17051ba9ab2eSKashyap, Desai "TaskMgmt completed (%d seconds)\n", 17061ba9ab2eSKashyap, Desai ioc->name, jiffies_to_msecs(jiffies - time_count)/1000)); 17071ba9ab2eSKashyap, Desai 17081ba9ab2eSKashyap, Desai out: 17091ba9ab2eSKashyap, Desai 17101ba9ab2eSKashyap, Desai CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status) 17111ba9ab2eSKashyap, Desai if (issue_hard_reset) { 17121ba9ab2eSKashyap, Desai printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", 17131ba9ab2eSKashyap, Desai ioc->name, __func__); 17141ba9ab2eSKashyap, Desai retval = mpt_HardResetHandler(ioc, CAN_SLEEP); 17151ba9ab2eSKashyap, Desai mpt_free_msg_frame(ioc, mf); 17161ba9ab2eSKashyap, Desai } 17171ba9ab2eSKashyap, Desai 17181ba9ab2eSKashyap, Desai retval = (retval == 0) ? 0 : FAILED; 17191ba9ab2eSKashyap, Desai mutex_unlock(&ioc->taskmgmt_cmds.mutex); 17201ba9ab2eSKashyap, Desai return retval; 17211ba9ab2eSKashyap, Desai } 17221ba9ab2eSKashyap, Desai EXPORT_SYMBOL(mptscsih_IssueTaskMgmt); 17231da177e4SLinus Torvalds 1724d66c7a0fSChristoph Hellwig static int 1725d66c7a0fSChristoph Hellwig mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) 1726d66c7a0fSChristoph Hellwig { 1727d66c7a0fSChristoph Hellwig switch (ioc->bus_type) { 1728d66c7a0fSChristoph Hellwig case FC: 1729d66c7a0fSChristoph Hellwig return 40; 1730d66c7a0fSChristoph Hellwig case SAS: 1731d66c7a0fSChristoph Hellwig case SPI: 1732d66c7a0fSChristoph Hellwig default: 173322ab019bSBernd Schubert return 10; 1734d66c7a0fSChristoph Hellwig } 1735d66c7a0fSChristoph Hellwig } 1736d66c7a0fSChristoph Hellwig 17371da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 17381da177e4SLinus Torvalds /** 17391da177e4SLinus Torvalds * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant 17401da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted 17411da177e4SLinus Torvalds * 17421da177e4SLinus Torvalds * (linux scsi_host_template.eh_abort_handler routine) 17431da177e4SLinus Torvalds * 17441da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1745cd2c6191SEric Moore **/ 17460d0c7974SMoore, Eric Dean int 17471da177e4SLinus Torvalds mptscsih_abort(struct scsi_cmnd * SCpnt) 17481da177e4SLinus Torvalds { 17491da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 17501da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 17511da177e4SLinus Torvalds u32 ctx2abort; 17521da177e4SLinus Torvalds int scpnt_idx; 1753466544d8SMoore, Eric Dean int retval; 1754958d4a32SEric Moore VirtDevice *vdevice; 17553dc0b03fSEric Moore ulong sn = SCpnt->serial_number; 1756958d4a32SEric Moore MPT_ADAPTER *ioc; 17571da177e4SLinus Torvalds 17581da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 17591da177e4SLinus Torvalds */ 1760e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL) { 17611da177e4SLinus Torvalds SCpnt->result = DID_RESET << 16; 17621da177e4SLinus Torvalds SCpnt->scsi_done(SCpnt); 176329dd3609SEric Moore printk(KERN_ERR MYNAM ": task abort: " 176429dd3609SEric Moore "can't locate host! (sc=%p)\n", SCpnt); 17651da177e4SLinus Torvalds return FAILED; 17661da177e4SLinus Torvalds } 17671da177e4SLinus Torvalds 1768958d4a32SEric Moore ioc = hd->ioc; 1769958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n", 1770958d4a32SEric Moore ioc->name, SCpnt); 1771958d4a32SEric Moore scsi_print_command(SCpnt); 1772958d4a32SEric Moore 1773958d4a32SEric Moore vdevice = SCpnt->device->hostdata; 1774958d4a32SEric Moore if (!vdevice || !vdevice->vtarget) { 177529dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 177629dd3609SEric Moore "task abort: device has been deleted (sc=%p)\n", 177729dd3609SEric Moore ioc->name, SCpnt)); 1778958d4a32SEric Moore SCpnt->result = DID_NO_CONNECT << 16; 1779958d4a32SEric Moore SCpnt->scsi_done(SCpnt); 1780958d4a32SEric Moore retval = 0; 1781958d4a32SEric Moore goto out; 1782958d4a32SEric Moore } 1783958d4a32SEric Moore 1784cc78d30aSEric Moore /* Task aborts are not supported for hidden raid components. 1785cc78d30aSEric Moore */ 1786cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 178729dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 178829dd3609SEric Moore "task abort: hidden raid component (sc=%p)\n", 178929dd3609SEric Moore ioc->name, SCpnt)); 1790cc78d30aSEric Moore SCpnt->result = DID_RESET << 16; 1791cc78d30aSEric Moore retval = FAILED; 1792cc78d30aSEric Moore goto out; 1793cc78d30aSEric Moore } 1794cc78d30aSEric Moore 17951da177e4SLinus Torvalds /* Find this command 17961da177e4SLinus Torvalds */ 1797e8206381SEric Moore if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { 17981da177e4SLinus Torvalds /* Cmd not found in ScsiLookup. 17991da177e4SLinus Torvalds * Do OS callback. 18001da177e4SLinus Torvalds */ 18011da177e4SLinus Torvalds SCpnt->result = DID_RESET << 16; 180229dd3609SEric Moore dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " 1803958d4a32SEric Moore "Command not in the active list! (sc=%p)\n", ioc->name, 1804958d4a32SEric Moore SCpnt)); 18059858ae38SKashyap, Desai retval = SUCCESS; 1806958d4a32SEric Moore goto out; 18071da177e4SLinus Torvalds } 18081da177e4SLinus Torvalds 18092f187862SKashyap, Desai if (ioc->timeouts < -1) 18102f187862SKashyap, Desai ioc->timeouts++; 181165207fedSMoore, Eric 18122f4c782cSKashyap, Desai if (mpt_fwfault_debug) 18132f4c782cSKashyap, Desai mpt_halt_firmware(ioc); 18142f4c782cSKashyap, Desai 18151da177e4SLinus Torvalds /* Most important! Set TaskMsgContext to SCpnt's MsgContext! 18161da177e4SLinus Torvalds * (the IO to be ABORT'd) 18171da177e4SLinus Torvalds * 18181da177e4SLinus Torvalds * NOTE: Since we do not byteswap MsgContext, we do not 18191da177e4SLinus Torvalds * swap it here either. It is an opaque cookie to 18201da177e4SLinus Torvalds * the controller, so it does not matter. -DaveM 18211da177e4SLinus Torvalds */ 1822e80b002bSEric Moore mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx); 18231da177e4SLinus Torvalds ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; 18241ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 18251ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 18261ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 18271ba9ab2eSKashyap, Desai vdevice->vtarget->id, vdevice->lun, 1828958d4a32SEric Moore ctx2abort, mptscsih_get_tm_timeout(ioc)); 18291da177e4SLinus Torvalds 1830e8206381SEric Moore if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && 18312f187862SKashyap, Desai SCpnt->serial_number == sn) { 18322f187862SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 18332f187862SKashyap, Desai "task abort: command still in active list! (sc=%p)\n", 18342f187862SKashyap, Desai ioc->name, SCpnt)); 18353dc0b03fSEric Moore retval = FAILED; 18362f187862SKashyap, Desai } else { 18372f187862SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 18382f187862SKashyap, Desai "task abort: command cleared from active list! (sc=%p)\n", 18392f187862SKashyap, Desai ioc->name, SCpnt)); 18402f187862SKashyap, Desai retval = SUCCESS; 18412f187862SKashyap, Desai } 18423dc0b03fSEric Moore 1843958d4a32SEric Moore out: 1844958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "task abort: %s (sc=%p)\n", 18452f187862SKashyap, Desai ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), SCpnt); 18461da177e4SLinus Torvalds 18472f187862SKashyap, Desai return retval; 18481da177e4SLinus Torvalds } 18491da177e4SLinus Torvalds 18501da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 18511da177e4SLinus Torvalds /** 18521da177e4SLinus Torvalds * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant 18531da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 18541da177e4SLinus Torvalds * 18551da177e4SLinus Torvalds * (linux scsi_host_template.eh_dev_reset_handler routine) 18561da177e4SLinus Torvalds * 18571da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1858cd2c6191SEric Moore **/ 18590d0c7974SMoore, Eric Dean int 18601da177e4SLinus Torvalds mptscsih_dev_reset(struct scsi_cmnd * SCpnt) 18611da177e4SLinus Torvalds { 18621da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1863466544d8SMoore, Eric Dean int retval; 1864958d4a32SEric Moore VirtDevice *vdevice; 1865958d4a32SEric Moore MPT_ADAPTER *ioc; 18661da177e4SLinus Torvalds 18671da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 18681da177e4SLinus Torvalds */ 1869e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 187029dd3609SEric Moore printk(KERN_ERR MYNAM ": target reset: " 187129dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 18721da177e4SLinus Torvalds return FAILED; 18731da177e4SLinus Torvalds } 18741da177e4SLinus Torvalds 1875958d4a32SEric Moore ioc = hd->ioc; 1876958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n", 1877958d4a32SEric Moore ioc->name, SCpnt); 1878466544d8SMoore, Eric Dean scsi_print_command(SCpnt); 18791da177e4SLinus Torvalds 1880958d4a32SEric Moore vdevice = SCpnt->device->hostdata; 1881958d4a32SEric Moore if (!vdevice || !vdevice->vtarget) { 18822f187862SKashyap, Desai retval = SUCCESS; 1883958d4a32SEric Moore goto out; 1884958d4a32SEric Moore } 1885958d4a32SEric Moore 1886cc78d30aSEric Moore /* Target reset to hidden raid component is not supported 1887cc78d30aSEric Moore */ 1888cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 1889cc78d30aSEric Moore retval = FAILED; 1890cc78d30aSEric Moore goto out; 1891cc78d30aSEric Moore } 1892cc78d30aSEric Moore 18931ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 18941ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 18951ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 18961ba9ab2eSKashyap, Desai vdevice->vtarget->id, 0, 0, 1897958d4a32SEric Moore mptscsih_get_tm_timeout(ioc)); 1898958d4a32SEric Moore 1899958d4a32SEric Moore out: 1900958d4a32SEric Moore printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n", 1901958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1902466544d8SMoore, Eric Dean 1903466544d8SMoore, Eric Dean if (retval == 0) 1904466544d8SMoore, Eric Dean return SUCCESS; 1905cd2c6191SEric Moore else 1906466544d8SMoore, Eric Dean return FAILED; 19071da177e4SLinus Torvalds } 19081da177e4SLinus Torvalds 1909cd2c6191SEric Moore 19101da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 19111da177e4SLinus Torvalds /** 19121da177e4SLinus Torvalds * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant 19131da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 19141da177e4SLinus Torvalds * 19151da177e4SLinus Torvalds * (linux scsi_host_template.eh_bus_reset_handler routine) 19161da177e4SLinus Torvalds * 19171da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 1918cd2c6191SEric Moore **/ 19190d0c7974SMoore, Eric Dean int 19201da177e4SLinus Torvalds mptscsih_bus_reset(struct scsi_cmnd * SCpnt) 19211da177e4SLinus Torvalds { 19221da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 1923466544d8SMoore, Eric Dean int retval; 1924a69de507SEric Moore VirtDevice *vdevice; 1925958d4a32SEric Moore MPT_ADAPTER *ioc; 19261da177e4SLinus Torvalds 19271da177e4SLinus Torvalds /* If we can't locate our host adapter structure, return FAILED status. 19281da177e4SLinus Torvalds */ 1929e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 193029dd3609SEric Moore printk(KERN_ERR MYNAM ": bus reset: " 193129dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 19321da177e4SLinus Torvalds return FAILED; 19331da177e4SLinus Torvalds } 19341da177e4SLinus Torvalds 1935958d4a32SEric Moore ioc = hd->ioc; 1936958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n", 1937958d4a32SEric Moore ioc->name, SCpnt); 1938466544d8SMoore, Eric Dean scsi_print_command(SCpnt); 19391da177e4SLinus Torvalds 19402f187862SKashyap, Desai if (ioc->timeouts < -1) 19412f187862SKashyap, Desai ioc->timeouts++; 19421da177e4SLinus Torvalds 1943a69de507SEric Moore vdevice = SCpnt->device->hostdata; 19442f187862SKashyap, Desai if (!vdevice || !vdevice->vtarget) 19452f187862SKashyap, Desai return SUCCESS; 19461ba9ab2eSKashyap, Desai retval = mptscsih_IssueTaskMgmt(hd, 19471ba9ab2eSKashyap, Desai MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, 19481ba9ab2eSKashyap, Desai vdevice->vtarget->channel, 0, 0, 0, 19491ba9ab2eSKashyap, Desai mptscsih_get_tm_timeout(ioc)); 19501da177e4SLinus Torvalds 1951958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", 1952958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 1953466544d8SMoore, Eric Dean 1954466544d8SMoore, Eric Dean if (retval == 0) 1955466544d8SMoore, Eric Dean return SUCCESS; 1956cd2c6191SEric Moore else 1957466544d8SMoore, Eric Dean return FAILED; 19581da177e4SLinus Torvalds } 19591da177e4SLinus Torvalds 19601da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 19611da177e4SLinus Torvalds /** 1962d9489fb6SRandy Dunlap * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant) 19631da177e4SLinus Torvalds * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to 19641da177e4SLinus Torvalds * 19651da177e4SLinus Torvalds * (linux scsi_host_template.eh_host_reset_handler routine) 19661da177e4SLinus Torvalds * 19671da177e4SLinus Torvalds * Returns SUCCESS or FAILED. 19681da177e4SLinus Torvalds */ 19690d0c7974SMoore, Eric Dean int 19701da177e4SLinus Torvalds mptscsih_host_reset(struct scsi_cmnd *SCpnt) 19711da177e4SLinus Torvalds { 19721da177e4SLinus Torvalds MPT_SCSI_HOST * hd; 19732f187862SKashyap, Desai int status = SUCCESS; 1974958d4a32SEric Moore MPT_ADAPTER *ioc; 19752f187862SKashyap, Desai int retval; 19761da177e4SLinus Torvalds 19771da177e4SLinus Torvalds /* If we can't locate the host to reset, then we failed. */ 1978e7eae9f6SEric Moore if ((hd = shost_priv(SCpnt->device->host)) == NULL){ 197929dd3609SEric Moore printk(KERN_ERR MYNAM ": host reset: " 198029dd3609SEric Moore "Can't locate host! (sc=%p)\n", SCpnt); 19811da177e4SLinus Torvalds return FAILED; 19821da177e4SLinus Torvalds } 19831da177e4SLinus Torvalds 1984a6da74cbSJames Bottomley /* make sure we have no outstanding commands at this stage */ 1985a6da74cbSJames Bottomley mptscsih_flush_running_cmds(hd); 1986a6da74cbSJames Bottomley 1987958d4a32SEric Moore ioc = hd->ioc; 1988958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n", 1989958d4a32SEric Moore ioc->name, SCpnt); 19901da177e4SLinus Torvalds 19911da177e4SLinus Torvalds /* If our attempts to reset the host failed, then return a failed 19921da177e4SLinus Torvalds * status. The host will be taken off line by the SCSI mid-layer. 19931da177e4SLinus Torvalds */ 19942f187862SKashyap, Desai retval = mpt_HardResetHandler(ioc, CAN_SLEEP); 19952f187862SKashyap, Desai if (retval < 0) 19962f187862SKashyap, Desai status = FAILED; 19972f187862SKashyap, Desai else 19982f187862SKashyap, Desai status = SUCCESS; 19991da177e4SLinus Torvalds 2000958d4a32SEric Moore printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n", 2001958d4a32SEric Moore ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); 20021da177e4SLinus Torvalds 20032f187862SKashyap, Desai return status; 20041da177e4SLinus Torvalds } 20051da177e4SLinus Torvalds 20061da177e4SLinus Torvalds static int 20071ba9ab2eSKashyap, Desai mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type, 20081ba9ab2eSKashyap, Desai SCSITaskMgmtReply_t *pScsiTmReply) 20091da177e4SLinus Torvalds { 20101ba9ab2eSKashyap, Desai u16 iocstatus; 20111ba9ab2eSKashyap, Desai u32 termination_count; 20121ba9ab2eSKashyap, Desai int retval; 20131da177e4SLinus Torvalds 20141ba9ab2eSKashyap, Desai if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { 20151ba9ab2eSKashyap, Desai retval = FAILED; 20161ba9ab2eSKashyap, Desai goto out; 20171da177e4SLinus Torvalds } 20181da177e4SLinus Torvalds 20191ba9ab2eSKashyap, Desai DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply); 20201da177e4SLinus Torvalds 20211ba9ab2eSKashyap, Desai iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; 20221ba9ab2eSKashyap, Desai termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); 20231ba9ab2eSKashyap, Desai 20241ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 20251ba9ab2eSKashyap, Desai "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n" 20261ba9ab2eSKashyap, Desai "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n" 20271ba9ab2eSKashyap, Desai "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus, 20281ba9ab2eSKashyap, Desai pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus), 20291ba9ab2eSKashyap, Desai le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode, 20301ba9ab2eSKashyap, Desai termination_count)); 20311ba9ab2eSKashyap, Desai 20321ba9ab2eSKashyap, Desai if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && 20331ba9ab2eSKashyap, Desai pScsiTmReply->ResponseCode) 20341ba9ab2eSKashyap, Desai mptscsih_taskmgmt_response_code(ioc, 20351ba9ab2eSKashyap, Desai pScsiTmReply->ResponseCode); 20361ba9ab2eSKashyap, Desai 20371ba9ab2eSKashyap, Desai if (iocstatus == MPI_IOCSTATUS_SUCCESS) { 20381ba9ab2eSKashyap, Desai retval = 0; 20391ba9ab2eSKashyap, Desai goto out; 20401da177e4SLinus Torvalds } 20411da177e4SLinus Torvalds 20421ba9ab2eSKashyap, Desai retval = FAILED; 20431ba9ab2eSKashyap, Desai if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { 20441ba9ab2eSKashyap, Desai if (termination_count == 1) 20451ba9ab2eSKashyap, Desai retval = 0; 20461ba9ab2eSKashyap, Desai goto out; 20471ba9ab2eSKashyap, Desai } 20481ba9ab2eSKashyap, Desai 20491ba9ab2eSKashyap, Desai if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || 20501ba9ab2eSKashyap, Desai iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) 20511ba9ab2eSKashyap, Desai retval = 0; 20521ba9ab2eSKashyap, Desai 20531ba9ab2eSKashyap, Desai out: 20541ba9ab2eSKashyap, Desai return retval; 20551da177e4SLinus Torvalds } 20561da177e4SLinus Torvalds 20571da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 2058e7deff33SKashyap, Desai void 20599f63bb73SMoore, Eric mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) 20609f63bb73SMoore, Eric { 20619f63bb73SMoore, Eric char *desc; 20629f63bb73SMoore, Eric 20639f63bb73SMoore, Eric switch (response_code) { 20649f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_COMPLETE: 20659f63bb73SMoore, Eric desc = "The task completed."; 20669f63bb73SMoore, Eric break; 20679f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_INVALID_FRAME: 20689f63bb73SMoore, Eric desc = "The IOC received an invalid frame status."; 20699f63bb73SMoore, Eric break; 20709f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: 20719f63bb73SMoore, Eric desc = "The task type is not supported."; 20729f63bb73SMoore, Eric break; 20739f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_FAILED: 20749f63bb73SMoore, Eric desc = "The requested task failed."; 20759f63bb73SMoore, Eric break; 20769f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED: 20779f63bb73SMoore, Eric desc = "The task completed successfully."; 20789f63bb73SMoore, Eric break; 20799f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN: 20809f63bb73SMoore, Eric desc = "The LUN request is invalid."; 20819f63bb73SMoore, Eric break; 20829f63bb73SMoore, Eric case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: 20839f63bb73SMoore, Eric desc = "The task is in the IOC queue and has not been sent to target."; 20849f63bb73SMoore, Eric break; 20859f63bb73SMoore, Eric default: 20869f63bb73SMoore, Eric desc = "unknown"; 20879f63bb73SMoore, Eric break; 20889f63bb73SMoore, Eric } 20899f63bb73SMoore, Eric printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n", 20909f63bb73SMoore, Eric ioc->name, response_code, desc); 20919f63bb73SMoore, Eric } 2092e7deff33SKashyap, Desai EXPORT_SYMBOL(mptscsih_taskmgmt_response_code); 20939f63bb73SMoore, Eric 20949f63bb73SMoore, Eric /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 20951da177e4SLinus Torvalds /** 20961da177e4SLinus Torvalds * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver 20971da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 20981da177e4SLinus Torvalds * @mf: Pointer to SCSI task mgmt request frame 20991da177e4SLinus Torvalds * @mr: Pointer to SCSI task mgmt reply frame 21001da177e4SLinus Torvalds * 21011da177e4SLinus Torvalds * This routine is called from mptbase.c::mpt_interrupt() at the completion 21021da177e4SLinus Torvalds * of any SCSI task management request. 21031da177e4SLinus Torvalds * This routine is registered with the MPT (base) driver at driver 21041da177e4SLinus Torvalds * load/init time via the mpt_register() API call. 21051da177e4SLinus Torvalds * 21061da177e4SLinus Torvalds * Returns 1 indicating alloc'd request frame ptr should be freed. 2107cd2c6191SEric Moore **/ 21080d0c7974SMoore, Eric Dean int 21091ba9ab2eSKashyap, Desai mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, 21101ba9ab2eSKashyap, Desai MPT_FRAME_HDR *mr) 21111da177e4SLinus Torvalds { 21121ba9ab2eSKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 21131ba9ab2eSKashyap, Desai "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr)); 21141da177e4SLinus Torvalds 21151ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; 21161da177e4SLinus Torvalds 21171ba9ab2eSKashyap, Desai if (!mr) 2118cd2c6191SEric Moore goto out; 2119cd2c6191SEric Moore 21201ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID; 21211ba9ab2eSKashyap, Desai memcpy(ioc->taskmgmt_cmds.reply, mr, 21221ba9ab2eSKashyap, Desai min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength)); 2123cd2c6191SEric Moore out: 21241ba9ab2eSKashyap, Desai if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { 21251ba9ab2eSKashyap, Desai mpt_clear_taskmgmt_in_progress_flag(ioc); 21261ba9ab2eSKashyap, Desai ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING; 21271ba9ab2eSKashyap, Desai complete(&ioc->taskmgmt_cmds.done); 21281da177e4SLinus Torvalds return 1; 21291da177e4SLinus Torvalds } 21301ba9ab2eSKashyap, Desai return 0; 21311ba9ab2eSKashyap, Desai } 21321da177e4SLinus Torvalds 21331da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 21341da177e4SLinus Torvalds /* 21351da177e4SLinus Torvalds * This is anyones guess quite frankly. 21361da177e4SLinus Torvalds */ 21370d0c7974SMoore, Eric Dean int 21381da177e4SLinus Torvalds mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, 21391da177e4SLinus Torvalds sector_t capacity, int geom[]) 21401da177e4SLinus Torvalds { 21411da177e4SLinus Torvalds int heads; 21421da177e4SLinus Torvalds int sectors; 21431da177e4SLinus Torvalds sector_t cylinders; 21441da177e4SLinus Torvalds ulong dummy; 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds heads = 64; 21471da177e4SLinus Torvalds sectors = 32; 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds dummy = heads * sectors; 21501da177e4SLinus Torvalds cylinders = capacity; 21511da177e4SLinus Torvalds sector_div(cylinders,dummy); 21521da177e4SLinus Torvalds 21531da177e4SLinus Torvalds /* 21541da177e4SLinus Torvalds * Handle extended translation size for logical drives 21551da177e4SLinus Torvalds * > 1Gb 21561da177e4SLinus Torvalds */ 21571da177e4SLinus Torvalds if ((ulong)capacity >= 0x200000) { 21581da177e4SLinus Torvalds heads = 255; 21591da177e4SLinus Torvalds sectors = 63; 21601da177e4SLinus Torvalds dummy = heads * sectors; 21611da177e4SLinus Torvalds cylinders = capacity; 21621da177e4SLinus Torvalds sector_div(cylinders,dummy); 21631da177e4SLinus Torvalds } 21641da177e4SLinus Torvalds 21651da177e4SLinus Torvalds /* return result */ 21661da177e4SLinus Torvalds geom[0] = heads; 21671da177e4SLinus Torvalds geom[1] = sectors; 21681da177e4SLinus Torvalds geom[2] = cylinders; 21691da177e4SLinus Torvalds 21701da177e4SLinus Torvalds return 0; 21711da177e4SLinus Torvalds } 21721da177e4SLinus Torvalds 2173f44e5461SMoore, Eric /* Search IOC page 3 to determine if this is hidden physical disk 2174f44e5461SMoore, Eric * 2175f44e5461SMoore, Eric */ 2176f44e5461SMoore, Eric int 2177793955f5SEric Moore mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id) 2178f44e5461SMoore, Eric { 2179b506ade9SEric Moore struct inactive_raid_component_info *component_info; 2180a7938b0bSKashyap, Desai int i, j; 2181a7938b0bSKashyap, Desai RaidPhysDiskPage1_t *phys_disk; 2182793955f5SEric Moore int rc = 0; 2183a7938b0bSKashyap, Desai int num_paths; 2184f44e5461SMoore, Eric 2185793955f5SEric Moore if (!ioc->raid_data.pIocPg3) 2186793955f5SEric Moore goto out; 2187f44e5461SMoore, Eric for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2188793955f5SEric Moore if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && 2189793955f5SEric Moore (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { 2190793955f5SEric Moore rc = 1; 2191793955f5SEric Moore goto out; 2192f44e5461SMoore, Eric } 2193793955f5SEric Moore } 2194793955f5SEric Moore 2195a7938b0bSKashyap, Desai if (ioc->bus_type != SAS) 2196a7938b0bSKashyap, Desai goto out; 2197a7938b0bSKashyap, Desai 2198a7938b0bSKashyap, Desai /* 2199a7938b0bSKashyap, Desai * Check if dual path 2200a7938b0bSKashyap, Desai */ 2201a7938b0bSKashyap, Desai for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2202a7938b0bSKashyap, Desai num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2203a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2204a7938b0bSKashyap, Desai if (num_paths < 2) 2205a7938b0bSKashyap, Desai continue; 2206a7938b0bSKashyap, Desai phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2207a7938b0bSKashyap, Desai (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2208a7938b0bSKashyap, Desai if (!phys_disk) 2209a7938b0bSKashyap, Desai continue; 2210a7938b0bSKashyap, Desai if ((mpt_raid_phys_disk_pg1(ioc, 2211a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2212a7938b0bSKashyap, Desai phys_disk))) { 2213a7938b0bSKashyap, Desai kfree(phys_disk); 2214a7938b0bSKashyap, Desai continue; 2215a7938b0bSKashyap, Desai } 2216a7938b0bSKashyap, Desai for (j = 0; j < num_paths; j++) { 2217a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2218a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2219a7938b0bSKashyap, Desai continue; 2220a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2221a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2222a7938b0bSKashyap, Desai continue; 2223a7938b0bSKashyap, Desai if ((id == phys_disk->Path[j].PhysDiskID) && 2224a7938b0bSKashyap, Desai (channel == phys_disk->Path[j].PhysDiskBus)) { 2225a7938b0bSKashyap, Desai rc = 1; 2226a7938b0bSKashyap, Desai kfree(phys_disk); 2227a7938b0bSKashyap, Desai goto out; 2228a7938b0bSKashyap, Desai } 2229a7938b0bSKashyap, Desai } 2230a7938b0bSKashyap, Desai kfree(phys_disk); 2231a7938b0bSKashyap, Desai } 2232a7938b0bSKashyap, Desai 2233a7938b0bSKashyap, Desai 2234b506ade9SEric Moore /* 2235b506ade9SEric Moore * Check inactive list for matching phys disks 2236b506ade9SEric Moore */ 2237b506ade9SEric Moore if (list_empty(&ioc->raid_data.inactive_list)) 2238b506ade9SEric Moore goto out; 2239b506ade9SEric Moore 2240ed5f606fSMatthias Kaehlcke mutex_lock(&ioc->raid_data.inactive_list_mutex); 2241b506ade9SEric Moore list_for_each_entry(component_info, &ioc->raid_data.inactive_list, 2242b506ade9SEric Moore list) { 2243b506ade9SEric Moore if ((component_info->d.PhysDiskID == id) && 2244b506ade9SEric Moore (component_info->d.PhysDiskBus == channel)) 2245b506ade9SEric Moore rc = 1; 2246b506ade9SEric Moore } 2247ed5f606fSMatthias Kaehlcke mutex_unlock(&ioc->raid_data.inactive_list_mutex); 2248b506ade9SEric Moore 2249793955f5SEric Moore out: 2250793955f5SEric Moore return rc; 2251f44e5461SMoore, Eric } 2252f44e5461SMoore, Eric EXPORT_SYMBOL(mptscsih_is_phys_disk); 2253f44e5461SMoore, Eric 2254793955f5SEric Moore u8 2255793955f5SEric Moore mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id) 2256c92f222eSJames Bottomley { 2257b506ade9SEric Moore struct inactive_raid_component_info *component_info; 2258a7938b0bSKashyap, Desai int i, j; 2259a7938b0bSKashyap, Desai RaidPhysDiskPage1_t *phys_disk; 2260793955f5SEric Moore int rc = -ENXIO; 2261a7938b0bSKashyap, Desai int num_paths; 2262c92f222eSJames Bottomley 2263793955f5SEric Moore if (!ioc->raid_data.pIocPg3) 2264793955f5SEric Moore goto out; 2265793955f5SEric Moore for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2266793955f5SEric Moore if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) && 2267793955f5SEric Moore (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) { 2268793955f5SEric Moore rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum; 2269793955f5SEric Moore goto out; 2270793955f5SEric Moore } 2271c92f222eSJames Bottomley } 2272c92f222eSJames Bottomley 2273a7938b0bSKashyap, Desai if (ioc->bus_type != SAS) 2274a7938b0bSKashyap, Desai goto out; 2275a7938b0bSKashyap, Desai 2276a7938b0bSKashyap, Desai /* 2277a7938b0bSKashyap, Desai * Check if dual path 2278a7938b0bSKashyap, Desai */ 2279a7938b0bSKashyap, Desai for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { 2280a7938b0bSKashyap, Desai num_paths = mpt_raid_phys_disk_get_num_paths(ioc, 2281a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum); 2282a7938b0bSKashyap, Desai if (num_paths < 2) 2283a7938b0bSKashyap, Desai continue; 2284a7938b0bSKashyap, Desai phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) + 2285a7938b0bSKashyap, Desai (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL); 2286a7938b0bSKashyap, Desai if (!phys_disk) 2287a7938b0bSKashyap, Desai continue; 2288a7938b0bSKashyap, Desai if ((mpt_raid_phys_disk_pg1(ioc, 2289a7938b0bSKashyap, Desai ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum, 2290a7938b0bSKashyap, Desai phys_disk))) { 2291a7938b0bSKashyap, Desai kfree(phys_disk); 2292a7938b0bSKashyap, Desai continue; 2293a7938b0bSKashyap, Desai } 2294a7938b0bSKashyap, Desai for (j = 0; j < num_paths; j++) { 2295a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2296a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_INVALID)) 2297a7938b0bSKashyap, Desai continue; 2298a7938b0bSKashyap, Desai if ((phys_disk->Path[j].Flags & 2299a7938b0bSKashyap, Desai MPI_RAID_PHYSDISK1_FLAG_BROKEN)) 2300a7938b0bSKashyap, Desai continue; 2301a7938b0bSKashyap, Desai if ((id == phys_disk->Path[j].PhysDiskID) && 2302a7938b0bSKashyap, Desai (channel == phys_disk->Path[j].PhysDiskBus)) { 2303a7938b0bSKashyap, Desai rc = phys_disk->PhysDiskNum; 2304a7938b0bSKashyap, Desai kfree(phys_disk); 2305a7938b0bSKashyap, Desai goto out; 2306a7938b0bSKashyap, Desai } 2307a7938b0bSKashyap, Desai } 2308a7938b0bSKashyap, Desai kfree(phys_disk); 2309a7938b0bSKashyap, Desai } 2310a7938b0bSKashyap, Desai 2311b506ade9SEric Moore /* 2312b506ade9SEric Moore * Check inactive list for matching phys disks 2313b506ade9SEric Moore */ 2314b506ade9SEric Moore if (list_empty(&ioc->raid_data.inactive_list)) 2315b506ade9SEric Moore goto out; 2316b506ade9SEric Moore 2317ed5f606fSMatthias Kaehlcke mutex_lock(&ioc->raid_data.inactive_list_mutex); 2318b506ade9SEric Moore list_for_each_entry(component_info, &ioc->raid_data.inactive_list, 2319b506ade9SEric Moore list) { 2320b506ade9SEric Moore if ((component_info->d.PhysDiskID == id) && 2321b506ade9SEric Moore (component_info->d.PhysDiskBus == channel)) 2322b506ade9SEric Moore rc = component_info->d.PhysDiskNum; 2323b506ade9SEric Moore } 2324ed5f606fSMatthias Kaehlcke mutex_unlock(&ioc->raid_data.inactive_list_mutex); 2325b506ade9SEric Moore 2326793955f5SEric Moore out: 2327793955f5SEric Moore return rc; 2328c92f222eSJames Bottomley } 2329c92f222eSJames Bottomley EXPORT_SYMBOL(mptscsih_raid_id_to_num); 2330c92f222eSJames Bottomley 2331c7c82987SMoore, Eric Dean /* 2332c7c82987SMoore, Eric Dean * OS entry point to allow for host driver to free allocated memory 2333c7c82987SMoore, Eric Dean * Called if no device present or device being unloaded 2334c7c82987SMoore, Eric Dean */ 2335c7c82987SMoore, Eric Dean void 2336c7c82987SMoore, Eric Dean mptscsih_slave_destroy(struct scsi_device *sdev) 2337c7c82987SMoore, Eric Dean { 2338c7c82987SMoore, Eric Dean struct Scsi_Host *host = sdev->host; 2339e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 2340c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2341c7c82987SMoore, Eric Dean VirtDevice *vdevice; 2342c7c82987SMoore, Eric Dean struct scsi_target *starget; 23431da177e4SLinus Torvalds 2344c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2345c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 2346c7c82987SMoore, Eric Dean vdevice = sdev->hostdata; 23471da177e4SLinus Torvalds 2348c7c82987SMoore, Eric Dean mptscsih_search_running_cmds(hd, vdevice); 2349c7c82987SMoore, Eric Dean vtarget->num_luns--; 2350c7c82987SMoore, Eric Dean mptscsih_synchronize_cache(hd, vdevice); 2351c7c82987SMoore, Eric Dean kfree(vdevice); 2352c7c82987SMoore, Eric Dean sdev->hostdata = NULL; 23531da177e4SLinus Torvalds } 23541da177e4SLinus Torvalds 23556e3815baSMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 23566e3815baSMoore, Eric Dean /* 23576e3815baSMoore, Eric Dean * mptscsih_change_queue_depth - This function will set a devices queue depth 23586e3815baSMoore, Eric Dean * @sdev: per scsi_device pointer 23596e3815baSMoore, Eric Dean * @qdepth: requested queue depth 2360e881a172SMike Christie * @reason: calling context 23616e3815baSMoore, Eric Dean * 23626e3815baSMoore, Eric Dean * Adding support for new 'change_queue_depth' api. 23636e3815baSMoore, Eric Dean */ 23646e3815baSMoore, Eric Dean int 2365e881a172SMike Christie mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) 23661da177e4SLinus Torvalds { 2367e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(sdev->host); 2368c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2369c7c82987SMoore, Eric Dean struct scsi_target *starget; 23701da177e4SLinus Torvalds int max_depth; 23711da177e4SLinus Torvalds int tagged; 2372e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 23731da177e4SLinus Torvalds 2374c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2375c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 23766e3815baSMoore, Eric Dean 2377e881a172SMike Christie if (reason != SCSI_QDEPTH_DEFAULT) 2378e881a172SMike Christie return -EOPNOTSUPP; 2379e881a172SMike Christie 2380e80b002bSEric Moore if (ioc->bus_type == SPI) { 2381c7c82987SMoore, Eric Dean if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) 23821da177e4SLinus Torvalds max_depth = 1; 2383c92f222eSJames Bottomley else if (sdev->type == TYPE_DISK && 2384c92f222eSJames Bottomley vtarget->minSyncFactor <= MPT_ULTRA160) 23851da177e4SLinus Torvalds max_depth = MPT_SCSI_CMD_PER_DEV_HIGH; 23861da177e4SLinus Torvalds else 23871da177e4SLinus Torvalds max_depth = MPT_SCSI_CMD_PER_DEV_LOW; 23881da177e4SLinus Torvalds } else 238979a3ec1aSKashyap, Desai max_depth = ioc->sh->can_queue; 239079a3ec1aSKashyap, Desai 239179a3ec1aSKashyap, Desai if (!sdev->tagged_supported) 239279a3ec1aSKashyap, Desai max_depth = 1; 23931da177e4SLinus Torvalds 23941da177e4SLinus Torvalds if (qdepth > max_depth) 23951da177e4SLinus Torvalds qdepth = max_depth; 23961da177e4SLinus Torvalds if (qdepth == 1) 23971da177e4SLinus Torvalds tagged = 0; 23981da177e4SLinus Torvalds else 23991da177e4SLinus Torvalds tagged = MSG_SIMPLE_TAG; 24001da177e4SLinus Torvalds 24016e3815baSMoore, Eric Dean scsi_adjust_queue_depth(sdev, tagged, qdepth); 24026e3815baSMoore, Eric Dean return sdev->queue_depth; 24031da177e4SLinus Torvalds } 24041da177e4SLinus Torvalds 24051da177e4SLinus Torvalds /* 24061da177e4SLinus Torvalds * OS entry point to adjust the queue_depths on a per-device basis. 24071da177e4SLinus Torvalds * Called once per device the bus scan. Use it to force the queue_depth 24081da177e4SLinus Torvalds * member to 1 if a device does not support Q tags. 24091da177e4SLinus Torvalds * Return non-zero if fails. 24101da177e4SLinus Torvalds */ 24110d0c7974SMoore, Eric Dean int 2412c7c82987SMoore, Eric Dean mptscsih_slave_configure(struct scsi_device *sdev) 24131da177e4SLinus Torvalds { 2414c7c82987SMoore, Eric Dean struct Scsi_Host *sh = sdev->host; 2415c7c82987SMoore, Eric Dean VirtTarget *vtarget; 2416c7c82987SMoore, Eric Dean VirtDevice *vdevice; 2417c7c82987SMoore, Eric Dean struct scsi_target *starget; 2418e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(sh); 2419e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 24201da177e4SLinus Torvalds 2421c7c82987SMoore, Eric Dean starget = scsi_target(sdev); 2422c7c82987SMoore, Eric Dean vtarget = starget->hostdata; 2423c7c82987SMoore, Eric Dean vdevice = sdev->hostdata; 24241da177e4SLinus Torvalds 2425e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 2426793955f5SEric Moore "device @ %p, channel=%d, id=%d, lun=%d\n", 2427e80b002bSEric Moore ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); 2428e80b002bSEric Moore if (ioc->bus_type == SPI) 2429e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 24301da177e4SLinus Torvalds "sdtr %d wdtr %d ppr %d inq length=%d\n", 2431e80b002bSEric Moore ioc->name, sdev->sdtr, sdev->wdtr, 2432c7c82987SMoore, Eric Dean sdev->ppr, sdev->inquiry_len)); 24331da177e4SLinus Torvalds 2434c7c82987SMoore, Eric Dean vdevice->configured_lun = 1; 24351da177e4SLinus Torvalds 2436e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 24371da177e4SLinus Torvalds "Queue depth=%d, tflags=%x\n", 2438e80b002bSEric Moore ioc->name, sdev->queue_depth, vtarget->tflags)); 24391da177e4SLinus Torvalds 2440e80b002bSEric Moore if (ioc->bus_type == SPI) 2441e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 24421da177e4SLinus Torvalds "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", 2443e80b002bSEric Moore ioc->name, vtarget->negoFlags, vtarget->maxOffset, 2444c7c82987SMoore, Eric Dean vtarget->minSyncFactor)); 24451da177e4SLinus Torvalds 2446e881a172SMike Christie mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH, 2447e881a172SMike Christie SCSI_QDEPTH_DEFAULT); 2448e80b002bSEric Moore dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 24491da177e4SLinus Torvalds "tagged %d, simple %d, ordered %d\n", 2450e80b002bSEric Moore ioc->name,sdev->tagged_supported, sdev->simple_tags, 2451c7c82987SMoore, Eric Dean sdev->ordered_tags)); 24521da177e4SLinus Torvalds 24531da177e4SLinus Torvalds return 0; 24541da177e4SLinus Torvalds } 24551da177e4SLinus Torvalds 24561da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 24571da177e4SLinus Torvalds /* 24581da177e4SLinus Torvalds * Private routines... 24591da177e4SLinus Torvalds */ 24601da177e4SLinus Torvalds 24611da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 24621da177e4SLinus Torvalds /* Utility function to copy sense data from the scsi_cmnd buffer 24631da177e4SLinus Torvalds * to the FC and SCSI target structures. 24641da177e4SLinus Torvalds * 24651da177e4SLinus Torvalds */ 24661da177e4SLinus Torvalds static void 24670d0c7974SMoore, Eric Dean mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) 24681da177e4SLinus Torvalds { 2469a69de507SEric Moore VirtDevice *vdevice; 24701da177e4SLinus Torvalds SCSIIORequest_t *pReq; 24711da177e4SLinus Torvalds u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); 2472e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 24731da177e4SLinus Torvalds 24741da177e4SLinus Torvalds /* Get target structure 24751da177e4SLinus Torvalds */ 24761da177e4SLinus Torvalds pReq = (SCSIIORequest_t *) mf; 2477a69de507SEric Moore vdevice = sc->device->hostdata; 24781da177e4SLinus Torvalds 24791da177e4SLinus Torvalds if (sense_count) { 24801da177e4SLinus Torvalds u8 *sense_data; 24811da177e4SLinus Torvalds int req_index; 24821da177e4SLinus Torvalds 24831da177e4SLinus Torvalds /* Copy the sense received into the scsi command block. */ 24841da177e4SLinus Torvalds req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 2485e80b002bSEric Moore sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); 24861da177e4SLinus Torvalds memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc)); 24871da177e4SLinus Torvalds 24881da177e4SLinus Torvalds /* Log SMART data (asc = 0x5D, non-IM case only) if required. 24891da177e4SLinus Torvalds */ 2490e80b002bSEric Moore if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { 2491a69de507SEric Moore if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) { 24921da177e4SLinus Torvalds int idx; 24931da177e4SLinus Torvalds 24945b5ef4f6SMoore, Eric idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; 24951da177e4SLinus Torvalds ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; 24961da177e4SLinus Torvalds ioc->events[idx].eventContext = ioc->eventContext; 24971da177e4SLinus Torvalds 24983d9780b9SDave Jones ioc->events[idx].data[0] = (pReq->LUN[1] << 24) | 24993d9780b9SDave Jones (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) | 25003d9780b9SDave Jones (sc->device->channel << 8) | sc->device->id; 25011da177e4SLinus Torvalds 25023d9780b9SDave Jones ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12]; 25031da177e4SLinus Torvalds 25041da177e4SLinus Torvalds ioc->eventContext++; 2505e80b002bSEric Moore if (ioc->pcidev->vendor == 2506786899b0SEric Moore PCI_VENDOR_ID_IBM) { 2507e80b002bSEric Moore mptscsih_issue_sep_command(ioc, 2508a69de507SEric Moore vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); 2509a69de507SEric Moore vdevice->vtarget->tflags |= 2510786899b0SEric Moore MPT_TARGET_FLAGS_LED_ON; 2511786899b0SEric Moore } 25121da177e4SLinus Torvalds } 25131da177e4SLinus Torvalds } 25141da177e4SLinus Torvalds } else { 2515e80b002bSEric Moore dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", 2516e80b002bSEric Moore ioc->name)); 25171da177e4SLinus Torvalds } 25181da177e4SLinus Torvalds } 25191da177e4SLinus Torvalds 2520db7051b2SKashyap, Desai /** 2521db7051b2SKashyap, Desai * mptscsih_get_scsi_lookup - retrieves scmd entry 2522db7051b2SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 2523db7051b2SKashyap, Desai * @i: index into the array 2524db7051b2SKashyap, Desai * 2525db7051b2SKashyap, Desai * Returns the scsi_cmd pointer 2526db7051b2SKashyap, Desai */ 2527db7051b2SKashyap, Desai struct scsi_cmnd * 2528db7051b2SKashyap, Desai mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) 2529db7051b2SKashyap, Desai { 2530db7051b2SKashyap, Desai unsigned long flags; 2531db7051b2SKashyap, Desai struct scsi_cmnd *scmd; 2532db7051b2SKashyap, Desai 2533db7051b2SKashyap, Desai spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2534db7051b2SKashyap, Desai scmd = ioc->ScsiLookup[i]; 2535db7051b2SKashyap, Desai spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2536db7051b2SKashyap, Desai 2537db7051b2SKashyap, Desai return scmd; 2538db7051b2SKashyap, Desai } 2539db7051b2SKashyap, Desai EXPORT_SYMBOL(mptscsih_get_scsi_lookup); 2540e8206381SEric Moore 2541e8206381SEric Moore /** 2542fc847ab4SJames Bottomley * mptscsih_getclear_scsi_lookup - retrieves and clears scmd entry from ScsiLookup[] array list 25432f187862SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 25442f187862SKashyap, Desai * @i: index into the array 25452f187862SKashyap, Desai * 25467105a387SRandy Dunlap * Returns the scsi_cmd pointer 25472f187862SKashyap, Desai * 2548e8206381SEric Moore **/ 2549e8206381SEric Moore static struct scsi_cmnd * 2550e8206381SEric Moore mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) 2551e8206381SEric Moore { 2552e8206381SEric Moore unsigned long flags; 2553e8206381SEric Moore struct scsi_cmnd *scmd; 2554e8206381SEric Moore 2555e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2556e8206381SEric Moore scmd = ioc->ScsiLookup[i]; 2557e8206381SEric Moore ioc->ScsiLookup[i] = NULL; 2558e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2559e8206381SEric Moore 2560e8206381SEric Moore return scmd; 2561e8206381SEric Moore } 2562e8206381SEric Moore 2563e8206381SEric Moore /** 2564e8206381SEric Moore * mptscsih_set_scsi_lookup 2565e8206381SEric Moore * 2566e8206381SEric Moore * writes a scmd entry into the ScsiLookup[] array list 2567e8206381SEric Moore * 2568e8206381SEric Moore * @ioc: Pointer to MPT_ADAPTER structure 2569e8206381SEric Moore * @i: index into the array 2570e8206381SEric Moore * @scmd: scsi_cmnd pointer 2571e8206381SEric Moore * 2572e8206381SEric Moore **/ 2573e8206381SEric Moore static void 2574e8206381SEric Moore mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd) 2575e8206381SEric Moore { 2576e8206381SEric Moore unsigned long flags; 2577e8206381SEric Moore 2578e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2579e8206381SEric Moore ioc->ScsiLookup[i] = scmd; 2580e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2581e8206381SEric Moore } 2582e8206381SEric Moore 2583e8206381SEric Moore /** 258423f9b75eSRandy Dunlap * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list 2585e8206381SEric Moore * @ioc: Pointer to MPT_ADAPTER structure 258623f9b75eSRandy Dunlap * @sc: scsi_cmnd pointer 258723f9b75eSRandy Dunlap */ 2588e8206381SEric Moore static int 2589e8206381SEric Moore SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc) 2590e8206381SEric Moore { 2591e8206381SEric Moore unsigned long flags; 2592e8206381SEric Moore int i, index=-1; 2593e8206381SEric Moore 2594e8206381SEric Moore spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); 2595e8206381SEric Moore for (i = 0; i < ioc->req_depth; i++) { 2596e8206381SEric Moore if (ioc->ScsiLookup[i] == sc) { 2597e8206381SEric Moore index = i; 2598e8206381SEric Moore goto out; 25991da177e4SLinus Torvalds } 26001da177e4SLinus Torvalds } 26011da177e4SLinus Torvalds 2602e8206381SEric Moore out: 2603e8206381SEric Moore spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); 2604e8206381SEric Moore return index; 26051da177e4SLinus Torvalds } 26061da177e4SLinus Torvalds 26071da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26080d0c7974SMoore, Eric Dean int 26091da177e4SLinus Torvalds mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) 26101da177e4SLinus Torvalds { 26111da177e4SLinus Torvalds MPT_SCSI_HOST *hd; 26121da177e4SLinus Torvalds 2613e7eae9f6SEric Moore if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) 26141da177e4SLinus Torvalds return 0; 261537c60f37SKashyap, Desai 2616e7eae9f6SEric Moore hd = shost_priv(ioc->sh); 261737c60f37SKashyap, Desai switch (reset_phase) { 261837c60f37SKashyap, Desai case MPT_IOC_SETUP_RESET: 261937c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 262037c60f37SKashyap, Desai "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); 262137c60f37SKashyap, Desai break; 262237c60f37SKashyap, Desai case MPT_IOC_PRE_RESET: 262337c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 262437c60f37SKashyap, Desai "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); 262537c60f37SKashyap, Desai mptscsih_flush_running_cmds(hd); 262637c60f37SKashyap, Desai break; 262737c60f37SKashyap, Desai case MPT_IOC_POST_RESET: 262837c60f37SKashyap, Desai dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 262937c60f37SKashyap, Desai "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); 263037c60f37SKashyap, Desai if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) { 263137c60f37SKashyap, Desai ioc->internal_cmds.status |= 263237c60f37SKashyap, Desai MPT_MGMT_STATUS_DID_IOCRESET; 263337c60f37SKashyap, Desai complete(&ioc->internal_cmds.done); 26341da177e4SLinus Torvalds } 263537c60f37SKashyap, Desai break; 263637c60f37SKashyap, Desai default: 263737c60f37SKashyap, Desai break; 26381da177e4SLinus Torvalds } 26391da177e4SLinus Torvalds return 1; /* currently means nothing really */ 26401da177e4SLinus Torvalds } 26411da177e4SLinus Torvalds 26421da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26430d0c7974SMoore, Eric Dean int 26441da177e4SLinus Torvalds mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) 26451da177e4SLinus Torvalds { 26461da177e4SLinus Torvalds u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; 26471da177e4SLinus Torvalds 264837c60f37SKashyap, Desai devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 264937c60f37SKashyap, Desai "MPT event (=%02Xh) routed to SCSI host driver!\n", 26501da177e4SLinus Torvalds ioc->name, event)); 26511da177e4SLinus Torvalds 26522f187862SKashyap, Desai if ((event == MPI_EVENT_IOC_BUS_RESET || 26532f187862SKashyap, Desai event == MPI_EVENT_EXT_BUS_RESET) && 26542f187862SKashyap, Desai (ioc->bus_type == SPI) && (ioc->soft_resets < -1)) 26552f187862SKashyap, Desai ioc->soft_resets++; 26561da177e4SLinus Torvalds 26571da177e4SLinus Torvalds return 1; /* currently means nothing really */ 26581da177e4SLinus Torvalds } 26591da177e4SLinus Torvalds 26601da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26611da177e4SLinus Torvalds /* 26621da177e4SLinus Torvalds * Bus Scan and Domain Validation functionality ... 26631da177e4SLinus Torvalds */ 26641da177e4SLinus Torvalds 26651da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26661da177e4SLinus Torvalds /* 26671da177e4SLinus Torvalds * mptscsih_scandv_complete - Scan and DV callback routine registered 26681da177e4SLinus Torvalds * to Fustion MPT (base) driver. 26691da177e4SLinus Torvalds * 26701da177e4SLinus Torvalds * @ioc: Pointer to MPT_ADAPTER structure 26711da177e4SLinus Torvalds * @mf: Pointer to original MPT request frame 26721da177e4SLinus Torvalds * @mr: Pointer to MPT reply frame (NULL if TurboReply) 26731da177e4SLinus Torvalds * 26741da177e4SLinus Torvalds * This routine is called from mpt.c::mpt_interrupt() at the completion 26751da177e4SLinus Torvalds * of any SCSI IO request. 26761da177e4SLinus Torvalds * This routine is registered with the Fusion MPT (base) driver at driver 26771da177e4SLinus Torvalds * load/init time via the mpt_register() API call. 26781da177e4SLinus Torvalds * 26791da177e4SLinus Torvalds * Returns 1 indicating alloc'd request frame ptr should be freed. 26801da177e4SLinus Torvalds * 26811da177e4SLinus Torvalds * Remark: Sets a completion code and (possibly) saves sense data 26821da177e4SLinus Torvalds * in the IOC member localReply structure. 26831da177e4SLinus Torvalds * Used ONLY for DV and other internal commands. 26841da177e4SLinus Torvalds */ 26850d0c7974SMoore, Eric Dean int 268637c60f37SKashyap, Desai mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, 268737c60f37SKashyap, Desai MPT_FRAME_HDR *reply) 26881da177e4SLinus Torvalds { 26891da177e4SLinus Torvalds SCSIIORequest_t *pReq; 26901da177e4SLinus Torvalds SCSIIOReply_t *pReply; 269137c60f37SKashyap, Desai u8 cmd; 269237c60f37SKashyap, Desai u16 req_idx; 26931da177e4SLinus Torvalds u8 *sense_data; 26941da177e4SLinus Torvalds int sz; 26951da177e4SLinus Torvalds 269637c60f37SKashyap, Desai ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; 269737c60f37SKashyap, Desai ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD; 269837c60f37SKashyap, Desai if (!reply) 269937c60f37SKashyap, Desai goto out; 270037c60f37SKashyap, Desai 270137c60f37SKashyap, Desai pReply = (SCSIIOReply_t *) reply; 270237c60f37SKashyap, Desai pReq = (SCSIIORequest_t *) req; 270337c60f37SKashyap, Desai ioc->internal_cmds.completion_code = 270437c60f37SKashyap, Desai mptscsih_get_completion_code(ioc, req, reply); 270537c60f37SKashyap, Desai ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID; 270637c60f37SKashyap, Desai memcpy(ioc->internal_cmds.reply, reply, 270737c60f37SKashyap, Desai min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength)); 270837c60f37SKashyap, Desai cmd = reply->u.hdr.Function; 270937c60f37SKashyap, Desai if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || 271037c60f37SKashyap, Desai (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) && 271137c60f37SKashyap, Desai (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) { 271237c60f37SKashyap, Desai req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); 2713e80b002bSEric Moore sense_data = ((u8 *)ioc->sense_buf_pool + 27141da177e4SLinus Torvalds (req_idx * MPT_SENSE_BUFFER_ALLOC)); 27151da177e4SLinus Torvalds sz = min_t(int, pReq->SenseBufferLength, 271637c60f37SKashyap, Desai MPT_SENSE_BUFFER_ALLOC); 271737c60f37SKashyap, Desai memcpy(ioc->internal_cmds.sense, sense_data, sz); 27181da177e4SLinus Torvalds } 271937c60f37SKashyap, Desai out: 272037c60f37SKashyap, Desai if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING)) 272137c60f37SKashyap, Desai return 0; 272237c60f37SKashyap, Desai ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING; 272337c60f37SKashyap, Desai complete(&ioc->internal_cmds.done); 27241da177e4SLinus Torvalds return 1; 27251da177e4SLinus Torvalds } 27261da177e4SLinus Torvalds 27271da177e4SLinus Torvalds 272837c60f37SKashyap, Desai /** 272937c60f37SKashyap, Desai * mptscsih_get_completion_code - 273037c60f37SKashyap, Desai * @ioc: Pointer to MPT_ADAPTER structure 27319cf46a35SRandy Dunlap * @req: Pointer to original MPT request frame 27329cf46a35SRandy Dunlap * @reply: Pointer to MPT reply frame (NULL if TurboReply) 273337c60f37SKashyap, Desai * 273437c60f37SKashyap, Desai **/ 273537c60f37SKashyap, Desai static int 273637c60f37SKashyap, Desai mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, 273737c60f37SKashyap, Desai MPT_FRAME_HDR *reply) 273837c60f37SKashyap, Desai { 273937c60f37SKashyap, Desai SCSIIOReply_t *pReply; 274037c60f37SKashyap, Desai MpiRaidActionReply_t *pr; 274137c60f37SKashyap, Desai u8 scsi_status; 274237c60f37SKashyap, Desai u16 status; 274337c60f37SKashyap, Desai int completion_code; 274437c60f37SKashyap, Desai 274537c60f37SKashyap, Desai pReply = (SCSIIOReply_t *)reply; 274637c60f37SKashyap, Desai status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; 274737c60f37SKashyap, Desai scsi_status = pReply->SCSIStatus; 274837c60f37SKashyap, Desai 274937c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 275037c60f37SKashyap, Desai "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh," 275137c60f37SKashyap, Desai "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState, 275237c60f37SKashyap, Desai scsi_status, le32_to_cpu(pReply->IOCLogInfo))); 275337c60f37SKashyap, Desai 275437c60f37SKashyap, Desai switch (status) { 275537c60f37SKashyap, Desai 275637c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 275737c60f37SKashyap, Desai completion_code = MPT_SCANDV_SELECTION_TIMEOUT; 275837c60f37SKashyap, Desai break; 275937c60f37SKashyap, Desai 276037c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 276137c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ 276237c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 276337c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 276437c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 276537c60f37SKashyap, Desai break; 276637c60f37SKashyap, Desai 276737c60f37SKashyap, Desai case MPI_IOCSTATUS_BUSY: 276837c60f37SKashyap, Desai case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: 276937c60f37SKashyap, Desai completion_code = MPT_SCANDV_BUSY; 277037c60f37SKashyap, Desai break; 277137c60f37SKashyap, Desai 277237c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ 277337c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 277437c60f37SKashyap, Desai case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ 277537c60f37SKashyap, Desai if (pReply->Function == MPI_FUNCTION_CONFIG) { 277637c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 277737c60f37SKashyap, Desai } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { 277837c60f37SKashyap, Desai pr = (MpiRaidActionReply_t *)reply; 277937c60f37SKashyap, Desai if (le16_to_cpu(pr->ActionStatus) == 278037c60f37SKashyap, Desai MPI_RAID_ACTION_ASTATUS_SUCCESS) 278137c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 278237c60f37SKashyap, Desai else 278337c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 278437c60f37SKashyap, Desai } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) 278537c60f37SKashyap, Desai completion_code = MPT_SCANDV_SENSE; 278637c60f37SKashyap, Desai else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { 278737c60f37SKashyap, Desai if (req->u.scsireq.CDB[0] == INQUIRY) 278837c60f37SKashyap, Desai completion_code = MPT_SCANDV_ISSUE_SENSE; 278937c60f37SKashyap, Desai else 279037c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 279137c60f37SKashyap, Desai } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) 279237c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 279337c60f37SKashyap, Desai else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) 279437c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 279537c60f37SKashyap, Desai else if (scsi_status == MPI_SCSI_STATUS_BUSY) 279637c60f37SKashyap, Desai completion_code = MPT_SCANDV_BUSY; 279737c60f37SKashyap, Desai else 279837c60f37SKashyap, Desai completion_code = MPT_SCANDV_GOOD; 279937c60f37SKashyap, Desai break; 280037c60f37SKashyap, Desai 280137c60f37SKashyap, Desai case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 280237c60f37SKashyap, Desai if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) 280337c60f37SKashyap, Desai completion_code = MPT_SCANDV_DID_RESET; 280437c60f37SKashyap, Desai else 280537c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 280637c60f37SKashyap, Desai break; 280737c60f37SKashyap, Desai default: 280837c60f37SKashyap, Desai completion_code = MPT_SCANDV_SOME_ERROR; 280937c60f37SKashyap, Desai break; 281037c60f37SKashyap, Desai 281137c60f37SKashyap, Desai } /* switch(status) */ 281237c60f37SKashyap, Desai 281337c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 281437c60f37SKashyap, Desai " completionCode set to %08xh\n", ioc->name, completion_code)); 281537c60f37SKashyap, Desai return completion_code; 281637c60f37SKashyap, Desai } 28171da177e4SLinus Torvalds 28181da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 28191da177e4SLinus Torvalds /** 28201da177e4SLinus Torvalds * mptscsih_do_cmd - Do internal command. 28211da177e4SLinus Torvalds * @hd: MPT_SCSI_HOST pointer 28221da177e4SLinus Torvalds * @io: INTERNAL_CMD pointer. 28231da177e4SLinus Torvalds * 28241da177e4SLinus Torvalds * Issue the specified internally generated command and do command 28251da177e4SLinus Torvalds * specific cleanup. For bus scan / DV only. 28261da177e4SLinus Torvalds * NOTES: If command is Inquiry and status is good, 28271da177e4SLinus Torvalds * initialize a target structure, save the data 28281da177e4SLinus Torvalds * 28291da177e4SLinus Torvalds * Remark: Single threaded access only. 28301da177e4SLinus Torvalds * 28311da177e4SLinus Torvalds * Return: 28321da177e4SLinus Torvalds * < 0 if an illegal command or no resources 28331da177e4SLinus Torvalds * 28341da177e4SLinus Torvalds * 0 if good 28351da177e4SLinus Torvalds * 28361da177e4SLinus Torvalds * > 0 if command complete but some type of completion error. 28371da177e4SLinus Torvalds */ 28381da177e4SLinus Torvalds static int 28391da177e4SLinus Torvalds mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) 28401da177e4SLinus Torvalds { 28411da177e4SLinus Torvalds MPT_FRAME_HDR *mf; 28421da177e4SLinus Torvalds SCSIIORequest_t *pScsiReq; 28431da177e4SLinus Torvalds int my_idx, ii, dir; 284437c60f37SKashyap, Desai int timeout; 28451da177e4SLinus Torvalds char cmdLen; 28461da177e4SLinus Torvalds char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 284737c60f37SKashyap, Desai u8 cmd = io->cmd; 2848e80b002bSEric Moore MPT_ADAPTER *ioc = hd->ioc; 284937c60f37SKashyap, Desai int ret = 0; 285037c60f37SKashyap, Desai unsigned long timeleft; 285137c60f37SKashyap, Desai unsigned long flags; 28521da177e4SLinus Torvalds 28531ba9ab2eSKashyap, Desai /* don't send internal command during diag reset */ 28541ba9ab2eSKashyap, Desai spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 28551ba9ab2eSKashyap, Desai if (ioc->ioc_reset_in_progress) { 28561ba9ab2eSKashyap, Desai spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 28571ba9ab2eSKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 28581ba9ab2eSKashyap, Desai "%s: busy with host reset\n", ioc->name, __func__)); 28591ba9ab2eSKashyap, Desai return MPT_SCANDV_BUSY; 28601ba9ab2eSKashyap, Desai } 28611ba9ab2eSKashyap, Desai spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 28621ba9ab2eSKashyap, Desai 286337c60f37SKashyap, Desai mutex_lock(&ioc->internal_cmds.mutex); 28641da177e4SLinus Torvalds 28651da177e4SLinus Torvalds /* Set command specific information 28661da177e4SLinus Torvalds */ 28671da177e4SLinus Torvalds switch (cmd) { 28681da177e4SLinus Torvalds case INQUIRY: 28691da177e4SLinus Torvalds cmdLen = 6; 28701da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28711da177e4SLinus Torvalds CDB[0] = cmd; 28721da177e4SLinus Torvalds CDB[4] = io->size; 287337c60f37SKashyap, Desai timeout = 10; 28741da177e4SLinus Torvalds break; 28751da177e4SLinus Torvalds 28761da177e4SLinus Torvalds case TEST_UNIT_READY: 28771da177e4SLinus Torvalds cmdLen = 6; 28781da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 287937c60f37SKashyap, Desai timeout = 10; 28801da177e4SLinus Torvalds break; 28811da177e4SLinus Torvalds 28821da177e4SLinus Torvalds case START_STOP: 28831da177e4SLinus Torvalds cmdLen = 6; 28841da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 28851da177e4SLinus Torvalds CDB[0] = cmd; 28861da177e4SLinus Torvalds CDB[4] = 1; /*Spin up the disk */ 288737c60f37SKashyap, Desai timeout = 15; 28881da177e4SLinus Torvalds break; 28891da177e4SLinus Torvalds 28901da177e4SLinus Torvalds case REQUEST_SENSE: 28911da177e4SLinus Torvalds cmdLen = 6; 28921da177e4SLinus Torvalds CDB[0] = cmd; 28931da177e4SLinus Torvalds CDB[4] = io->size; 28941da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 289537c60f37SKashyap, Desai timeout = 10; 28961da177e4SLinus Torvalds break; 28971da177e4SLinus Torvalds 28981da177e4SLinus Torvalds case READ_BUFFER: 28991da177e4SLinus Torvalds cmdLen = 10; 29001da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 29011da177e4SLinus Torvalds CDB[0] = cmd; 29021da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_ECHO) { 29031da177e4SLinus Torvalds CDB[1] = 0x0A; 29041da177e4SLinus Torvalds } else { 29051da177e4SLinus Torvalds CDB[1] = 0x02; 29061da177e4SLinus Torvalds } 29071da177e4SLinus Torvalds 29081da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_BUF_CAP) { 29091da177e4SLinus Torvalds CDB[1] |= 0x01; 29101da177e4SLinus Torvalds } 29111da177e4SLinus Torvalds CDB[6] = (io->size >> 16) & 0xFF; 29121da177e4SLinus Torvalds CDB[7] = (io->size >> 8) & 0xFF; 29131da177e4SLinus Torvalds CDB[8] = io->size & 0xFF; 291437c60f37SKashyap, Desai timeout = 10; 29151da177e4SLinus Torvalds break; 29161da177e4SLinus Torvalds 29171da177e4SLinus Torvalds case WRITE_BUFFER: 29181da177e4SLinus Torvalds cmdLen = 10; 29191da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_WRITE; 29201da177e4SLinus Torvalds CDB[0] = cmd; 29211da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_ECHO) { 29221da177e4SLinus Torvalds CDB[1] = 0x0A; 29231da177e4SLinus Torvalds } else { 29241da177e4SLinus Torvalds CDB[1] = 0x02; 29251da177e4SLinus Torvalds } 29261da177e4SLinus Torvalds CDB[6] = (io->size >> 16) & 0xFF; 29271da177e4SLinus Torvalds CDB[7] = (io->size >> 8) & 0xFF; 29281da177e4SLinus Torvalds CDB[8] = io->size & 0xFF; 292937c60f37SKashyap, Desai timeout = 10; 29301da177e4SLinus Torvalds break; 29311da177e4SLinus Torvalds 29321da177e4SLinus Torvalds case RESERVE: 29331da177e4SLinus Torvalds cmdLen = 6; 29341da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 29351da177e4SLinus Torvalds CDB[0] = cmd; 293637c60f37SKashyap, Desai timeout = 10; 29371da177e4SLinus Torvalds break; 29381da177e4SLinus Torvalds 29391da177e4SLinus Torvalds case RELEASE: 29401da177e4SLinus Torvalds cmdLen = 6; 29411da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 29421da177e4SLinus Torvalds CDB[0] = cmd; 294337c60f37SKashyap, Desai timeout = 10; 29441da177e4SLinus Torvalds break; 29451da177e4SLinus Torvalds 29461da177e4SLinus Torvalds case SYNCHRONIZE_CACHE: 29471da177e4SLinus Torvalds cmdLen = 10; 29481da177e4SLinus Torvalds dir = MPI_SCSIIO_CONTROL_READ; 29491da177e4SLinus Torvalds CDB[0] = cmd; 29501da177e4SLinus Torvalds // CDB[1] = 0x02; /* set immediate bit */ 295137c60f37SKashyap, Desai timeout = 10; 29521da177e4SLinus Torvalds break; 29531da177e4SLinus Torvalds 29541da177e4SLinus Torvalds default: 29551da177e4SLinus Torvalds /* Error Case */ 295637c60f37SKashyap, Desai ret = -EFAULT; 295737c60f37SKashyap, Desai goto out; 29581da177e4SLinus Torvalds } 29591da177e4SLinus Torvalds 29601da177e4SLinus Torvalds /* Get and Populate a free Frame 296137c60f37SKashyap, Desai * MsgContext set in mpt_get_msg_frame call 29621da177e4SLinus Torvalds */ 2963e80b002bSEric Moore if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { 296437c60f37SKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n", 296537c60f37SKashyap, Desai ioc->name, __func__)); 296637c60f37SKashyap, Desai ret = MPT_SCANDV_BUSY; 296737c60f37SKashyap, Desai goto out; 29681da177e4SLinus Torvalds } 29691da177e4SLinus Torvalds 29701da177e4SLinus Torvalds pScsiReq = (SCSIIORequest_t *) mf; 29711da177e4SLinus Torvalds 29721da177e4SLinus Torvalds /* Get the request index */ 29731da177e4SLinus Torvalds my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); 29741da177e4SLinus Torvalds ADD_INDEX_LOG(my_idx); /* for debug */ 29751da177e4SLinus Torvalds 29761da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_PHYS_DISK) { 29771da177e4SLinus Torvalds pScsiReq->TargetID = io->physDiskNum; 29781da177e4SLinus Torvalds pScsiReq->Bus = 0; 29791da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 29801da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; 29811da177e4SLinus Torvalds } else { 29821da177e4SLinus Torvalds pScsiReq->TargetID = io->id; 2983793955f5SEric Moore pScsiReq->Bus = io->channel; 29841da177e4SLinus Torvalds pScsiReq->ChainOffset = 0; 29851da177e4SLinus Torvalds pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; 29861da177e4SLinus Torvalds } 29871da177e4SLinus Torvalds 29881da177e4SLinus Torvalds pScsiReq->CDBLength = cmdLen; 29891da177e4SLinus Torvalds pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE; 29901da177e4SLinus Torvalds 29911da177e4SLinus Torvalds pScsiReq->Reserved = 0; 29921da177e4SLinus Torvalds 299314d0f0b0SKashyap, Desai pScsiReq->MsgFlags = mpt_msg_flags(ioc); 29941da177e4SLinus Torvalds /* MsgContext set in mpt_get_msg_fram call */ 29951da177e4SLinus Torvalds 2996793955f5SEric Moore int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN); 29971da177e4SLinus Torvalds 29981da177e4SLinus Torvalds if (io->flags & MPT_ICFLAG_TAGGED_CMD) 29991da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ); 30001da177e4SLinus Torvalds else 30011da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); 30021da177e4SLinus Torvalds 30031da177e4SLinus Torvalds if (cmd == REQUEST_SENSE) { 30041da177e4SLinus Torvalds pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); 300537c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 300637c60f37SKashyap, Desai "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd)); 30071da177e4SLinus Torvalds } 30081da177e4SLinus Torvalds 30091da177e4SLinus Torvalds for (ii = 0; ii < 16; ii++) 30101da177e4SLinus Torvalds pScsiReq->CDB[ii] = CDB[ii]; 30111da177e4SLinus Torvalds 30121da177e4SLinus Torvalds pScsiReq->DataLength = cpu_to_le32(io->size); 3013e80b002bSEric Moore pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma 30141da177e4SLinus Torvalds + (my_idx * MPT_SENSE_BUFFER_ALLOC)); 30151da177e4SLinus Torvalds 301637c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 301737c60f37SKashyap, Desai "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n", 301837c60f37SKashyap, Desai ioc->name, __func__, cmd, io->channel, io->id, io->lun)); 30191da177e4SLinus Torvalds 302037c60f37SKashyap, Desai if (dir == MPI_SCSIIO_CONTROL_READ) 302114d0f0b0SKashyap, Desai ioc->add_sge((char *) &pScsiReq->SGL, 302237c60f37SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma); 302337c60f37SKashyap, Desai else 302414d0f0b0SKashyap, Desai ioc->add_sge((char *) &pScsiReq->SGL, 302537c60f37SKashyap, Desai MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma); 30261da177e4SLinus Torvalds 302737c60f37SKashyap, Desai INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) 3028e80b002bSEric Moore mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); 302937c60f37SKashyap, Desai timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 303037c60f37SKashyap, Desai timeout*HZ); 303137c60f37SKashyap, Desai if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 303237c60f37SKashyap, Desai ret = MPT_SCANDV_DID_RESET; 303337c60f37SKashyap, Desai dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 303437c60f37SKashyap, Desai "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__, 303537c60f37SKashyap, Desai cmd)); 303637c60f37SKashyap, Desai if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { 303737c60f37SKashyap, Desai mpt_free_msg_frame(ioc, mf); 303837c60f37SKashyap, Desai goto out; 303937c60f37SKashyap, Desai } 304037c60f37SKashyap, Desai if (!timeleft) { 304137c60f37SKashyap, Desai printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", 304237c60f37SKashyap, Desai ioc->name, __func__); 304337c60f37SKashyap, Desai mpt_HardResetHandler(ioc, CAN_SLEEP); 304437c60f37SKashyap, Desai mpt_free_msg_frame(ioc, mf); 304537c60f37SKashyap, Desai } 304637c60f37SKashyap, Desai goto out; 30471da177e4SLinus Torvalds } 30481da177e4SLinus Torvalds 304937c60f37SKashyap, Desai ret = ioc->internal_cmds.completion_code; 305037c60f37SKashyap, Desai devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n", 305137c60f37SKashyap, Desai ioc->name, __func__, ret)); 305237c60f37SKashyap, Desai 305337c60f37SKashyap, Desai out: 305437c60f37SKashyap, Desai CLEAR_MGMT_STATUS(ioc->internal_cmds.status) 305537c60f37SKashyap, Desai mutex_unlock(&ioc->internal_cmds.mutex); 305637c60f37SKashyap, Desai return ret; 30571da177e4SLinus Torvalds } 30581da177e4SLinus Torvalds 30591da177e4SLinus Torvalds /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 30601da177e4SLinus Torvalds /** 3061c7c82987SMoore, Eric Dean * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. 3062c7c82987SMoore, Eric Dean * @hd: Pointer to a SCSI HOST structure 3063d9489fb6SRandy Dunlap * @vdevice: virtual target device 3064c7c82987SMoore, Eric Dean * 3065c7c82987SMoore, Eric Dean * Uses the ISR, but with special processing. 3066c7c82987SMoore, Eric Dean * MUST be single-threaded. 3067c7c82987SMoore, Eric Dean * 3068c7c82987SMoore, Eric Dean */ 3069c7c82987SMoore, Eric Dean static void 3070c7c82987SMoore, Eric Dean mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice) 3071c7c82987SMoore, Eric Dean { 3072c7c82987SMoore, Eric Dean INTERNAL_CMD iocmd; 30731da177e4SLinus Torvalds 3074cc78d30aSEric Moore /* Ignore hidden raid components, this is handled when the command 3075cc78d30aSEric Moore * is sent to the volume 3076cc78d30aSEric Moore */ 3077cc78d30aSEric Moore if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 3078cc78d30aSEric Moore return; 3079cc78d30aSEric Moore 3080cc78d30aSEric Moore if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted || 3081cc78d30aSEric Moore !vdevice->configured_lun) 3082cc78d30aSEric Moore return; 3083cc78d30aSEric Moore 30841da177e4SLinus Torvalds /* Following parameters will not change 30851da177e4SLinus Torvalds * in this routine. 30861da177e4SLinus Torvalds */ 30871da177e4SLinus Torvalds iocmd.cmd = SYNCHRONIZE_CACHE; 30881da177e4SLinus Torvalds iocmd.flags = 0; 30891da177e4SLinus Torvalds iocmd.physDiskNum = -1; 30901da177e4SLinus Torvalds iocmd.data = NULL; 30911da177e4SLinus Torvalds iocmd.data_dma = -1; 30921da177e4SLinus Torvalds iocmd.size = 0; 30931da177e4SLinus Torvalds iocmd.rsvd = iocmd.rsvd2 = 0; 3094793955f5SEric Moore iocmd.channel = vdevice->vtarget->channel; 3095793955f5SEric Moore iocmd.id = vdevice->vtarget->id; 3096793955f5SEric Moore iocmd.lun = vdevice->lun; 30971da177e4SLinus Torvalds 3098c7c82987SMoore, Eric Dean mptscsih_do_cmd(hd, &iocmd); 30991da177e4SLinus Torvalds } 31001da177e4SLinus Torvalds 3101edb9068dSPrakash, Sathya static ssize_t 3102ee959b00STony Jones mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr, 3103ee959b00STony Jones char *buf) 3104edb9068dSPrakash, Sathya { 3105ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3106e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3107edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3108edb9068dSPrakash, Sathya 3109edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", 3110edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, 3111edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, 3112edb9068dSPrakash, Sathya (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, 3113edb9068dSPrakash, Sathya ioc->facts.FWVersion.Word & 0x000000FF); 3114edb9068dSPrakash, Sathya } 3115ee959b00STony Jones static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL); 3116edb9068dSPrakash, Sathya 3117edb9068dSPrakash, Sathya static ssize_t 3118ee959b00STony Jones mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr, 3119ee959b00STony Jones char *buf) 3120edb9068dSPrakash, Sathya { 3121ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3122e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3123edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3124edb9068dSPrakash, Sathya 3125edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", 3126edb9068dSPrakash, Sathya (ioc->biosVersion & 0xFF000000) >> 24, 3127edb9068dSPrakash, Sathya (ioc->biosVersion & 0x00FF0000) >> 16, 3128edb9068dSPrakash, Sathya (ioc->biosVersion & 0x0000FF00) >> 8, 3129edb9068dSPrakash, Sathya ioc->biosVersion & 0x000000FF); 3130edb9068dSPrakash, Sathya } 3131ee959b00STony Jones static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL); 3132edb9068dSPrakash, Sathya 3133edb9068dSPrakash, Sathya static ssize_t 3134ee959b00STony Jones mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr, 3135ee959b00STony Jones char *buf) 3136edb9068dSPrakash, Sathya { 3137ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3138e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3139edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3140edb9068dSPrakash, Sathya 3141edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); 3142edb9068dSPrakash, Sathya } 3143ee959b00STony Jones static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL); 3144edb9068dSPrakash, Sathya 3145edb9068dSPrakash, Sathya static ssize_t 3146ee959b00STony Jones mptscsih_version_product_show(struct device *dev, 3147ee959b00STony Jones struct device_attribute *attr, 3148ee959b00STony Jones char *buf) 3149edb9068dSPrakash, Sathya { 3150ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3151e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3152edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3153edb9068dSPrakash, Sathya 3154edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); 3155edb9068dSPrakash, Sathya } 3156ee959b00STony Jones static DEVICE_ATTR(version_product, S_IRUGO, 3157edb9068dSPrakash, Sathya mptscsih_version_product_show, NULL); 3158edb9068dSPrakash, Sathya 3159edb9068dSPrakash, Sathya static ssize_t 3160ee959b00STony Jones mptscsih_version_nvdata_persistent_show(struct device *dev, 3161ee959b00STony Jones struct device_attribute *attr, 3162ee959b00STony Jones char *buf) 3163edb9068dSPrakash, Sathya { 3164ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3165e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3166edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3167edb9068dSPrakash, Sathya 3168edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02xh\n", 3169edb9068dSPrakash, Sathya ioc->nvdata_version_persistent); 3170edb9068dSPrakash, Sathya } 3171ee959b00STony Jones static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, 3172edb9068dSPrakash, Sathya mptscsih_version_nvdata_persistent_show, NULL); 3173edb9068dSPrakash, Sathya 3174edb9068dSPrakash, Sathya static ssize_t 3175ee959b00STony Jones mptscsih_version_nvdata_default_show(struct device *dev, 3176ee959b00STony Jones struct device_attribute *attr, char *buf) 3177edb9068dSPrakash, Sathya { 3178ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3179e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3180edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3181edb9068dSPrakash, Sathya 3182edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); 3183edb9068dSPrakash, Sathya } 3184ee959b00STony Jones static DEVICE_ATTR(version_nvdata_default, S_IRUGO, 3185edb9068dSPrakash, Sathya mptscsih_version_nvdata_default_show, NULL); 3186edb9068dSPrakash, Sathya 3187edb9068dSPrakash, Sathya static ssize_t 3188ee959b00STony Jones mptscsih_board_name_show(struct device *dev, struct device_attribute *attr, 3189ee959b00STony Jones char *buf) 3190edb9068dSPrakash, Sathya { 3191ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3192e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3193edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3194edb9068dSPrakash, Sathya 3195edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); 3196edb9068dSPrakash, Sathya } 3197ee959b00STony Jones static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL); 3198edb9068dSPrakash, Sathya 3199edb9068dSPrakash, Sathya static ssize_t 3200ee959b00STony Jones mptscsih_board_assembly_show(struct device *dev, 3201ee959b00STony Jones struct device_attribute *attr, char *buf) 3202edb9068dSPrakash, Sathya { 3203ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3204e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3205edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3206edb9068dSPrakash, Sathya 3207edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); 3208edb9068dSPrakash, Sathya } 3209ee959b00STony Jones static DEVICE_ATTR(board_assembly, S_IRUGO, 3210edb9068dSPrakash, Sathya mptscsih_board_assembly_show, NULL); 3211edb9068dSPrakash, Sathya 3212edb9068dSPrakash, Sathya static ssize_t 3213ee959b00STony Jones mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr, 3214ee959b00STony Jones char *buf) 3215edb9068dSPrakash, Sathya { 3216ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3217e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3218edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3219edb9068dSPrakash, Sathya 3220edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); 3221edb9068dSPrakash, Sathya } 3222ee959b00STony Jones static DEVICE_ATTR(board_tracer, S_IRUGO, 3223edb9068dSPrakash, Sathya mptscsih_board_tracer_show, NULL); 3224edb9068dSPrakash, Sathya 3225edb9068dSPrakash, Sathya static ssize_t 3226ee959b00STony Jones mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr, 3227ee959b00STony Jones char *buf) 3228edb9068dSPrakash, Sathya { 3229ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3230e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3231edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3232edb9068dSPrakash, Sathya 3233edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); 3234edb9068dSPrakash, Sathya } 3235ee959b00STony Jones static DEVICE_ATTR(io_delay, S_IRUGO, 3236edb9068dSPrakash, Sathya mptscsih_io_delay_show, NULL); 3237edb9068dSPrakash, Sathya 3238edb9068dSPrakash, Sathya static ssize_t 3239ee959b00STony Jones mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr, 3240ee959b00STony Jones char *buf) 3241edb9068dSPrakash, Sathya { 3242ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3243e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 3244edb9068dSPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 3245edb9068dSPrakash, Sathya 3246edb9068dSPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); 3247edb9068dSPrakash, Sathya } 3248ee959b00STony Jones static DEVICE_ATTR(device_delay, S_IRUGO, 3249edb9068dSPrakash, Sathya mptscsih_device_delay_show, NULL); 3250edb9068dSPrakash, Sathya 32516757d6b4SPrakash, Sathya static ssize_t 3252ee959b00STony Jones mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr, 3253ee959b00STony Jones char *buf) 32546757d6b4SPrakash, Sathya { 3255ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3256e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 32576757d6b4SPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 32586757d6b4SPrakash, Sathya 32596757d6b4SPrakash, Sathya return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level); 32606757d6b4SPrakash, Sathya } 32616757d6b4SPrakash, Sathya static ssize_t 3262ee959b00STony Jones mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr, 3263ee959b00STony Jones const char *buf, size_t count) 32646757d6b4SPrakash, Sathya { 3265ee959b00STony Jones struct Scsi_Host *host = class_to_shost(dev); 3266e7eae9f6SEric Moore MPT_SCSI_HOST *hd = shost_priv(host); 32676757d6b4SPrakash, Sathya MPT_ADAPTER *ioc = hd->ioc; 32686757d6b4SPrakash, Sathya int val = 0; 32696757d6b4SPrakash, Sathya 32706757d6b4SPrakash, Sathya if (sscanf(buf, "%x", &val) != 1) 32716757d6b4SPrakash, Sathya return -EINVAL; 32726757d6b4SPrakash, Sathya 32736757d6b4SPrakash, Sathya ioc->debug_level = val; 32746757d6b4SPrakash, Sathya printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n", 32756757d6b4SPrakash, Sathya ioc->name, ioc->debug_level); 32766757d6b4SPrakash, Sathya return strlen(buf); 32776757d6b4SPrakash, Sathya } 3278ee959b00STony Jones static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR, 32796757d6b4SPrakash, Sathya mptscsih_debug_level_show, mptscsih_debug_level_store); 32806757d6b4SPrakash, Sathya 3281ee959b00STony Jones struct device_attribute *mptscsih_host_attrs[] = { 3282ee959b00STony Jones &dev_attr_version_fw, 3283ee959b00STony Jones &dev_attr_version_bios, 3284ee959b00STony Jones &dev_attr_version_mpi, 3285ee959b00STony Jones &dev_attr_version_product, 3286ee959b00STony Jones &dev_attr_version_nvdata_persistent, 3287ee959b00STony Jones &dev_attr_version_nvdata_default, 3288ee959b00STony Jones &dev_attr_board_name, 3289ee959b00STony Jones &dev_attr_board_assembly, 3290ee959b00STony Jones &dev_attr_board_tracer, 3291ee959b00STony Jones &dev_attr_io_delay, 3292ee959b00STony Jones &dev_attr_device_delay, 3293ee959b00STony Jones &dev_attr_debug_level, 3294edb9068dSPrakash, Sathya NULL, 3295edb9068dSPrakash, Sathya }; 329637c60f37SKashyap, Desai 3297edb9068dSPrakash, Sathya EXPORT_SYMBOL(mptscsih_host_attrs); 3298edb9068dSPrakash, Sathya 32990d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_remove); 33000d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_shutdown); 33010d0c7974SMoore, Eric Dean #ifdef CONFIG_PM 33020d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_suspend); 33030d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_resume); 33040d0c7974SMoore, Eric Dean #endif 33050d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_proc_info); 33060d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_info); 33070d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_qcmd); 33080d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_slave_destroy); 33090d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_slave_configure); 33100d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_abort); 33110d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_dev_reset); 33120d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_bus_reset); 33130d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_host_reset); 33140d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_bios_param); 33150d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_io_done); 33160d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_taskmgmt_complete); 33170d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_scandv_complete); 33180d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_event_process); 33190d0c7974SMoore, Eric Dean EXPORT_SYMBOL(mptscsih_ioc_reset); 33206e3815baSMoore, Eric Dean EXPORT_SYMBOL(mptscsih_change_queue_depth); 33211da177e4SLinus Torvalds 33220d0c7974SMoore, Eric Dean /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 3323