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                u64 lun, int ctx2abort, ulong timeout);
  99
 100int             mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 101int             mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 102
 103void
 104mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code);
 105static int      mptscsih_get_completion_code(MPT_ADAPTER *ioc,
 106                MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 107int             mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 108static int      mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 109static void     mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
 110
 111static int
 112mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
 113                                SCSITaskMgmtReply_t *pScsiTmReply);
 114void            mptscsih_remove(struct pci_dev *);
 115void            mptscsih_shutdown(struct pci_dev *);
 116#ifdef CONFIG_PM
 117int             mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 118int             mptscsih_resume(struct pci_dev *pdev);
 119#endif
 120
 121#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 = %llu\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:%llu] "
 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:%llu) reported QUEUE_FULL!\n",
1159                                ioc->name, 0, sc->device->id, sc->device->lun));
1160                hd->last_queue_full = time;
1161        }
1162}
1163
1164/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1165/*
1166 *      mptscsih_remove - Removed scsi devices
1167 *      @pdev: Pointer to pci_dev structure
1168 *
1169 *
1170 */
1171void
1172mptscsih_remove(struct pci_dev *pdev)
1173{
1174        MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1175        struct Scsi_Host        *host = ioc->sh;
1176        MPT_SCSI_HOST           *hd;
1177        int sz1;
1178
1179        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->info_kbuf == NULL)
1275                if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1276                        return h->info_kbuf;
1277        h->info_kbuf[0] = '\0';
1278
1279        mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1280        h->info_kbuf[size-1] = '\0';
1281
1282        return h->info_kbuf;
1283}
1284
1285int mptscsih_show_info(struct seq_file *m, struct Scsi_Host *host)
1286{
1287        MPT_SCSI_HOST   *hd = shost_priv(host);
1288        MPT_ADAPTER     *ioc = hd->ioc;
1289
1290        seq_printf(m, "%s: %s, ", ioc->name, ioc->prod_name);
1291        seq_printf(m, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1292        seq_printf(m, "Ports=%d, ", ioc->facts.NumberOfPorts);
1293        seq_printf(m, "MaxQ=%d\n", ioc->req_depth);
1294
1295        return 0;
1296}
1297
1298/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1299#define ADD_INDEX_LOG(req_ent)  do { } while(0)
1300
1301/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1302/**
1303 *      mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1304 *      @SCpnt: Pointer to scsi_cmnd structure
1305 *
1306 *      (linux scsi_host_template.queuecommand routine)
1307 *      This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
1308 *      from a linux scsi_cmnd request and send it to the IOC.
1309 *
1310 *      Returns 0. (rtn value discarded by linux scsi mid-layer)
1311 */
1312int
1313mptscsih_qcmd(struct scsi_cmnd *SCpnt)
1314{
1315        MPT_SCSI_HOST           *hd;
1316        MPT_FRAME_HDR           *mf;
1317        SCSIIORequest_t         *pScsiReq;
1318        VirtDevice              *vdevice = SCpnt->device->hostdata;
1319        u32      datalen;
1320        u32      scsictl;
1321        u32      scsidir;
1322        u32      cmd_len;
1323        int      my_idx;
1324        int      ii;
1325        MPT_ADAPTER *ioc;
1326
1327        hd = shost_priv(SCpnt->device->host);
1328        ioc = hd->ioc;
1329
1330        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "qcmd: SCpnt=%p\n",
1331                ioc->name, SCpnt));
1332
1333        if (ioc->taskmgmt_quiesce_io)
1334                return SCSI_MLQUEUE_HOST_BUSY;
1335
1336        /*
1337         *  Put together a MPT SCSI request...
1338         */
1339        if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
1340                dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1341                                ioc->name));
1342                return SCSI_MLQUEUE_HOST_BUSY;
1343        }
1344
1345        pScsiReq = (SCSIIORequest_t *) mf;
1346
1347        my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1348
1349        ADD_INDEX_LOG(my_idx);
1350
1351        /*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1352         *    Seems we may receive a buffer (datalen>0) even when there
1353         *    will be no data transfer!  GRRRRR...
1354         */
1355        if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1356                datalen = scsi_bufflen(SCpnt);
1357                scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
1358        } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1359                datalen = scsi_bufflen(SCpnt);
1360                scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
1361        } else {
1362                datalen = 0;
1363                scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1364        }
1365
1366        /* Default to untagged. Once a target structure has been allocated,
1367         * use the Inquiry data to determine if device supports tagged.
1368         */
1369        if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1370            && (SCpnt->device->tagged_supported)) {
1371                scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1372                if (SCpnt->request && SCpnt->request->ioprio) {
1373                        if (((SCpnt->request->ioprio & 0x7) == 1) ||
1374                                !(SCpnt->request->ioprio & 0x7))
1375                                scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
1376                }
1377        } else
1378                scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1379
1380
1381        /* Use the above information to set up the message frame
1382         */
1383        pScsiReq->TargetID = (u8) vdevice->vtarget->id;
1384        pScsiReq->Bus = vdevice->vtarget->channel;
1385        pScsiReq->ChainOffset = 0;
1386        if (vdevice->vtarget->tflags &  MPT_TARGET_FLAGS_RAID_COMPONENT)
1387                pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
1388        else
1389                pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1390        pScsiReq->CDBLength = SCpnt->cmd_len;
1391        pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1392        pScsiReq->Reserved = 0;
1393        pScsiReq->MsgFlags = mpt_msg_flags(ioc);
1394        int_to_scsilun(SCpnt->device->lun, (struct scsi_lun *)pScsiReq->LUN);
1395        pScsiReq->Control = cpu_to_le32(scsictl);
1396
1397        /*
1398         *  Write SCSI CDB into the message
1399         */
1400        cmd_len = SCpnt->cmd_len;
1401        for (ii=0; ii < cmd_len; ii++)
1402                pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1403
1404        for (ii=cmd_len; ii < 16; ii++)
1405                pScsiReq->CDB[ii] = 0;
1406
1407        /* DataLength */
1408        pScsiReq->DataLength = cpu_to_le32(datalen);
1409
1410        /* SenseBuffer low address */
1411        pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
1412                                           + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1413
1414        /* Now add the SG list
1415         * Always have a SGE even if null length.
1416         */
1417        if (datalen == 0) {
1418                /* Add a NULL SGE */
1419                ioc->add_sge((char *)&pScsiReq->SGL,
1420                        MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1421                        (dma_addr_t) -1);
1422        } else {
1423                /* Add a 32 or 64 bit SGE */
1424                if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1425                        goto fail;
1426        }
1427
1428        SCpnt->host_scribble = (unsigned char *)mf;
1429        mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt);
1430
1431        mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
1432        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1433                        ioc->name, SCpnt, mf, my_idx));
1434        DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf);
1435        return 0;
1436
1437 fail:
1438        mptscsih_freeChainBuffers(ioc, my_idx);
1439        mpt_free_msg_frame(ioc, mf);
1440        return SCSI_MLQUEUE_HOST_BUSY;
1441}
1442
1443/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1444/*
1445 *      mptscsih_freeChainBuffers - Function to free chain buffers associated
1446 *      with a SCSI IO request
1447 *      @hd: Pointer to the MPT_SCSI_HOST instance
1448 *      @req_idx: Index of the SCSI IO request frame.
1449 *
1450 *      Called if SG chain buffer allocation fails and mptscsih callbacks.
1451 *      No return.
1452 */
1453static void
1454mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1455{
1456        MPT_FRAME_HDR *chain;
1457        unsigned long flags;
1458        int chain_idx;
1459        int next;
1460
1461        /* Get the first chain index and reset
1462         * tracker state.
1463         */
1464        chain_idx = ioc->ReqToChain[req_idx];
1465        ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1466
1467        while (chain_idx != MPT_HOST_NO_CHAIN) {
1468
1469                /* Save the next chain buffer index */
1470                next = ioc->ChainToChain[chain_idx];
1471
1472                /* Free this chain buffer and reset
1473                 * tracker
1474                 */
1475                ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1476
1477                chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1478                                        + (chain_idx * ioc->req_sz));
1479
1480                spin_lock_irqsave(&ioc->FreeQlock, flags);
1481                list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1482                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1483
1484                dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FreeChainBuffers (index %d)\n",
1485                                ioc->name, chain_idx));
1486
1487                /* handle next */
1488                chain_idx = next;
1489        }
1490        return;
1491}
1492
1493/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1494/*
1495 *      Reset Handling
1496 */
1497
1498/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1499/**
1500 *      mptscsih_IssueTaskMgmt - Generic send Task Management function.
1501 *      @hd: Pointer to MPT_SCSI_HOST structure
1502 *      @type: Task Management type
1503 *      @channel: channel number for task management
1504 *      @id: Logical Target ID for reset (if appropriate)
1505 *      @lun: Logical Unit for reset (if appropriate)
1506 *      @ctx2abort: Context for the task to be aborted (if appropriate)
1507 *      @timeout: timeout for task management control
1508 *
1509 *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1510 *      or a non-interrupt thread.  In the former, must not call schedule().
1511 *
1512 *      Not all fields are meaningfull for all task types.
1513 *
1514 *      Returns 0 for SUCCESS, or FAILED.
1515 *
1516 **/
1517int
1518mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, u64 lun,
1519        int ctx2abort, ulong timeout)
1520{
1521        MPT_FRAME_HDR   *mf;
1522        SCSITaskMgmt_t  *pScsiTm;
1523        int              ii;
1524        int              retval;
1525        MPT_ADAPTER     *ioc = hd->ioc;
1526        unsigned long    timeleft;
1527        u8               issue_hard_reset;
1528        u32              ioc_raw_state;
1529        unsigned long    time_count;
1530
1531        issue_hard_reset = 0;
1532        ioc_raw_state = mpt_GetIocState(ioc, 0);
1533
1534        if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1535                printk(MYIOC_s_WARN_FMT
1536                        "TaskMgmt type=%x: IOC Not operational (0x%x)!\n",
1537                        ioc->name, type, ioc_raw_state);
1538                printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
1539                    ioc->name, __func__);
1540                if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
1541                        printk(MYIOC_s_WARN_FMT "TaskMgmt HardReset "
1542                            "FAILED!!\n", ioc->name);
1543                return 0;
1544        }
1545
1546        /* DOORBELL ACTIVE check is not required if
1547        *  MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q is supported.
1548        */
1549
1550        if (!((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q)
1551                 && (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) &&
1552                (ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1553                printk(MYIOC_s_WARN_FMT
1554                        "TaskMgmt type=%x: ioc_state: "
1555                        "DOORBELL_ACTIVE (0x%x)!\n",
1556                        ioc->name, type, ioc_raw_state);
1557                return FAILED;
1558        }
1559
1560        mutex_lock(&ioc->taskmgmt_cmds.mutex);
1561        if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
1562                mf = NULL;
1563                retval = FAILED;
1564                goto out;
1565        }
1566
1567        /* Return Fail to calling function if no message frames available.
1568         */
1569        if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
1570                dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1571                        "TaskMgmt no msg frames!!\n", ioc->name));
1572                retval = FAILED;
1573                mpt_clear_taskmgmt_in_progress_flag(ioc);
1574                goto out;
1575        }
1576        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1577                        ioc->name, mf));
1578
1579        /* Format the Request
1580         */
1581        pScsiTm = (SCSITaskMgmt_t *) mf;
1582        pScsiTm->TargetID = id;
1583        pScsiTm->Bus = channel;
1584        pScsiTm->ChainOffset = 0;
1585        pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1586
1587        pScsiTm->Reserved = 0;
1588        pScsiTm->TaskType = type;
1589        pScsiTm->Reserved1 = 0;
1590        pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1591                    ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1592
1593        int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
1594
1595        for (ii=0; ii < 7; ii++)
1596                pScsiTm->Reserved2[ii] = 0;
1597
1598        pScsiTm->TaskMsgContext = ctx2abort;
1599
1600        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt: ctx2abort (0x%08x) "
1601                "task_type = 0x%02X, timeout = %ld\n", ioc->name, ctx2abort,
1602                type, timeout));
1603
1604        DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm);
1605
1606        INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1607        time_count = jiffies;
1608        if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&
1609            (ioc->facts.MsgVersion >= MPI_VERSION_01_05))
1610                mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
1611        else {
1612                retval = mpt_send_handshake_request(ioc->TaskCtx, ioc,
1613                        sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP);
1614                if (retval) {
1615                        dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1616                                "TaskMgmt handshake FAILED!(mf=%p, rc=%d) \n",
1617                                ioc->name, mf, retval));
1618                        mpt_free_msg_frame(ioc, mf);
1619                        mpt_clear_taskmgmt_in_progress_flag(ioc);
1620                        goto out;
1621                }
1622        }
1623
1624        timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
1625                timeout*HZ);
1626        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
1627                retval = FAILED;
1628                dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
1629                    "TaskMgmt TIMED OUT!(mf=%p)\n", ioc->name, mf));
1630                mpt_clear_taskmgmt_in_progress_flag(ioc);
1631                if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
1632                        goto out;
1633                issue_hard_reset = 1;
1634                goto out;
1635        }
1636
1637        retval = mptscsih_taskmgmt_reply(ioc, type,
1638            (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply);
1639
1640        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1641            "TaskMgmt completed (%d seconds)\n",
1642            ioc->name, jiffies_to_msecs(jiffies - time_count)/1000));
1643
1644 out:
1645
1646        CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
1647        if (issue_hard_reset) {
1648                printk(MYIOC_s_WARN_FMT
1649                       "Issuing Reset from %s!! doorbell=0x%08x\n",
1650                       ioc->name, __func__, mpt_GetIocState(ioc, 0));
1651                retval = (ioc->bus_type == SAS) ?
1652                        mpt_HardResetHandler(ioc, CAN_SLEEP) :
1653                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
1654                mpt_free_msg_frame(ioc, mf);
1655        }
1656
1657        retval = (retval == 0) ? 0 : FAILED;
1658        mutex_unlock(&ioc->taskmgmt_cmds.mutex);
1659        return retval;
1660}
1661EXPORT_SYMBOL(mptscsih_IssueTaskMgmt);
1662
1663static int
1664mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
1665{
1666        switch (ioc->bus_type) {
1667        case FC:
1668                return 40;
1669        case SAS:
1670                return 30;
1671        case SPI:
1672        default:
1673                return 10;
1674        }
1675}
1676
1677/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1678/**
1679 *      mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1680 *      @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1681 *
1682 *      (linux scsi_host_template.eh_abort_handler routine)
1683 *
1684 *      Returns SUCCESS or FAILED.
1685 **/
1686int
1687mptscsih_abort(struct scsi_cmnd * SCpnt)
1688{
1689        MPT_SCSI_HOST   *hd;
1690        MPT_FRAME_HDR   *mf;
1691        u32              ctx2abort;
1692        int              scpnt_idx;
1693        int              retval;
1694        VirtDevice       *vdevice;
1695        MPT_ADAPTER     *ioc;
1696
1697        /* If we can't locate our host adapter structure, return FAILED status.
1698         */
1699        if ((hd = shost_priv(SCpnt->device->host)) == NULL) {
1700                SCpnt->result = DID_RESET << 16;
1701                SCpnt->scsi_done(SCpnt);
1702                printk(KERN_ERR MYNAM ": task abort: "
1703                    "can't locate host! (sc=%p)\n", SCpnt);
1704                return FAILED;
1705        }
1706
1707        ioc = hd->ioc;
1708        printk(MYIOC_s_INFO_FMT "attempting task abort! (sc=%p)\n",
1709               ioc->name, SCpnt);
1710        scsi_print_command(SCpnt);
1711
1712        vdevice = SCpnt->device->hostdata;
1713        if (!vdevice || !vdevice->vtarget) {
1714                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1715                    "task abort: device has been deleted (sc=%p)\n",
1716                    ioc->name, SCpnt));
1717                SCpnt->result = DID_NO_CONNECT << 16;
1718                SCpnt->scsi_done(SCpnt);
1719                retval = SUCCESS;
1720                goto out;
1721        }
1722
1723        /* Task aborts are not supported for hidden raid components.
1724         */
1725        if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1726                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1727                    "task abort: hidden raid component (sc=%p)\n",
1728                    ioc->name, SCpnt));
1729                SCpnt->result = DID_RESET << 16;
1730                retval = FAILED;
1731                goto out;
1732        }
1733
1734        /* Task aborts are not supported for volumes.
1735         */
1736        if (vdevice->vtarget->raidVolume) {
1737                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1738                    "task abort: raid volume (sc=%p)\n",
1739                    ioc->name, SCpnt));
1740                SCpnt->result = DID_RESET << 16;
1741                retval = FAILED;
1742                goto out;
1743        }
1744
1745        /* Find this command
1746         */
1747        if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) {
1748                /* Cmd not found in ScsiLookup.
1749                 * Do OS callback.
1750                 */
1751                SCpnt->result = DID_RESET << 16;
1752                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: "
1753                   "Command not in the active list! (sc=%p)\n", ioc->name,
1754                   SCpnt));
1755                retval = SUCCESS;
1756                goto out;
1757        }
1758
1759        if (ioc->timeouts < -1)
1760                ioc->timeouts++;
1761
1762        if (mpt_fwfault_debug)
1763                mpt_halt_firmware(ioc);
1764
1765        /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
1766         * (the IO to be ABORT'd)
1767         *
1768         * NOTE: Since we do not byteswap MsgContext, we do not
1769         *       swap it here either.  It is an opaque cookie to
1770         *       the controller, so it does not matter. -DaveM
1771         */
1772        mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx);
1773        ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1774        retval = mptscsih_IssueTaskMgmt(hd,
1775                         MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1776                         vdevice->vtarget->channel,
1777                         vdevice->vtarget->id, vdevice->lun,
1778                         ctx2abort, mptscsih_get_tm_timeout(ioc));
1779
1780        if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx) {
1781                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1782                    "task abort: command still in active list! (sc=%p)\n",
1783                    ioc->name, SCpnt));
1784                retval = FAILED;
1785        } else {
1786                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1787                    "task abort: command cleared from active list! (sc=%p)\n",
1788                    ioc->name, SCpnt));
1789                retval = SUCCESS;
1790        }
1791
1792 out:
1793        printk(MYIOC_s_INFO_FMT "task abort: %s (rv=%04x) (sc=%p)\n",
1794            ioc->name, ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), retval,
1795            SCpnt);
1796
1797        return retval;
1798}
1799
1800/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1801/**
1802 *      mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
1803 *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1804 *
1805 *      (linux scsi_host_template.eh_dev_reset_handler routine)
1806 *
1807 *      Returns SUCCESS or FAILED.
1808 **/
1809int
1810mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1811{
1812        MPT_SCSI_HOST   *hd;
1813        int              retval;
1814        VirtDevice       *vdevice;
1815        MPT_ADAPTER     *ioc;
1816
1817        /* If we can't locate our host adapter structure, return FAILED status.
1818         */
1819        if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1820                printk(KERN_ERR MYNAM ": target reset: "
1821                   "Can't locate host! (sc=%p)\n", SCpnt);
1822                return FAILED;
1823        }
1824
1825        ioc = hd->ioc;
1826        printk(MYIOC_s_INFO_FMT "attempting target reset! (sc=%p)\n",
1827               ioc->name, SCpnt);
1828        scsi_print_command(SCpnt);
1829
1830        vdevice = SCpnt->device->hostdata;
1831        if (!vdevice || !vdevice->vtarget) {
1832                retval = 0;
1833                goto out;
1834        }
1835
1836        /* Target reset to hidden raid component is not supported
1837         */
1838        if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1839                retval = FAILED;
1840                goto out;
1841        }
1842
1843        retval = mptscsih_IssueTaskMgmt(hd,
1844                                MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1845                                vdevice->vtarget->channel,
1846                                vdevice->vtarget->id, 0, 0,
1847                                mptscsih_get_tm_timeout(ioc));
1848
1849 out:
1850        printk (MYIOC_s_INFO_FMT "target reset: %s (sc=%p)\n",
1851            ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1852
1853        if (retval == 0)
1854                return SUCCESS;
1855        else
1856                return FAILED;
1857}
1858
1859
1860/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1861/**
1862 *      mptscsih_bus_reset - Perform a SCSI BUS_RESET!  new_eh variant
1863 *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1864 *
1865 *      (linux scsi_host_template.eh_bus_reset_handler routine)
1866 *
1867 *      Returns SUCCESS or FAILED.
1868 **/
1869int
1870mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1871{
1872        MPT_SCSI_HOST   *hd;
1873        int              retval;
1874        VirtDevice       *vdevice;
1875        MPT_ADAPTER     *ioc;
1876
1877        /* If we can't locate our host adapter structure, return FAILED status.
1878         */
1879        if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1880                printk(KERN_ERR MYNAM ": bus reset: "
1881                   "Can't locate host! (sc=%p)\n", SCpnt);
1882                return FAILED;
1883        }
1884
1885        ioc = hd->ioc;
1886        printk(MYIOC_s_INFO_FMT "attempting bus reset! (sc=%p)\n",
1887               ioc->name, SCpnt);
1888        scsi_print_command(SCpnt);
1889
1890        if (ioc->timeouts < -1)
1891                ioc->timeouts++;
1892
1893        vdevice = SCpnt->device->hostdata;
1894        if (!vdevice || !vdevice->vtarget)
1895                return SUCCESS;
1896        retval = mptscsih_IssueTaskMgmt(hd,
1897                                        MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1898                                        vdevice->vtarget->channel, 0, 0, 0,
1899                                        mptscsih_get_tm_timeout(ioc));
1900
1901        printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n",
1902            ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1903
1904        if (retval == 0)
1905                return SUCCESS;
1906        else
1907                return FAILED;
1908}
1909
1910/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1911/**
1912 *      mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant)
1913 *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1914 *
1915 *      (linux scsi_host_template.eh_host_reset_handler routine)
1916 *
1917 *      Returns SUCCESS or FAILED.
1918 */
1919int
1920mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1921{
1922        MPT_SCSI_HOST *  hd;
1923        int              status = SUCCESS;
1924        MPT_ADAPTER     *ioc;
1925        int             retval;
1926
1927        /*  If we can't locate the host to reset, then we failed. */
1928        if ((hd = shost_priv(SCpnt->device->host)) == NULL){
1929                printk(KERN_ERR MYNAM ": host reset: "
1930                    "Can't locate host! (sc=%p)\n", SCpnt);
1931                return FAILED;
1932        }
1933
1934        /* make sure we have no outstanding commands at this stage */
1935        mptscsih_flush_running_cmds(hd);
1936
1937        ioc = hd->ioc;
1938        printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n",
1939            ioc->name, SCpnt);
1940
1941        /*  If our attempts to reset the host failed, then return a failed
1942         *  status.  The host will be taken off line by the SCSI mid-layer.
1943         */
1944    retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
1945        if (retval < 0)
1946                status = FAILED;
1947        else
1948                status = SUCCESS;
1949
1950        printk(MYIOC_s_INFO_FMT "host reset: %s (sc=%p)\n",
1951            ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
1952
1953        return status;
1954}
1955
1956static int
1957mptscsih_taskmgmt_reply(MPT_ADAPTER *ioc, u8 type,
1958        SCSITaskMgmtReply_t *pScsiTmReply)
1959{
1960        u16                      iocstatus;
1961        u32                      termination_count;
1962        int                      retval;
1963
1964        if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
1965                retval = FAILED;
1966                goto out;
1967        }
1968
1969        DBG_DUMP_TM_REPLY_FRAME(ioc, (u32 *)pScsiTmReply);
1970
1971        iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
1972        termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);
1973
1974        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1975            "TaskMgmt fw_channel = %d, fw_id = %d, task_type = 0x%02X,\n"
1976            "\tiocstatus = 0x%04X, loginfo = 0x%08X, response_code = 0x%02X,\n"
1977            "\tterm_cmnds = %d\n", ioc->name, pScsiTmReply->Bus,
1978            pScsiTmReply->TargetID, type, le16_to_cpu(pScsiTmReply->IOCStatus),
1979            le32_to_cpu(pScsiTmReply->IOCLogInfo), pScsiTmReply->ResponseCode,
1980            termination_count));
1981
1982        if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
1983            pScsiTmReply->ResponseCode)
1984                mptscsih_taskmgmt_response_code(ioc,
1985                    pScsiTmReply->ResponseCode);
1986
1987        if (iocstatus == MPI_IOCSTATUS_SUCCESS) {
1988                retval = 0;
1989                goto out;
1990        }
1991
1992        retval = FAILED;
1993        if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1994                if (termination_count == 1)
1995                        retval = 0;
1996                goto out;
1997        }
1998
1999        if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
2000           iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
2001                retval = 0;
2002
2003 out:
2004        return retval;
2005}
2006
2007/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2008void
2009mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
2010{
2011        char *desc;
2012
2013        switch (response_code) {
2014        case MPI_SCSITASKMGMT_RSP_TM_COMPLETE:
2015                desc = "The task completed.";
2016                break;
2017        case MPI_SCSITASKMGMT_RSP_INVALID_FRAME:
2018                desc = "The IOC received an invalid frame status.";
2019                break;
2020        case MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2021                desc = "The task type is not supported.";
2022                break;
2023        case MPI_SCSITASKMGMT_RSP_TM_FAILED:
2024                desc = "The requested task failed.";
2025                break;
2026        case MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2027                desc = "The task completed successfully.";
2028                break;
2029        case MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2030                desc = "The LUN request is invalid.";
2031                break;
2032        case MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2033                desc = "The task is in the IOC queue and has not been sent to target.";
2034                break;
2035        default:
2036                desc = "unknown";
2037                break;
2038        }
2039        printk(MYIOC_s_INFO_FMT "Response Code(0x%08x): F/W: %s\n",
2040                ioc->name, response_code, desc);
2041}
2042EXPORT_SYMBOL(mptscsih_taskmgmt_response_code);
2043
2044/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2045/**
2046 *      mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2047 *      @ioc: Pointer to MPT_ADAPTER structure
2048 *      @mf: Pointer to SCSI task mgmt request frame
2049 *      @mr: Pointer to SCSI task mgmt reply frame
2050 *
2051 *      This routine is called from mptbase.c::mpt_interrupt() at the completion
2052 *      of any SCSI task management request.
2053 *      This routine is registered with the MPT (base) driver at driver
2054 *      load/init time via the mpt_register() API call.
2055 *
2056 *      Returns 1 indicating alloc'd request frame ptr should be freed.
2057 **/
2058int
2059mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf,
2060        MPT_FRAME_HDR *mr)
2061{
2062        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2063                "TaskMgmt completed (mf=%p, mr=%p)\n", ioc->name, mf, mr));
2064
2065        ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2066
2067        if (!mr)
2068                goto out;
2069
2070        ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2071        memcpy(ioc->taskmgmt_cmds.reply, mr,
2072            min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
2073 out:
2074        if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
2075                mpt_clear_taskmgmt_in_progress_flag(ioc);
2076                ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2077                complete(&ioc->taskmgmt_cmds.done);
2078                if (ioc->bus_type == SAS)
2079                        ioc->schedule_target_reset(ioc);
2080                return 1;
2081        }
2082        return 0;
2083}
2084
2085/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2086/*
2087 *      This is anyones guess quite frankly.
2088 */
2089int
2090mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2091                sector_t capacity, int geom[])
2092{
2093        int             heads;
2094        int             sectors;
2095        sector_t        cylinders;
2096        ulong           dummy;
2097
2098        heads = 64;
2099        sectors = 32;
2100
2101        dummy = heads * sectors;
2102        cylinders = capacity;
2103        sector_div(cylinders,dummy);
2104
2105        /*
2106         * Handle extended translation size for logical drives
2107         * > 1Gb
2108         */
2109        if ((ulong)capacity >= 0x200000) {
2110                heads = 255;
2111                sectors = 63;
2112                dummy = heads * sectors;
2113                cylinders = capacity;
2114                sector_div(cylinders,dummy);
2115        }
2116
2117        /* return result */
2118        geom[0] = heads;
2119        geom[1] = sectors;
2120        geom[2] = cylinders;
2121
2122        return 0;
2123}
2124
2125/* Search IOC page 3 to determine if this is hidden physical disk
2126 *
2127 */
2128int
2129mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id)
2130{
2131        struct inactive_raid_component_info *component_info;
2132        int i, j;
2133        RaidPhysDiskPage1_t *phys_disk;
2134        int rc = 0;
2135        int num_paths;
2136
2137        if (!ioc->raid_data.pIocPg3)
2138                goto out;
2139        for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2140                if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2141                    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2142                        rc = 1;
2143                        goto out;
2144                }
2145        }
2146
2147        if (ioc->bus_type != SAS)
2148                goto out;
2149
2150        /*
2151         * Check if dual path
2152         */
2153        for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2154                num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2155                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2156                if (num_paths < 2)
2157                        continue;
2158                phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2159                   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2160                if (!phys_disk)
2161                        continue;
2162                if ((mpt_raid_phys_disk_pg1(ioc,
2163                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2164                    phys_disk))) {
2165                        kfree(phys_disk);
2166                        continue;
2167                }
2168                for (j = 0; j < num_paths; j++) {
2169                        if ((phys_disk->Path[j].Flags &
2170                            MPI_RAID_PHYSDISK1_FLAG_INVALID))
2171                                continue;
2172                        if ((phys_disk->Path[j].Flags &
2173                            MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2174                                continue;
2175                        if ((id == phys_disk->Path[j].PhysDiskID) &&
2176                            (channel == phys_disk->Path[j].PhysDiskBus)) {
2177                                rc = 1;
2178                                kfree(phys_disk);
2179                                goto out;
2180                        }
2181                }
2182                kfree(phys_disk);
2183        }
2184
2185
2186        /*
2187         * Check inactive list for matching phys disks
2188         */
2189        if (list_empty(&ioc->raid_data.inactive_list))
2190                goto out;
2191
2192        mutex_lock(&ioc->raid_data.inactive_list_mutex);
2193        list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2194            list) {
2195                if ((component_info->d.PhysDiskID == id) &&
2196                    (component_info->d.PhysDiskBus == channel))
2197                        rc = 1;
2198        }
2199        mutex_unlock(&ioc->raid_data.inactive_list_mutex);
2200
2201 out:
2202        return rc;
2203}
2204EXPORT_SYMBOL(mptscsih_is_phys_disk);
2205
2206u8
2207mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2208{
2209        struct inactive_raid_component_info *component_info;
2210        int i, j;
2211        RaidPhysDiskPage1_t *phys_disk;
2212        int rc = -ENXIO;
2213        int num_paths;
2214
2215        if (!ioc->raid_data.pIocPg3)
2216                goto out;
2217        for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2218                if ((id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) &&
2219                    (channel == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskBus)) {
2220                        rc = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum;
2221                        goto out;
2222                }
2223        }
2224
2225        if (ioc->bus_type != SAS)
2226                goto out;
2227
2228        /*
2229         * Check if dual path
2230         */
2231        for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
2232                num_paths = mpt_raid_phys_disk_get_num_paths(ioc,
2233                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum);
2234                if (num_paths < 2)
2235                        continue;
2236                phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
2237                   (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
2238                if (!phys_disk)
2239                        continue;
2240                if ((mpt_raid_phys_disk_pg1(ioc,
2241                    ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskNum,
2242                    phys_disk))) {
2243                        kfree(phys_disk);
2244                        continue;
2245                }
2246                for (j = 0; j < num_paths; j++) {
2247                        if ((phys_disk->Path[j].Flags &
2248                            MPI_RAID_PHYSDISK1_FLAG_INVALID))
2249                                continue;
2250                        if ((phys_disk->Path[j].Flags &
2251                            MPI_RAID_PHYSDISK1_FLAG_BROKEN))
2252                                continue;
2253                        if ((id == phys_disk->Path[j].PhysDiskID) &&
2254                            (channel == phys_disk->Path[j].PhysDiskBus)) {
2255                                rc = phys_disk->PhysDiskNum;
2256                                kfree(phys_disk);
2257                                goto out;
2258                        }
2259                }
2260                kfree(phys_disk);
2261        }
2262
2263        /*
2264         * Check inactive list for matching phys disks
2265         */
2266        if (list_empty(&ioc->raid_data.inactive_list))
2267                goto out;
2268
2269        mutex_lock(&ioc->raid_data.inactive_list_mutex);
2270        list_for_each_entry(component_info, &ioc->raid_data.inactive_list,
2271            list) {
2272                if ((component_info->d.PhysDiskID == id) &&
2273                    (component_info->d.PhysDiskBus == channel))
2274                        rc = component_info->d.PhysDiskNum;
2275        }
2276        mutex_unlock(&ioc->raid_data.inactive_list_mutex);
2277
2278 out:
2279        return rc;
2280}
2281EXPORT_SYMBOL(mptscsih_raid_id_to_num);
2282
2283/*
2284 *      OS entry point to allow for host driver to free allocated memory
2285 *      Called if no device present or device being unloaded
2286 */
2287void
2288mptscsih_slave_destroy(struct scsi_device *sdev)
2289{
2290        struct Scsi_Host        *host = sdev->host;
2291        MPT_SCSI_HOST           *hd = shost_priv(host);
2292        VirtTarget              *vtarget;
2293        VirtDevice              *vdevice;
2294        struct scsi_target      *starget;
2295
2296        starget = scsi_target(sdev);
2297        vtarget = starget->hostdata;
2298        vdevice = sdev->hostdata;
2299        if (!vdevice)
2300                return;
2301
2302        mptscsih_search_running_cmds(hd, vdevice);
2303        vtarget->num_luns--;
2304        mptscsih_synchronize_cache(hd, vdevice);
2305        kfree(vdevice);
2306        sdev->hostdata = NULL;
2307}
2308
2309/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2310/*
2311 *      mptscsih_change_queue_depth - This function will set a devices queue depth
2312 *      @sdev: per scsi_device pointer
2313 *      @qdepth: requested queue depth
2314 *
2315 *      Adding support for new 'change_queue_depth' api.
2316*/
2317int
2318mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2319{
2320        MPT_SCSI_HOST           *hd = shost_priv(sdev->host);
2321        VirtTarget              *vtarget;
2322        struct scsi_target      *starget;
2323        int                     max_depth;
2324        MPT_ADAPTER             *ioc = hd->ioc;
2325
2326        starget = scsi_target(sdev);
2327        vtarget = starget->hostdata;
2328
2329        if (ioc->bus_type == SPI) {
2330                if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2331                        max_depth = 1;
2332                else if (sdev->type == TYPE_DISK &&
2333                         vtarget->minSyncFactor <= MPT_ULTRA160)
2334                        max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2335                else
2336                        max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2337        } else
2338                 max_depth = ioc->sh->can_queue;
2339
2340        if (!sdev->tagged_supported)
2341                max_depth = 1;
2342
2343        if (qdepth > max_depth)
2344                qdepth = max_depth;
2345
2346        return scsi_change_queue_depth(sdev, qdepth);
2347}
2348
2349/*
2350 *      OS entry point to adjust the queue_depths on a per-device basis.
2351 *      Called once per device the bus scan. Use it to force the queue_depth
2352 *      member to 1 if a device does not support Q tags.
2353 *      Return non-zero if fails.
2354 */
2355int
2356mptscsih_slave_configure(struct scsi_device *sdev)
2357{
2358        struct Scsi_Host        *sh = sdev->host;
2359        VirtTarget              *vtarget;
2360        VirtDevice              *vdevice;
2361        struct scsi_target      *starget;
2362        MPT_SCSI_HOST           *hd = shost_priv(sh);
2363        MPT_ADAPTER             *ioc = hd->ioc;
2364
2365        starget = scsi_target(sdev);
2366        vtarget = starget->hostdata;
2367        vdevice = sdev->hostdata;
2368
2369        dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2370                "device @ %p, channel=%d, id=%d, lun=%llu\n",
2371                ioc->name, sdev, sdev->channel, sdev->id, sdev->lun));
2372        if (ioc->bus_type == SPI)
2373                dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2374                    "sdtr %d wdtr %d ppr %d inq length=%d\n",
2375                    ioc->name, sdev->sdtr, sdev->wdtr,
2376                    sdev->ppr, sdev->inquiry_len));
2377
2378        vdevice->configured_lun = 1;
2379
2380        dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2381                "Queue depth=%d, tflags=%x\n",
2382                ioc->name, sdev->queue_depth, vtarget->tflags));
2383
2384        if (ioc->bus_type == SPI)
2385                dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2386                    "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2387                    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
2388                    vtarget->minSyncFactor));
2389
2390        mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
2391        dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2392                "tagged %d, simple %d\n",
2393                ioc->name,sdev->tagged_supported, sdev->simple_tags));
2394
2395        blk_queue_dma_alignment (sdev->request_queue, 512 - 1);
2396
2397        return 0;
2398}
2399
2400/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2401/*
2402 *  Private routines...
2403 */
2404
2405/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2406/* Utility function to copy sense data from the scsi_cmnd buffer
2407 * to the FC and SCSI target structures.
2408 *
2409 */
2410static void
2411mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2412{
2413        VirtDevice      *vdevice;
2414        SCSIIORequest_t *pReq;
2415        u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
2416        MPT_ADAPTER     *ioc = hd->ioc;
2417
2418        /* Get target structure
2419         */
2420        pReq = (SCSIIORequest_t *) mf;
2421        vdevice = sc->device->hostdata;
2422
2423        if (sense_count) {
2424                u8 *sense_data;
2425                int req_index;
2426
2427                /* Copy the sense received into the scsi command block. */
2428                req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2429                sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2430                memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2431
2432                /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2433                 */
2434                if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2435                        if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) {
2436                                int idx;
2437
2438                                idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
2439                                ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2440                                ioc->events[idx].eventContext = ioc->eventContext;
2441
2442                                ioc->events[idx].data[0] = (pReq->LUN[1] << 24) |
2443                                        (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) |
2444                                        (sc->device->channel << 8) | sc->device->id;
2445
2446                                ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12];
2447
2448                                ioc->eventContext++;
2449                                if (ioc->pcidev->vendor ==
2450                                    PCI_VENDOR_ID_IBM) {
2451                                        mptscsih_issue_sep_command(ioc,
2452                                            vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
2453                                        vdevice->vtarget->tflags |=
2454                                            MPT_TARGET_FLAGS_LED_ON;
2455                                }
2456                        }
2457                }
2458        } else {
2459                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n",
2460                                ioc->name));
2461        }
2462}
2463
2464/**
2465 * mptscsih_get_scsi_lookup - retrieves scmd entry
2466 * @ioc: Pointer to MPT_ADAPTER structure
2467 * @i: index into the array
2468 *
2469 * Returns the scsi_cmd pointer
2470 */
2471struct scsi_cmnd *
2472mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i)
2473{
2474        unsigned long   flags;
2475        struct scsi_cmnd *scmd;
2476
2477        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2478        scmd = ioc->ScsiLookup[i];
2479        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2480
2481        return scmd;
2482}
2483EXPORT_SYMBOL(mptscsih_get_scsi_lookup);
2484
2485/**
2486 * mptscsih_getclear_scsi_lookup -  retrieves and clears scmd entry from ScsiLookup[] array list
2487 * @ioc: Pointer to MPT_ADAPTER structure
2488 * @i: index into the array
2489 *
2490 * Returns the scsi_cmd pointer
2491 *
2492 **/
2493static struct scsi_cmnd *
2494mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i)
2495{
2496        unsigned long   flags;
2497        struct scsi_cmnd *scmd;
2498
2499        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2500        scmd = ioc->ScsiLookup[i];
2501        ioc->ScsiLookup[i] = NULL;
2502        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2503
2504        return scmd;
2505}
2506
2507/**
2508 * mptscsih_set_scsi_lookup - write a scmd entry into the ScsiLookup[] array list
2509 *
2510 * @ioc: Pointer to MPT_ADAPTER structure
2511 * @i: index into the array
2512 * @scmd: scsi_cmnd pointer
2513 *
2514 **/
2515static void
2516mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd)
2517{
2518        unsigned long   flags;
2519
2520        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2521        ioc->ScsiLookup[i] = scmd;
2522        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2523}
2524
2525/**
2526 * SCPNT_TO_LOOKUP_IDX - searches for a given scmd in the ScsiLookup[] array list
2527 * @ioc: Pointer to MPT_ADAPTER structure
2528 * @sc: scsi_cmnd pointer
2529 */
2530static int
2531SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc)
2532{
2533        unsigned long   flags;
2534        int i, index=-1;
2535
2536        spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
2537        for (i = 0; i < ioc->req_depth; i++) {
2538                if (ioc->ScsiLookup[i] == sc) {
2539                        index = i;
2540                        goto out;
2541                }
2542        }
2543
2544 out:
2545        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
2546        return index;
2547}
2548
2549/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2550int
2551mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2552{
2553        MPT_SCSI_HOST   *hd;
2554
2555        if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL)
2556                return 0;
2557
2558        hd = shost_priv(ioc->sh);
2559        switch (reset_phase) {
2560        case MPT_IOC_SETUP_RESET:
2561                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2562                    "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
2563                break;
2564        case MPT_IOC_PRE_RESET:
2565                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2566                    "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
2567                mptscsih_flush_running_cmds(hd);
2568                break;
2569        case MPT_IOC_POST_RESET:
2570                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2571                    "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
2572                if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) {
2573                        ioc->internal_cmds.status |=
2574                                MPT_MGMT_STATUS_DID_IOCRESET;
2575                        complete(&ioc->internal_cmds.done);
2576                }
2577                break;
2578        default:
2579                break;
2580        }
2581        return 1;               /* currently means nothing really */
2582}
2583
2584/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2585int
2586mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2587{
2588        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2589
2590        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2591                "MPT event (=%02Xh) routed to SCSI host driver!\n",
2592                ioc->name, event));
2593
2594        if ((event == MPI_EVENT_IOC_BUS_RESET ||
2595            event == MPI_EVENT_EXT_BUS_RESET) &&
2596            (ioc->bus_type == SPI) && (ioc->soft_resets < -1))
2597                        ioc->soft_resets++;
2598
2599        return 1;               /* currently means nothing really */
2600}
2601
2602/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2603/*
2604 *  Bus Scan and Domain Validation functionality ...
2605 */
2606
2607/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2608/*
2609 *      mptscsih_scandv_complete - Scan and DV callback routine registered
2610 *      to Fustion MPT (base) driver.
2611 *
2612 *      @ioc: Pointer to MPT_ADAPTER structure
2613 *      @mf: Pointer to original MPT request frame
2614 *      @mr: Pointer to MPT reply frame (NULL if TurboReply)
2615 *
2616 *      This routine is called from mpt.c::mpt_interrupt() at the completion
2617 *      of any SCSI IO request.
2618 *      This routine is registered with the Fusion MPT (base) driver at driver
2619 *      load/init time via the mpt_register() API call.
2620 *
2621 *      Returns 1 indicating alloc'd request frame ptr should be freed.
2622 *
2623 *      Remark: Sets a completion code and (possibly) saves sense data
2624 *      in the IOC member localReply structure.
2625 *      Used ONLY for DV and other internal commands.
2626 */
2627int
2628mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2629                                MPT_FRAME_HDR *reply)
2630{
2631        SCSIIORequest_t *pReq;
2632        SCSIIOReply_t   *pReply;
2633        u8               cmd;
2634        u16              req_idx;
2635        u8      *sense_data;
2636        int              sz;
2637
2638        ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
2639        ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD;
2640        if (!reply)
2641                goto out;
2642
2643        pReply = (SCSIIOReply_t *) reply;
2644        pReq = (SCSIIORequest_t *) req;
2645        ioc->internal_cmds.completion_code =
2646            mptscsih_get_completion_code(ioc, req, reply);
2647        ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
2648        memcpy(ioc->internal_cmds.reply, reply,
2649            min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength));
2650        cmd = reply->u.hdr.Function;
2651        if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
2652            (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) &&
2653            (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) {
2654                req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
2655                sense_data = ((u8 *)ioc->sense_buf_pool +
2656                    (req_idx * MPT_SENSE_BUFFER_ALLOC));
2657                sz = min_t(int, pReq->SenseBufferLength,
2658                    MPT_SENSE_BUFFER_ALLOC);
2659                memcpy(ioc->internal_cmds.sense, sense_data, sz);
2660        }
2661 out:
2662        if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING))
2663                return 0;
2664        ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
2665        complete(&ioc->internal_cmds.done);
2666        return 1;
2667}
2668
2669
2670/**
2671 *      mptscsih_get_completion_code - get completion code from MPT request
2672 *      @ioc: Pointer to MPT_ADAPTER structure
2673 *      @req: Pointer to original MPT request frame
2674 *      @reply: Pointer to MPT reply frame (NULL if TurboReply)
2675 *
2676 **/
2677static int
2678mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2679                                MPT_FRAME_HDR *reply)
2680{
2681        SCSIIOReply_t   *pReply;
2682        MpiRaidActionReply_t *pr;
2683        u8               scsi_status;
2684        u16              status;
2685        int              completion_code;
2686
2687        pReply = (SCSIIOReply_t *)reply;
2688        status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2689        scsi_status = pReply->SCSIStatus;
2690
2691        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2692            "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh,"
2693            "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState,
2694            scsi_status, le32_to_cpu(pReply->IOCLogInfo)));
2695
2696        switch (status) {
2697
2698        case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
2699                completion_code = MPT_SCANDV_SELECTION_TIMEOUT;
2700                break;
2701
2702        case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
2703        case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
2704        case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
2705        case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
2706                completion_code = MPT_SCANDV_DID_RESET;
2707                break;
2708
2709        case MPI_IOCSTATUS_BUSY:
2710        case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
2711                completion_code = MPT_SCANDV_BUSY;
2712                break;
2713
2714        case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
2715        case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
2716        case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
2717                if (pReply->Function == MPI_FUNCTION_CONFIG) {
2718                        completion_code = MPT_SCANDV_GOOD;
2719                } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
2720                        pr = (MpiRaidActionReply_t *)reply;
2721                        if (le16_to_cpu(pr->ActionStatus) ==
2722                                MPI_RAID_ACTION_ASTATUS_SUCCESS)
2723                                completion_code = MPT_SCANDV_GOOD;
2724                        else
2725                                completion_code = MPT_SCANDV_SOME_ERROR;
2726                } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)
2727                        completion_code = MPT_SCANDV_SENSE;
2728                else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
2729                        if (req->u.scsireq.CDB[0] == INQUIRY)
2730                                completion_code = MPT_SCANDV_ISSUE_SENSE;
2731                        else
2732                                completion_code = MPT_SCANDV_DID_RESET;
2733                } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
2734                        completion_code = MPT_SCANDV_DID_RESET;
2735                else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2736                        completion_code = MPT_SCANDV_DID_RESET;
2737                else if (scsi_status == MPI_SCSI_STATUS_BUSY)
2738                        completion_code = MPT_SCANDV_BUSY;
2739                else
2740                        completion_code = MPT_SCANDV_GOOD;
2741                break;
2742
2743        case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
2744                if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
2745                        completion_code = MPT_SCANDV_DID_RESET;
2746                else
2747                        completion_code = MPT_SCANDV_SOME_ERROR;
2748                break;
2749        default:
2750                completion_code = MPT_SCANDV_SOME_ERROR;
2751                break;
2752
2753        }       /* switch(status) */
2754
2755        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2756            "  completionCode set to %08xh\n", ioc->name, completion_code));
2757        return completion_code;
2758}
2759
2760/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2761/**
2762 *      mptscsih_do_cmd - Do internal command.
2763 *      @hd: MPT_SCSI_HOST pointer
2764 *      @io: INTERNAL_CMD pointer.
2765 *
2766 *      Issue the specified internally generated command and do command
2767 *      specific cleanup. For bus scan / DV only.
2768 *      NOTES: If command is Inquiry and status is good,
2769 *      initialize a target structure, save the data
2770 *
2771 *      Remark: Single threaded access only.
2772 *
2773 *      Return:
2774 *              < 0 if an illegal command or no resources
2775 *
2776 *                 0 if good
2777 *
2778 *               > 0 if command complete but some type of completion error.
2779 */
2780static int
2781mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
2782{
2783        MPT_FRAME_HDR   *mf;
2784        SCSIIORequest_t *pScsiReq;
2785        int              my_idx, ii, dir;
2786        int              timeout;
2787        char             cmdLen;
2788        char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2789        u8               cmd = io->cmd;
2790        MPT_ADAPTER *ioc = hd->ioc;
2791        int              ret = 0;
2792        unsigned long    timeleft;
2793        unsigned long    flags;
2794
2795        /* don't send internal command during diag reset */
2796        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2797        if (ioc->ioc_reset_in_progress) {
2798                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2799                dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2800                        "%s: busy with host reset\n", ioc->name, __func__));
2801                return MPT_SCANDV_BUSY;
2802        }
2803        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2804
2805        mutex_lock(&ioc->internal_cmds.mutex);
2806
2807        /* Set command specific information
2808         */
2809        switch (cmd) {
2810        case INQUIRY:
2811                cmdLen = 6;
2812                dir = MPI_SCSIIO_CONTROL_READ;
2813                CDB[0] = cmd;
2814                CDB[4] = io->size;
2815                timeout = 10;
2816                break;
2817
2818        case TEST_UNIT_READY:
2819                cmdLen = 6;
2820                dir = MPI_SCSIIO_CONTROL_READ;
2821                timeout = 10;
2822                break;
2823
2824        case START_STOP:
2825                cmdLen = 6;
2826                dir = MPI_SCSIIO_CONTROL_READ;
2827                CDB[0] = cmd;
2828                CDB[4] = 1;     /*Spin up the disk */
2829                timeout = 15;
2830                break;
2831
2832        case REQUEST_SENSE:
2833                cmdLen = 6;
2834                CDB[0] = cmd;
2835                CDB[4] = io->size;
2836                dir = MPI_SCSIIO_CONTROL_READ;
2837                timeout = 10;
2838                break;
2839
2840        case READ_BUFFER:
2841                cmdLen = 10;
2842                dir = MPI_SCSIIO_CONTROL_READ;
2843                CDB[0] = cmd;
2844                if (io->flags & MPT_ICFLAG_ECHO) {
2845                        CDB[1] = 0x0A;
2846                } else {
2847                        CDB[1] = 0x02;
2848                }
2849
2850                if (io->flags & MPT_ICFLAG_BUF_CAP) {
2851                        CDB[1] |= 0x01;
2852                }
2853                CDB[6] = (io->size >> 16) & 0xFF;
2854                CDB[7] = (io->size >>  8) & 0xFF;
2855                CDB[8] = io->size & 0xFF;
2856                timeout = 10;
2857                break;
2858
2859        case WRITE_BUFFER:
2860                cmdLen = 10;
2861                dir = MPI_SCSIIO_CONTROL_WRITE;
2862                CDB[0] = cmd;
2863                if (io->flags & MPT_ICFLAG_ECHO) {
2864                        CDB[1] = 0x0A;
2865                } else {
2866                        CDB[1] = 0x02;
2867                }
2868                CDB[6] = (io->size >> 16) & 0xFF;
2869                CDB[7] = (io->size >>  8) & 0xFF;
2870                CDB[8] = io->size & 0xFF;
2871                timeout = 10;
2872                break;
2873
2874        case RESERVE:
2875                cmdLen = 6;
2876                dir = MPI_SCSIIO_CONTROL_READ;
2877                CDB[0] = cmd;
2878                timeout = 10;
2879                break;
2880
2881        case RELEASE:
2882                cmdLen = 6;
2883                dir = MPI_SCSIIO_CONTROL_READ;
2884                CDB[0] = cmd;
2885                timeout = 10;
2886                break;
2887
2888        case SYNCHRONIZE_CACHE:
2889                cmdLen = 10;
2890                dir = MPI_SCSIIO_CONTROL_READ;
2891                CDB[0] = cmd;
2892//              CDB[1] = 0x02;  /* set immediate bit */
2893                timeout = 10;
2894                break;
2895
2896        default:
2897                /* Error Case */
2898                ret = -EFAULT;
2899                goto out;
2900        }
2901
2902        /* Get and Populate a free Frame
2903         * MsgContext set in mpt_get_msg_frame call
2904         */
2905        if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {
2906                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n",
2907                    ioc->name, __func__));
2908                ret = MPT_SCANDV_BUSY;
2909                goto out;
2910        }
2911
2912        pScsiReq = (SCSIIORequest_t *) mf;
2913
2914        /* Get the request index */
2915        my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2916        ADD_INDEX_LOG(my_idx); /* for debug */
2917
2918        if (io->flags & MPT_ICFLAG_PHYS_DISK) {
2919                pScsiReq->TargetID = io->physDiskNum;
2920                pScsiReq->Bus = 0;
2921                pScsiReq->ChainOffset = 0;
2922                pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
2923        } else {
2924                pScsiReq->TargetID = io->id;
2925                pScsiReq->Bus = io->channel;
2926                pScsiReq->ChainOffset = 0;
2927                pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2928        }
2929
2930        pScsiReq->CDBLength = cmdLen;
2931        pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2932
2933        pScsiReq->Reserved = 0;
2934
2935        pScsiReq->MsgFlags = mpt_msg_flags(ioc);
2936        /* MsgContext set in mpt_get_msg_fram call  */
2937
2938        int_to_scsilun(io->lun, (struct scsi_lun *)pScsiReq->LUN);
2939
2940        if (io->flags & MPT_ICFLAG_TAGGED_CMD)
2941                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
2942        else
2943                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
2944
2945        if (cmd == REQUEST_SENSE) {
2946                pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
2947                devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2948                    "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd));
2949        }
2950
2951        for (ii = 0; ii < 16; ii++)
2952                pScsiReq->CDB[ii] = CDB[ii];
2953
2954        pScsiReq->DataLength = cpu_to_le32(io->size);
2955        pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma
2956                                           + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2957
2958        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2959            "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%llu\n",
2960            ioc->name, __func__, cmd, io->channel, io->id, io->lun));
2961
2962        if (dir == MPI_SCSIIO_CONTROL_READ)
2963                ioc->add_sge((char *) &pScsiReq->SGL,
2964                    MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma);
2965        else
2966                ioc->add_sge((char *) &pScsiReq->SGL,
2967                    MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma);
2968
2969        INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status)
2970        mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);
2971        timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done,
2972            timeout*HZ);
2973        if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2974                ret = MPT_SCANDV_DID_RESET;
2975                dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2976                    "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__,
2977                    cmd));
2978                if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) {
2979                        mpt_free_msg_frame(ioc, mf);
2980                        goto out;
2981                }
2982                if (!timeleft) {
2983                        printk(MYIOC_s_WARN_FMT
2984                               "Issuing Reset from %s!! doorbell=0x%08xh"
2985                               " cmd=0x%02x\n",
2986                               ioc->name, __func__, mpt_GetIocState(ioc, 0),
2987                               cmd);
2988                        mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
2989                        mpt_free_msg_frame(ioc, mf);
2990                }
2991                goto out;
2992        }
2993
2994        ret = ioc->internal_cmds.completion_code;
2995        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n",
2996                        ioc->name, __func__, ret));
2997
2998 out:
2999        CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
3000        mutex_unlock(&ioc->internal_cmds.mutex);
3001        return ret;
3002}
3003
3004/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3005/**
3006 *      mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3007 *      @hd: Pointer to a SCSI HOST structure
3008 *      @vdevice: virtual target device
3009 *
3010 *      Uses the ISR, but with special processing.
3011 *      MUST be single-threaded.
3012 *
3013 */
3014static void
3015mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
3016{
3017        INTERNAL_CMD             iocmd;
3018
3019        /* Ignore hidden raid components, this is handled when the command
3020         * is sent to the volume
3021         */
3022        if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
3023                return;
3024
3025        if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted ||
3026            !vdevice->configured_lun)
3027                return;
3028
3029        /* Following parameters will not change
3030         * in this routine.
3031         */
3032        iocmd.cmd = SYNCHRONIZE_CACHE;
3033        iocmd.flags = 0;
3034        iocmd.physDiskNum = -1;
3035        iocmd.data = NULL;
3036        iocmd.data_dma = -1;
3037        iocmd.size = 0;
3038        iocmd.rsvd = iocmd.rsvd2 = 0;
3039        iocmd.channel = vdevice->vtarget->channel;
3040        iocmd.id = vdevice->vtarget->id;
3041        iocmd.lun = vdevice->lun;
3042
3043        mptscsih_do_cmd(hd, &iocmd);
3044}
3045
3046static ssize_t
3047mptscsih_version_fw_show(struct device *dev, struct device_attribute *attr,
3048                         char *buf)
3049{
3050        struct Scsi_Host *host = class_to_shost(dev);
3051        MPT_SCSI_HOST   *hd = shost_priv(host);
3052        MPT_ADAPTER *ioc = hd->ioc;
3053
3054        return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
3055            (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
3056            (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
3057            (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
3058            ioc->facts.FWVersion.Word & 0x000000FF);
3059}
3060static DEVICE_ATTR(version_fw, S_IRUGO, mptscsih_version_fw_show, NULL);
3061
3062static ssize_t
3063mptscsih_version_bios_show(struct device *dev, struct device_attribute *attr,
3064                           char *buf)
3065{
3066        struct Scsi_Host *host = class_to_shost(dev);
3067        MPT_SCSI_HOST   *hd = shost_priv(host);
3068        MPT_ADAPTER *ioc = hd->ioc;
3069
3070        return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
3071            (ioc->biosVersion & 0xFF000000) >> 24,
3072            (ioc->biosVersion & 0x00FF0000) >> 16,
3073            (ioc->biosVersion & 0x0000FF00) >> 8,
3074            ioc->biosVersion & 0x000000FF);
3075}
3076static DEVICE_ATTR(version_bios, S_IRUGO, mptscsih_version_bios_show, NULL);
3077
3078static ssize_t
3079mptscsih_version_mpi_show(struct device *dev, struct device_attribute *attr,
3080                          char *buf)
3081{
3082        struct Scsi_Host *host = class_to_shost(dev);
3083        MPT_SCSI_HOST   *hd = shost_priv(host);
3084        MPT_ADAPTER *ioc = hd->ioc;
3085
3086        return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion);
3087}
3088static DEVICE_ATTR(version_mpi, S_IRUGO, mptscsih_version_mpi_show, NULL);
3089
3090static ssize_t
3091mptscsih_version_product_show(struct device *dev,
3092                              struct device_attribute *attr,
3093char *buf)
3094{
3095        struct Scsi_Host *host = class_to_shost(dev);
3096        MPT_SCSI_HOST   *hd = shost_priv(host);
3097        MPT_ADAPTER *ioc = hd->ioc;
3098
3099        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name);
3100}
3101static DEVICE_ATTR(version_product, S_IRUGO,
3102    mptscsih_version_product_show, NULL);
3103
3104static ssize_t
3105mptscsih_version_nvdata_persistent_show(struct device *dev,
3106                                        struct device_attribute *attr,
3107                                        char *buf)
3108{
3109        struct Scsi_Host *host = class_to_shost(dev);
3110        MPT_SCSI_HOST   *hd = shost_priv(host);
3111        MPT_ADAPTER *ioc = hd->ioc;
3112
3113        return snprintf(buf, PAGE_SIZE, "%02xh\n",
3114            ioc->nvdata_version_persistent);
3115}
3116static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
3117    mptscsih_version_nvdata_persistent_show, NULL);
3118
3119static ssize_t
3120mptscsih_version_nvdata_default_show(struct device *dev,
3121                                     struct device_attribute *attr, char *buf)
3122{
3123        struct Scsi_Host *host = class_to_shost(dev);
3124        MPT_SCSI_HOST   *hd = shost_priv(host);
3125        MPT_ADAPTER *ioc = hd->ioc;
3126
3127        return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default);
3128}
3129static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
3130    mptscsih_version_nvdata_default_show, NULL);
3131
3132static ssize_t
3133mptscsih_board_name_show(struct device *dev, struct device_attribute *attr,
3134                         char *buf)
3135{
3136        struct Scsi_Host *host = class_to_shost(dev);
3137        MPT_SCSI_HOST   *hd = shost_priv(host);
3138        MPT_ADAPTER *ioc = hd->ioc;
3139
3140        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name);
3141}
3142static DEVICE_ATTR(board_name, S_IRUGO, mptscsih_board_name_show, NULL);
3143
3144static ssize_t
3145mptscsih_board_assembly_show(struct device *dev,
3146                             struct device_attribute *attr, char *buf)
3147{
3148        struct Scsi_Host *host = class_to_shost(dev);
3149        MPT_SCSI_HOST   *hd = shost_priv(host);
3150        MPT_ADAPTER *ioc = hd->ioc;
3151
3152        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly);
3153}
3154static DEVICE_ATTR(board_assembly, S_IRUGO,
3155    mptscsih_board_assembly_show, NULL);
3156
3157static ssize_t
3158mptscsih_board_tracer_show(struct device *dev, struct device_attribute *attr,
3159                           char *buf)
3160{
3161        struct Scsi_Host *host = class_to_shost(dev);
3162        MPT_SCSI_HOST   *hd = shost_priv(host);
3163        MPT_ADAPTER *ioc = hd->ioc;
3164
3165        return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer);
3166}
3167static DEVICE_ATTR(board_tracer, S_IRUGO,
3168    mptscsih_board_tracer_show, NULL);
3169
3170static ssize_t
3171mptscsih_io_delay_show(struct device *dev, struct device_attribute *attr,
3172                       char *buf)
3173{
3174        struct Scsi_Host *host = class_to_shost(dev);
3175        MPT_SCSI_HOST   *hd = shost_priv(host);
3176        MPT_ADAPTER *ioc = hd->ioc;
3177
3178        return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
3179}
3180static DEVICE_ATTR(io_delay, S_IRUGO,
3181    mptscsih_io_delay_show, NULL);
3182
3183static ssize_t
3184mptscsih_device_delay_show(struct device *dev, struct device_attribute *attr,
3185                           char *buf)
3186{
3187        struct Scsi_Host *host = class_to_shost(dev);
3188        MPT_SCSI_HOST   *hd = shost_priv(host);
3189        MPT_ADAPTER *ioc = hd->ioc;
3190
3191        return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
3192}
3193static DEVICE_ATTR(device_delay, S_IRUGO,
3194    mptscsih_device_delay_show, NULL);
3195
3196static ssize_t
3197mptscsih_debug_level_show(struct device *dev, struct device_attribute *attr,
3198                          char *buf)
3199{
3200        struct Scsi_Host *host = class_to_shost(dev);
3201        MPT_SCSI_HOST   *hd = shost_priv(host);
3202        MPT_ADAPTER *ioc = hd->ioc;
3203
3204        return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level);
3205}
3206static ssize_t
3207mptscsih_debug_level_store(struct device *dev, struct device_attribute *attr,
3208                           const char *buf, size_t count)
3209{
3210        struct Scsi_Host *host = class_to_shost(dev);
3211        MPT_SCSI_HOST   *hd = shost_priv(host);
3212        MPT_ADAPTER *ioc = hd->ioc;
3213        int val = 0;
3214
3215        if (sscanf(buf, "%x", &val) != 1)
3216                return -EINVAL;
3217
3218        ioc->debug_level = val;
3219        printk(MYIOC_s_INFO_FMT "debug_level=%08xh\n",
3220                                ioc->name, ioc->debug_level);
3221        return strlen(buf);
3222}
3223static DEVICE_ATTR(debug_level, S_IRUGO | S_IWUSR,
3224        mptscsih_debug_level_show, mptscsih_debug_level_store);
3225
3226struct device_attribute *mptscsih_host_attrs[] = {
3227        &dev_attr_version_fw,
3228        &dev_attr_version_bios,
3229        &dev_attr_version_mpi,
3230        &dev_attr_version_product,
3231        &dev_attr_version_nvdata_persistent,
3232        &dev_attr_version_nvdata_default,
3233        &dev_attr_board_name,
3234        &dev_attr_board_assembly,
3235        &dev_attr_board_tracer,
3236        &dev_attr_io_delay,
3237        &dev_attr_device_delay,
3238        &dev_attr_debug_level,
3239        NULL,
3240};
3241
3242EXPORT_SYMBOL(mptscsih_host_attrs);
3243
3244EXPORT_SYMBOL(mptscsih_remove);
3245EXPORT_SYMBOL(mptscsih_shutdown);
3246#ifdef CONFIG_PM
3247EXPORT_SYMBOL(mptscsih_suspend);
3248EXPORT_SYMBOL(mptscsih_resume);
3249#endif
3250EXPORT_SYMBOL(mptscsih_show_info);
3251EXPORT_SYMBOL(mptscsih_info);
3252EXPORT_SYMBOL(mptscsih_qcmd);
3253EXPORT_SYMBOL(mptscsih_slave_destroy);
3254EXPORT_SYMBOL(mptscsih_slave_configure);
3255EXPORT_SYMBOL(mptscsih_abort);
3256EXPORT_SYMBOL(mptscsih_dev_reset);
3257EXPORT_SYMBOL(mptscsih_bus_reset);
3258EXPORT_SYMBOL(mptscsih_host_reset);
3259EXPORT_SYMBOL(mptscsih_bios_param);
3260EXPORT_SYMBOL(mptscsih_io_done);
3261EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
3262EXPORT_SYMBOL(mptscsih_scandv_complete);
3263EXPORT_SYMBOL(mptscsih_event_process);
3264EXPORT_SYMBOL(mptscsih_ioc_reset);
3265EXPORT_SYMBOL(mptscsih_change_queue_depth);
3266
3267/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3268