Showing error 1817

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/message/fusion/mptscsih.c
Line in file: 1415
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-11 08:47:26 UTC


Source:

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