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