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