Showing error 1814

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/message/fusion/mptbase.c
Line in file: 2350
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/mptbase.c
   3 *      This is the Fusion MPT base driver which supports multiple
   4 *      (SCSI + LAN) specialized protocol drivers.
   5 *      For use with LSI PCI chip/adapter(s)
   6 *      running LSI Fusion MPT (Message Passing Technology) firmware.
   7 *
   8 *  Copyright (c) 1999-2008 LSI Corporation
   9 *  (mailto:DL-MPTFusionLinux@lsi.com)
  10 *
  11 */
  12/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  13/*
  14    This program is free software; you can redistribute it and/or modify
  15    it under the terms of the GNU General Public License as published by
  16    the Free Software Foundation; version 2 of the License.
  17
  18    This program is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22
  23    NO WARRANTY
  24    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
  25    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
  26    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
  27    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
  28    solely responsible for determining the appropriateness of using and
  29    distributing the Program and assumes all risks associated with its
  30    exercise of rights under this Agreement, including but not limited to
  31    the risks and costs of program errors, damage to or loss of data,
  32    programs or equipment, and unavailability or interruption of operations.
  33
  34    DISCLAIMER OF LIABILITY
  35    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
  36    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
  38    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  39    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  40    USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
  41    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
  42
  43    You should have received a copy of the GNU General Public License
  44    along with this program; if not, write to the Free Software
  45    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  46*/
  47/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  48
  49#include <linux/kernel.h>
  50#include <linux/module.h>
  51#include <linux/errno.h>
  52#include <linux/init.h>
  53#include <linux/slab.h>
  54#include <linux/types.h>
  55#include <linux/pci.h>
  56#include <linux/kdev_t.h>
  57#include <linux/blkdev.h>
  58#include <linux/delay.h>
  59#include <linux/interrupt.h>                /* needed for in_interrupt() proto */
  60#include <linux/dma-mapping.h>
  61#include <asm/io.h>
  62#ifdef CONFIG_MTRR
  63#include <asm/mtrr.h>
  64#endif
  65
  66#include "mptbase.h"
  67#include "lsi/mpi_log_fc.h"
  68
  69/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  70#define my_NAME                "Fusion MPT base driver"
  71#define my_VERSION        MPT_LINUX_VERSION_COMMON
  72#define MYNAM                "mptbase"
  73
  74MODULE_AUTHOR(MODULEAUTHOR);
  75MODULE_DESCRIPTION(my_NAME);
  76MODULE_LICENSE("GPL");
  77MODULE_VERSION(my_VERSION);
  78
  79/*
  80 *  cmd line parameters
  81 */
  82static int mpt_msi_enable = -1;
  83module_param(mpt_msi_enable, int, 0);
  84MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
  85
  86static int mpt_channel_mapping;
  87module_param(mpt_channel_mapping, int, 0);
  88MODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)");
  89
  90static int mpt_debug_level;
  91static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
  92module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
  93                  &mpt_debug_level, 0600);
  94MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");
  95
  96#ifdef MFCNT
  97static int mfcounter = 0;
  98#define PRINT_MF_COUNT 20000
  99#endif
 100
 101/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 102/*
 103 *  Public data...
 104 */
 105
 106static struct proc_dir_entry *mpt_proc_root_dir;
 107
 108#define WHOINIT_UNKNOWN                0xAA
 109
 110/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 111/*
 112 *  Private data...
 113 */
 114                                        /* Adapter link list */
 115LIST_HEAD(ioc_list);
 116                                        /* Callback lookup table */
 117static MPT_CALLBACK                 MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS];
 118                                        /* Protocol driver class lookup table */
 119static int                         MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS];
 120                                        /* Event handler lookup table */
 121static MPT_EVHANDLER                 MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 122                                        /* Reset handler lookup table */
 123static MPT_RESETHANDLER                 MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 124static struct mpt_pci_driver         *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS];
 125
 126static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 127
 128/*
 129 *  Driver Callback Index's
 130 */
 131static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS;
 132static u8 last_drv_idx;
 133
 134/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 135/*
 136 *  Forward protos...
 137 */
 138static irqreturn_t mpt_interrupt(int irq, void *bus_id);
 139static int        mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 140static int        mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes,
 141                        u32 *req, int replyBytes, u16 *u16reply, int maxwait,
 142                        int sleepFlag);
 143static int        mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
 144static void        mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
 145static void        mpt_adapter_disable(MPT_ADAPTER *ioc);
 146static void        mpt_adapter_dispose(MPT_ADAPTER *ioc);
 147
 148static void        MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
 149static int        MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag);
 150static int        GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason);
 151static int        GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
 152static int        SendIocInit(MPT_ADAPTER *ioc, int sleepFlag);
 153static int        SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag);
 154static int        mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag);
 155static int        mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag);
 156static int        mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 157static int        KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag);
 158static int        SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag);
 159static int        PrimeIocFifos(MPT_ADAPTER *ioc);
 160static int        WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 161static int        WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 162static int        WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 163static int        GetLanConfigPages(MPT_ADAPTER *ioc);
 164static int        GetIoUnitPage2(MPT_ADAPTER *ioc);
 165int                mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 166static int        mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
 167static int        mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
 168static void         mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
 169static void         mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
 170static void        mpt_timer_expired(unsigned long data);
 171static void        mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc);
 172static int        SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch);
 173static int        SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp);
 174static int        mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag);
 175static int        mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init);
 176
 177#ifdef CONFIG_PROC_FS
 178static int        procmpt_summary_read(char *buf, char **start, off_t offset,
 179                                int request, int *eof, void *data);
 180static int        procmpt_version_read(char *buf, char **start, off_t offset,
 181                                int request, int *eof, void *data);
 182static int        procmpt_iocinfo_read(char *buf, char **start, off_t offset,
 183                                int request, int *eof, void *data);
 184#endif
 185static void        mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc);
 186
 187//int                mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 188static int        ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *evReply, int *evHandlers);
 189static void        mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf);
 190static void        mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
 191static void        mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 192static void        mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);
 193static int        mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 194static void        mpt_inactive_raid_list_free(MPT_ADAPTER *ioc);
 195
 196/* module entry point */
 197static int  __init    fusion_init  (void);
 198static void __exit    fusion_exit  (void);
 199
 200#define CHIPREG_READ32(addr)                 readl_relaxed(addr)
 201#define CHIPREG_READ32_dmasync(addr)        readl(addr)
 202#define CHIPREG_WRITE32(addr,val)         writel(val, addr)
 203#define CHIPREG_PIO_WRITE32(addr,val)        outl(val, (unsigned long)addr)
 204#define CHIPREG_PIO_READ32(addr)         inl((unsigned long)addr)
 205
 206static void
 207pci_disable_io_access(struct pci_dev *pdev)
 208{
 209        u16 command_reg;
 210
 211        pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
 212        command_reg &= ~1;
 213        pci_write_config_word(pdev, PCI_COMMAND, command_reg);
 214}
 215
 216static void
 217pci_enable_io_access(struct pci_dev *pdev)
 218{
 219        u16 command_reg;
 220
 221        pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
 222        command_reg |= 1;
 223        pci_write_config_word(pdev, PCI_COMMAND, command_reg);
 224}
 225
 226static int mpt_set_debug_level(const char *val, struct kernel_param *kp)
 227{
 228        int ret = param_set_int(val, kp);
 229        MPT_ADAPTER *ioc;
 230
 231        if (ret)
 232                return ret;
 233
 234        list_for_each_entry(ioc, &ioc_list, list)
 235                ioc->debug_level = mpt_debug_level;
 236        return 0;
 237}
 238
 239/**
 240 *        mpt_get_cb_idx - obtain cb_idx for registered driver
 241 *        @dclass: class driver enum
 242 *
 243 *        Returns cb_idx, or zero means it wasn't found
 244 **/
 245static u8
 246mpt_get_cb_idx(MPT_DRIVER_CLASS dclass)
 247{
 248        u8 cb_idx;
 249
 250        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--)
 251                if (MptDriverClass[cb_idx] == dclass)
 252                        return cb_idx;
 253        return 0;
 254}
 255
 256/**
 257 *        mpt_fault_reset_work - work performed on workq after ioc fault
 258 *        @work: input argument, used to derive ioc
 259 *
 260**/
 261static void
 262mpt_fault_reset_work(struct work_struct *work)
 263{
 264        MPT_ADAPTER        *ioc =
 265            container_of(work, MPT_ADAPTER, fault_reset_work.work);
 266        u32                 ioc_raw_state;
 267        int                 rc;
 268        unsigned long         flags;
 269
 270        if (ioc->diagPending || !ioc->active)
 271                goto out;
 272
 273        ioc_raw_state = mpt_GetIocState(ioc, 0);
 274        if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
 275                printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n",
 276                       ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
 277                printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n",
 278                       ioc->name, __func__);
 279                rc = mpt_HardResetHandler(ioc, CAN_SLEEP);
 280                printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name,
 281                       __func__, (rc == 0) ? "success" : "failed");
 282                ioc_raw_state = mpt_GetIocState(ioc, 0);
 283                if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT)
 284                        printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after "
 285                            "reset (%04xh)\n", ioc->name, ioc_raw_state &
 286                            MPI_DOORBELL_DATA_MASK);
 287        }
 288
 289 out:
 290        /*
 291         * Take turns polling alternate controller
 292         */
 293        if (ioc->alt_ioc)
 294                ioc = ioc->alt_ioc;
 295
 296        /* rearm the timer */
 297        spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
 298        if (ioc->reset_work_q)
 299                queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
 300                        msecs_to_jiffies(MPT_POLLING_INTERVAL));
 301        spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
 302}
 303
 304
 305/*
 306 *  Process turbo (context) reply...
 307 */
 308static void
 309mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa)
 310{
 311        MPT_FRAME_HDR *mf = NULL;
 312        MPT_FRAME_HDR *mr = NULL;
 313        u16 req_idx = 0;
 314        u8 cb_idx;
 315
 316        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n",
 317                                ioc->name, pa));
 318
 319        switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) {
 320        case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT:
 321                req_idx = pa & 0x0000FFFF;
 322                cb_idx = (pa & 0x00FF0000) >> 16;
 323                mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 324                break;
 325        case MPI_CONTEXT_REPLY_TYPE_LAN:
 326                cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER);
 327                /*
 328                 *  Blind set of mf to NULL here was fatal
 329                 *  after lan_reply says "freeme"
 330                 *  Fix sort of combined with an optimization here;
 331                 *  added explicit check for case where lan_reply
 332                 *  was just returning 1 and doing nothing else.
 333                 *  For this case skip the callback, but set up
 334                 *  proper mf value first here:-)
 335                 */
 336                if ((pa & 0x58000000) == 0x58000000) {
 337                        req_idx = pa & 0x0000FFFF;
 338                        mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 339                        mpt_free_msg_frame(ioc, mf);
 340                        mb();
 341                        return;
 342                        break;
 343                }
 344                mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
 345                break;
 346        case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET:
 347                cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER);
 348                mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
 349                break;
 350        default:
 351                cb_idx = 0;
 352                BUG();
 353        }
 354
 355        /*  Check for (valid) IO callback!  */
 356        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
 357                MptCallbacks[cb_idx] == NULL) {
 358                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
 359                                __func__, ioc->name, cb_idx);
 360                goto out;
 361        }
 362
 363        if (MptCallbacks[cb_idx](ioc, mf, mr))
 364                mpt_free_msg_frame(ioc, mf);
 365 out:
 366        mb();
 367}
 368
 369static void
 370mpt_reply(MPT_ADAPTER *ioc, u32 pa)
 371{
 372        MPT_FRAME_HDR        *mf;
 373        MPT_FRAME_HDR        *mr;
 374        u16                 req_idx;
 375        u8                 cb_idx;
 376        int                 freeme;
 377
 378        u32 reply_dma_low;
 379        u16 ioc_stat;
 380
 381        /* non-TURBO reply!  Hmmm, something may be up...
 382         *  Newest turbo reply mechanism; get address
 383         *  via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)!
 384         */
 385
 386        /* Map DMA address of reply header to cpu address.
 387         * pa is 32 bits - but the dma address may be 32 or 64 bits
 388         * get offset based only only the low addresses
 389         */
 390
 391        reply_dma_low = (pa <<= 1);
 392        mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames +
 393                         (reply_dma_low - ioc->reply_frames_low_dma));
 394
 395        req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx);
 396        cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
 397        mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 398
 399        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n",
 400                        ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function));
 401        DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr);
 402
 403         /*  Check/log IOC log info
 404         */
 405        ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
 406        if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
 407                u32         log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
 408                if (ioc->bus_type == FC)
 409                        mpt_fc_log_info(ioc, log_info);
 410                else if (ioc->bus_type == SPI)
 411                        mpt_spi_log_info(ioc, log_info);
 412                else if (ioc->bus_type == SAS)
 413                        mpt_sas_log_info(ioc, log_info);
 414        }
 415
 416        if (ioc_stat & MPI_IOCSTATUS_MASK)
 417                mpt_iocstatus_info(ioc, (u32)ioc_stat, mf);
 418
 419        /*  Check for (valid) IO callback!  */
 420        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS ||
 421                MptCallbacks[cb_idx] == NULL) {
 422                printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n",
 423                                __func__, ioc->name, cb_idx);
 424                freeme = 0;
 425                goto out;
 426        }
 427
 428        freeme = MptCallbacks[cb_idx](ioc, mf, mr);
 429
 430 out:
 431        /*  Flush (non-TURBO) reply with a WRITE!  */
 432        CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
 433
 434        if (freeme)
 435                mpt_free_msg_frame(ioc, mf);
 436        mb();
 437}
 438
 439/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 440/**
 441 *        mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
 442 *        @irq: irq number (not used)
 443 *        @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
 444 *
 445 *        This routine is registered via the request_irq() kernel API call,
 446 *        and handles all interrupts generated from a specific MPT adapter
 447 *        (also referred to as a IO Controller or IOC).
 448 *        This routine must clear the interrupt from the adapter and does
 449 *        so by reading the reply FIFO.  Multiple replies may be processed
 450 *        per single call to this routine.
 451 *
 452 *        This routine handles register-level access of the adapter but
 453 *        dispatches (calls) a protocol-specific callback routine to handle
 454 *        the protocol-specific details of the MPT request completion.
 455 */
 456static irqreturn_t
 457mpt_interrupt(int irq, void *bus_id)
 458{
 459        MPT_ADAPTER *ioc = bus_id;
 460        u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
 461
 462        if (pa == 0xFFFFFFFF)
 463                return IRQ_NONE;
 464
 465        /*
 466         *  Drain the reply FIFO!
 467         */
 468        do {
 469                if (pa & MPI_ADDRESS_REPLY_A_BIT)
 470                        mpt_reply(ioc, pa);
 471                else
 472                        mpt_turbo_reply(ioc, pa);
 473                pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
 474        } while (pa != 0xFFFFFFFF);
 475
 476        return IRQ_HANDLED;
 477}
 478
 479/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 480/**
 481 *        mpt_base_reply - MPT base driver's callback routine
 482 *        @ioc: Pointer to MPT_ADAPTER structure
 483 *        @mf: Pointer to original MPT request frame
 484 *        @reply: Pointer to MPT reply frame (NULL if TurboReply)
 485 *
 486 *        MPT base driver's callback routine; all base driver
 487 *        "internal" request/reply processing is routed here.
 488 *        Currently used for EventNotification and EventAck handling.
 489 *
 490 *        Returns 1 indicating original alloc'd request frame ptr
 491 *        should be freed, or 0 if it shouldn't.
 492 */
 493static int
 494mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 495{
 496        int freereq = 1;
 497        u8 func;
 498
 499        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply() called\n", ioc->name));
 500#ifdef CONFIG_FUSION_LOGGING
 501        if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) &&
 502                        !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) {
 503                dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n",
 504                    ioc->name, mf));
 505                DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf);
 506        }
 507#endif
 508
 509        func = reply->u.hdr.Function;
 510        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, Function=%02Xh\n",
 511                        ioc->name, func));
 512
 513        if (func == MPI_FUNCTION_EVENT_NOTIFICATION) {
 514                EventNotificationReply_t *pEvReply = (EventNotificationReply_t *) reply;
 515                int evHandlers = 0;
 516                int results;
 517
 518                results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
 519                if (results != evHandlers) {
 520                        /* CHECKME! Any special handling needed here? */
 521                        devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
 522                                        ioc->name, evHandlers, results));
 523                }
 524
 525                /*
 526                 *        Hmmm...  It seems that EventNotificationReply is an exception
 527                 *        to the rule of one reply per request.
 528                 */
 529                if (pEvReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) {
 530                        freereq = 0;
 531                } else {
 532                        devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "EVENT_NOTIFICATION reply %p returns Request frame\n",
 533                                ioc->name, pEvReply));
 534                }
 535
 536#ifdef CONFIG_PROC_FS
 537//                LogEvent(ioc, pEvReply);
 538#endif
 539
 540        } else if (func == MPI_FUNCTION_EVENT_ACK) {
 541                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_base_reply, EventAck reply received\n",
 542                                ioc->name));
 543        } else if (func == MPI_FUNCTION_CONFIG) {
 544                CONFIGPARMS *pCfg;
 545                unsigned long flags;
 546
 547                dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "config_complete (mf=%p,mr=%p)\n",
 548                                ioc->name, mf, reply));
 549
 550                pCfg = * ((CONFIGPARMS **)((u8 *) mf + ioc->req_sz - sizeof(void *)));
 551
 552                if (pCfg) {
 553                        /* disable timer and remove from linked list */
 554                        del_timer(&pCfg->timer);
 555
 556                        spin_lock_irqsave(&ioc->FreeQlock, flags);
 557                        list_del(&pCfg->linkage);
 558                        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 559
 560                        /*
 561                         *        If IOC Status is SUCCESS, save the header
 562                         *        and set the status code to GOOD.
 563                         */
 564                        pCfg->status = MPT_CONFIG_ERROR;
 565                        if (reply) {
 566                                ConfigReply_t        *pReply = (ConfigReply_t *)reply;
 567                                u16                 status;
 568
 569                                status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 570                                dcprintk(ioc, printk(MYIOC_s_NOTE_FMT "  IOCStatus=%04xh, IOCLogInfo=%08xh\n",
 571                                     ioc->name, status, le32_to_cpu(pReply->IOCLogInfo)));
 572
 573                                pCfg->status = status;
 574                                if (status == MPI_IOCSTATUS_SUCCESS) {
 575                                        if ((pReply->Header.PageType &
 576                                            MPI_CONFIG_PAGETYPE_MASK) ==
 577                                            MPI_CONFIG_PAGETYPE_EXTENDED) {
 578                                                pCfg->cfghdr.ehdr->ExtPageLength =
 579                                                    le16_to_cpu(pReply->ExtPageLength);
 580                                                pCfg->cfghdr.ehdr->ExtPageType =
 581                                                    pReply->ExtPageType;
 582                                        }
 583                                        pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion;
 584
 585                                        /* If this is a regular header, save PageLength. */
 586                                        /* LMP Do this better so not using a reserved field! */
 587                                        pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength;
 588                                        pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber;
 589                                        pCfg->cfghdr.hdr->PageType = pReply->Header.PageType;
 590                                }
 591                        }
 592
 593                        /*
 594                         *        Wake up the original calling thread
 595                         */
 596                        pCfg->wait_done = 1;
 597                        wake_up(&mpt_waitq);
 598                }
 599        } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) {
 600                /* we should be always getting a reply frame */
 601                memcpy(ioc->persist_reply_frame, reply,
 602                    min(MPT_DEFAULT_FRAME_SIZE,
 603                    4*reply->u.reply.MsgLength));
 604                del_timer(&ioc->persist_timer);
 605                ioc->persist_wait_done = 1;
 606                wake_up(&mpt_waitq);
 607        } else {
 608                printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n",
 609                                ioc->name, func);
 610        }
 611
 612        /*
 613         *        Conditionally tell caller to free the original
 614         *        EventNotification/EventAck/unexpected request frame!
 615         */
 616        return freereq;
 617}
 618
 619/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 620/**
 621 *        mpt_register - Register protocol-specific main callback handler.
 622 *        @cbfunc: callback function pointer
 623 *        @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value)
 624 *
 625 *        This routine is called by a protocol-specific driver (SCSI host,
 626 *        LAN, SCSI target) to register its reply callback routine.  Each
 627 *        protocol-specific driver must do this before it will be able to
 628 *        use any IOC resources, such as obtaining request frames.
 629 *
 630 *        NOTES: The SCSI protocol driver currently calls this routine thrice
 631 *        in order to register separate callbacks; one for "normal" SCSI IO;
 632 *        one for MptScsiTaskMgmt requests; one for Scan/DV requests.
 633 *
 634 *        Returns u8 valued "handle" in the range (and S.O.D. order)
 635 *        {N,...,7,6,5,...,1} if successful.
 636 *        A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be
 637 *        considered an error by the caller.
 638 */
 639u8
 640mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass)
 641{
 642        u8 cb_idx;
 643        last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS;
 644
 645        /*
 646         *  Search for empty callback slot in this order: {N,...,7,6,5,...,1}
 647         *  (slot/handle 0 is reserved!)
 648         */
 649        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
 650                if (MptCallbacks[cb_idx] == NULL) {
 651                        MptCallbacks[cb_idx] = cbfunc;
 652                        MptDriverClass[cb_idx] = dclass;
 653                        MptEvHandlers[cb_idx] = NULL;
 654                        last_drv_idx = cb_idx;
 655                        break;
 656                }
 657        }
 658
 659        return last_drv_idx;
 660}
 661
 662/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 663/**
 664 *        mpt_deregister - Deregister a protocol drivers resources.
 665 *        @cb_idx: previously registered callback handle
 666 *
 667 *        Each protocol-specific driver should call this routine when its
 668 *        module is unloaded.
 669 */
 670void
 671mpt_deregister(u8 cb_idx)
 672{
 673        if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) {
 674                MptCallbacks[cb_idx] = NULL;
 675                MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
 676                MptEvHandlers[cb_idx] = NULL;
 677
 678                last_drv_idx++;
 679        }
 680}
 681
 682/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 683/**
 684 *        mpt_event_register - Register protocol-specific event callback handler.
 685 *        @cb_idx: previously registered (via mpt_register) callback handle
 686 *        @ev_cbfunc: callback function
 687 *
 688 *        This routine can be called by one or more protocol-specific drivers
 689 *        if/when they choose to be notified of MPT events.
 690 *
 691 *        Returns 0 for success.
 692 */
 693int
 694mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc)
 695{
 696        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 697                return -1;
 698
 699        MptEvHandlers[cb_idx] = ev_cbfunc;
 700        return 0;
 701}
 702
 703/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 704/**
 705 *        mpt_event_deregister - Deregister protocol-specific event callback handler
 706 *        @cb_idx: previously registered callback handle
 707 *
 708 *        Each protocol-specific driver should call this routine
 709 *        when it does not (or can no longer) handle events,
 710 *        or when its module is unloaded.
 711 */
 712void
 713mpt_event_deregister(u8 cb_idx)
 714{
 715        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 716                return;
 717
 718        MptEvHandlers[cb_idx] = NULL;
 719}
 720
 721/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 722/**
 723 *        mpt_reset_register - Register protocol-specific IOC reset handler.
 724 *        @cb_idx: previously registered (via mpt_register) callback handle
 725 *        @reset_func: reset function
 726 *
 727 *        This routine can be called by one or more protocol-specific drivers
 728 *        if/when they choose to be notified of IOC resets.
 729 *
 730 *        Returns 0 for success.
 731 */
 732int
 733mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func)
 734{
 735        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 736                return -1;
 737
 738        MptResetHandlers[cb_idx] = reset_func;
 739        return 0;
 740}
 741
 742/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 743/**
 744 *        mpt_reset_deregister - Deregister protocol-specific IOC reset handler.
 745 *        @cb_idx: previously registered callback handle
 746 *
 747 *        Each protocol-specific driver should call this routine
 748 *        when it does not (or can no longer) handle IOC reset handling,
 749 *        or when its module is unloaded.
 750 */
 751void
 752mpt_reset_deregister(u8 cb_idx)
 753{
 754        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 755                return;
 756
 757        MptResetHandlers[cb_idx] = NULL;
 758}
 759
 760/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 761/**
 762 *        mpt_device_driver_register - Register device driver hooks
 763 *        @dd_cbfunc: driver callbacks struct
 764 *        @cb_idx: MPT protocol driver index
 765 */
 766int
 767mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx)
 768{
 769        MPT_ADAPTER        *ioc;
 770        const struct pci_device_id *id;
 771
 772        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 773                return -EINVAL;
 774
 775        MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
 776
 777        /* call per pci device probe entry point */
 778        list_for_each_entry(ioc, &ioc_list, list) {
 779                id = ioc->pcidev->driver ?
 780                    ioc->pcidev->driver->id_table : NULL;
 781                if (dd_cbfunc->probe)
 782                        dd_cbfunc->probe(ioc->pcidev, id);
 783         }
 784
 785        return 0;
 786}
 787
 788/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 789/**
 790 *        mpt_device_driver_deregister - DeRegister device driver hooks
 791 *        @cb_idx: MPT protocol driver index
 792 */
 793void
 794mpt_device_driver_deregister(u8 cb_idx)
 795{
 796        struct mpt_pci_driver *dd_cbfunc;
 797        MPT_ADAPTER        *ioc;
 798
 799        if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS)
 800                return;
 801
 802        dd_cbfunc = MptDeviceDriverHandlers[cb_idx];
 803
 804        list_for_each_entry(ioc, &ioc_list, list) {
 805                if (dd_cbfunc->remove)
 806                        dd_cbfunc->remove(ioc->pcidev);
 807        }
 808
 809        MptDeviceDriverHandlers[cb_idx] = NULL;
 810}
 811
 812
 813/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 814/**
 815 *        mpt_get_msg_frame - Obtain an MPT request frame from the pool
 816 *        @cb_idx: Handle of registered MPT protocol driver
 817 *        @ioc: Pointer to MPT adapter structure
 818 *
 819 *        Obtain an MPT request frame from the pool (of 1024) that are
 820 *        allocated per MPT adapter.
 821 *
 822 *        Returns pointer to a MPT request frame or %NULL if none are available
 823 *        or IOC is not active.
 824 */
 825MPT_FRAME_HDR*
 826mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc)
 827{
 828        MPT_FRAME_HDR *mf;
 829        unsigned long flags;
 830        u16         req_idx;        /* Request index */
 831
 832        /* validate handle and ioc identifier */
 833
 834#ifdef MFCNT
 835        if (!ioc->active)
 836                printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame "
 837                    "returning NULL!\n", ioc->name);
 838#endif
 839
 840        /* If interrupts are not attached, do not return a request frame */
 841        if (!ioc->active)
 842                return NULL;
 843
 844        spin_lock_irqsave(&ioc->FreeQlock, flags);
 845        if (!list_empty(&ioc->FreeQ)) {
 846                int req_offset;
 847
 848                mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR,
 849                                u.frame.linkage.list);
 850                list_del(&mf->u.frame.linkage.list);
 851                mf->u.frame.linkage.arg1 = 0;
 852                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;        /* byte */
 853                req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 854                                                                /* u16! */
 855                req_idx = req_offset / ioc->req_sz;
 856                mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
 857                mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 858                /* Default, will be changed if necessary in SG generation */
 859                ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame;
 860#ifdef MFCNT
 861                ioc->mfcnt++;
 862#endif
 863        }
 864        else
 865                mf = NULL;
 866        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 867
 868#ifdef MFCNT
 869        if (mf == NULL)
 870                printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! "
 871                    "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt,
 872                    ioc->req_depth);
 873        mfcounter++;
 874        if (mfcounter == PRINT_MF_COUNT)
 875                printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name,
 876                    ioc->mfcnt, ioc->req_depth);
 877#endif
 878
 879        dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n",
 880            ioc->name, cb_idx, ioc->id, mf));
 881        return mf;
 882}
 883
 884/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 885/**
 886 *        mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC
 887 *        @cb_idx: Handle of registered MPT protocol driver
 888 *        @ioc: Pointer to MPT adapter structure
 889 *        @mf: Pointer to MPT request frame
 890 *
 891 *        This routine posts an MPT request frame to the request post FIFO of a
 892 *        specific MPT adapter.
 893 */
 894void
 895mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 896{
 897        u32 mf_dma_addr;
 898        int req_offset;
 899        u16         req_idx;        /* Request index */
 900
 901        /* ensure values are reset properly! */
 902        mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;                /* byte */
 903        req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 904                                                                /* u16! */
 905        req_idx = req_offset / ioc->req_sz;
 906        mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
 907        mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 908
 909        DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
 910
 911        mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
 912        dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d "
 913            "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx,
 914            ioc->RequestNB[req_idx]));
 915        CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 916}
 917
 918/**
 919 *        mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame
 920 *        @cb_idx: Handle of registered MPT protocol driver
 921 *        @ioc: Pointer to MPT adapter structure
 922 *        @mf: Pointer to MPT request frame
 923 *
 924 *        Send a protocol-specific MPT request frame to an IOC using
 925 *        hi-priority request queue.
 926 *
 927 *        This routine posts an MPT request frame to the request post FIFO of a
 928 *        specific MPT adapter.
 929 **/
 930void
 931mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 932{
 933        u32 mf_dma_addr;
 934        int req_offset;
 935        u16         req_idx;        /* Request index */
 936
 937        /* ensure values are reset properly! */
 938        mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
 939        req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 940        req_idx = req_offset / ioc->req_sz;
 941        mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
 942        mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 943
 944        DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf);
 945
 946        mf_dma_addr = (ioc->req_frames_low_dma + req_offset);
 947        dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n",
 948                ioc->name, mf_dma_addr, req_idx));
 949        CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr);
 950}
 951
 952/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 953/**
 954 *        mpt_free_msg_frame - Place MPT request frame back on FreeQ.
 955 *        @handle: Handle of registered MPT protocol driver
 956 *        @ioc: Pointer to MPT adapter structure
 957 *        @mf: Pointer to MPT request frame
 958 *
 959 *        This routine places a MPT request frame back on the MPT adapter's
 960 *        FreeQ.
 961 */
 962void
 963mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 964{
 965        unsigned long flags;
 966
 967        /*  Put Request back on FreeQ!  */
 968        spin_lock_irqsave(&ioc->FreeQlock, flags);
 969        mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */
 970        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
 971#ifdef MFCNT
 972        ioc->mfcnt--;
 973#endif
 974        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 975}
 976
 977/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 978/**
 979 *        mpt_add_sge - Place a simple SGE at address pAddr.
 980 *        @pAddr: virtual address for SGE
 981 *        @flagslength: SGE flags and data transfer length
 982 *        @dma_addr: Physical address
 983 *
 984 *        This routine places a MPT request frame back on the MPT adapter's
 985 *        FreeQ.
 986 */
 987void
 988mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
 989{
 990        if (sizeof(dma_addr_t) == sizeof(u64)) {
 991                SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
 992                u32 tmp = dma_addr & 0xFFFFFFFF;
 993
 994                pSge->FlagsLength = cpu_to_le32(flagslength);
 995                pSge->Address.Low = cpu_to_le32(tmp);
 996                tmp = (u32) ((u64)dma_addr >> 32);
 997                pSge->Address.High = cpu_to_le32(tmp);
 998
 999        } else {
1000                SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
1001                pSge->FlagsLength = cpu_to_le32(flagslength);
1002                pSge->Address = cpu_to_le32(dma_addr);
1003        }
1004}
1005
1006/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1007/**
1008 *        mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1009 *        @cb_idx: Handle of registered MPT protocol driver
1010 *        @ioc: Pointer to MPT adapter structure
1011 *        @reqBytes: Size of the request in bytes
1012 *        @req: Pointer to MPT request frame
1013 *        @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1014 *
1015 *        This routine is used exclusively to send MptScsiTaskMgmt
1016 *        requests since they are required to be sent via doorbell handshake.
1017 *
1018 *        NOTE: It is the callers responsibility to byte-swap fields in the
1019 *        request which are greater than 1 byte in size.
1020 *
1021 *        Returns 0 for success, non-zero for failure.
1022 */
1023int
1024mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1025{
1026        int        r = 0;
1027        u8        *req_as_bytes;
1028        int         ii;
1029
1030        /* State is known to be good upon entering
1031         * this function so issue the bus reset
1032         * request.
1033         */
1034
1035        /*
1036         * Emulate what mpt_put_msg_frame() does /wrt to sanity
1037         * setting cb_idx/req_idx.  But ONLY if this request
1038         * is in proper (pre-alloc'd) request buffer range...
1039         */
1040        ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1041        if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1042                MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1043                mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1044                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1045        }
1046
1047        /* Make sure there are no doorbells */
1048        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1049
1050        CHIPREG_WRITE32(&ioc->chip->Doorbell,
1051                        ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1052                         ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1053
1054        /* Wait for IOC doorbell int */
1055        if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1056                return ii;
1057        }
1058
1059        /* Read doorbell and check for active bit */
1060        if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1061                return -5;
1062
1063        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1064                ioc->name, ii));
1065
1066        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1067
1068        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1069                return -2;
1070        }
1071
1072        /* Send request via doorbell handshake */
1073        req_as_bytes = (u8 *) req;
1074        for (ii = 0; ii < reqBytes/4; ii++) {
1075                u32 word;
1076
1077                word = ((req_as_bytes[(ii*4) + 0] <<  0) |
1078                        (req_as_bytes[(ii*4) + 1] <<  8) |
1079                        (req_as_bytes[(ii*4) + 2] << 16) |
1080                        (req_as_bytes[(ii*4) + 3] << 24));
1081                CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1082                if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1083                        r = -3;
1084                        break;
1085                }
1086        }
1087
1088        if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1089                r = 0;
1090        else
1091                r = -4;
1092
1093        /* Make sure there are no doorbells */
1094        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1095
1096        return r;
1097}
1098
1099/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1100/**
1101 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1102 * @ioc: Pointer to MPT adapter structure
1103 * @access_control_value: define bits below
1104 * @sleepFlag: Specifies whether the process can sleep
1105 *
1106 * Provides mechanism for the host driver to control the IOC's
1107 * Host Page Buffer access.
1108 *
1109 * Access Control Value - bits[15:12]
1110 * 0h Reserved
1111 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1112 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1113 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1114 *
1115 * Returns 0 for success, non-zero for failure.
1116 */
1117
1118static int
1119mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1120{
1121        int         r = 0;
1122
1123        /* return if in use */
1124        if (CHIPREG_READ32(&ioc->chip->Doorbell)
1125            & MPI_DOORBELL_ACTIVE)
1126            return -1;
1127
1128        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1129
1130        CHIPREG_WRITE32(&ioc->chip->Doorbell,
1131                ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1132                 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1133                 (access_control_value<<12)));
1134
1135        /* Wait for IOC to clear Doorbell Status bit */
1136        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1137                return -2;
1138        }else
1139                return 0;
1140}
1141
1142/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1143/**
1144 *        mpt_host_page_alloc - allocate system memory for the fw
1145 *        @ioc: Pointer to pointer to IOC adapter
1146 *        @ioc_init: Pointer to ioc init config page
1147 *
1148 *        If we already allocated memory in past, then resend the same pointer.
1149 *        Returns 0 for success, non-zero for failure.
1150 */
1151static int
1152mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1153{
1154        char        *psge;
1155        int        flags_length;
1156        u32        host_page_buffer_sz=0;
1157
1158        if(!ioc->HostPageBuffer) {
1159
1160                host_page_buffer_sz =
1161                    le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1162
1163                if(!host_page_buffer_sz)
1164                        return 0; /* fw doesn't need any host buffers */
1165
1166                /* spin till we get enough memory */
1167                while(host_page_buffer_sz > 0) {
1168
1169                        if((ioc->HostPageBuffer = pci_alloc_consistent(
1170                            ioc->pcidev,
1171                            host_page_buffer_sz,
1172                            &ioc->HostPageBuffer_dma)) != NULL) {
1173
1174                                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1175                                    "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1176                                    ioc->name, ioc->HostPageBuffer,
1177                                    (u32)ioc->HostPageBuffer_dma,
1178                                    host_page_buffer_sz));
1179                                ioc->alloc_total += host_page_buffer_sz;
1180                                ioc->HostPageBuffer_sz = host_page_buffer_sz;
1181                                break;
1182                        }
1183
1184                        host_page_buffer_sz -= (4*1024);
1185                }
1186        }
1187
1188        if(!ioc->HostPageBuffer) {
1189                printk(MYIOC_s_ERR_FMT
1190                    "Failed to alloc memory for host_page_buffer!\n",
1191                    ioc->name);
1192                return -999;
1193        }
1194
1195        psge = (char *)&ioc_init->HostPageBufferSGE;
1196        flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1197            MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1198            MPI_SGE_FLAGS_32_BIT_ADDRESSING |
1199            MPI_SGE_FLAGS_HOST_TO_IOC |
1200            MPI_SGE_FLAGS_END_OF_BUFFER;
1201        if (sizeof(dma_addr_t) == sizeof(u64)) {
1202            flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING;
1203        }
1204        flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1205        flags_length |= ioc->HostPageBuffer_sz;
1206        mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1207        ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1208
1209return 0;
1210}
1211
1212/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1213/**
1214 *        mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1215 *        @iocid: IOC unique identifier (integer)
1216 *        @iocpp: Pointer to pointer to IOC adapter
1217 *
1218 *        Given a unique IOC identifier, set pointer to the associated MPT
1219 *        adapter structure.
1220 *
1221 *        Returns iocid and sets iocpp if iocid is found.
1222 *        Returns -1 if iocid is not found.
1223 */
1224int
1225mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1226{
1227        MPT_ADAPTER *ioc;
1228
1229        list_for_each_entry(ioc,&ioc_list,list) {
1230                if (ioc->id == iocid) {
1231                        *iocpp =ioc;
1232                        return iocid;
1233                }
1234        }
1235
1236        *iocpp = NULL;
1237        return -1;
1238}
1239
1240/**
1241 *        mpt_get_product_name - returns product string
1242 *        @vendor: pci vendor id
1243 *        @device: pci device id
1244 *        @revision: pci revision id
1245 *        @prod_name: string returned
1246 *
1247 *        Returns product string displayed when driver loads,
1248 *        in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1249 *
1250 **/
1251static void
1252mpt_get_product_name(u16 vendor, u16 device, u8 revision, char *prod_name)
1253{
1254        char *product_str = NULL;
1255
1256        if (vendor == PCI_VENDOR_ID_BROCADE) {
1257                switch (device)
1258                {
1259                case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1260                        switch (revision)
1261                        {
1262                        case 0x00:
1263                                product_str = "BRE040 A0";
1264                                break;
1265                        case 0x01:
1266                                product_str = "BRE040 A1";
1267                                break;
1268                        default:
1269                                product_str = "BRE040";
1270                                break;
1271                        }
1272                        break;
1273                }
1274                goto out;
1275        }
1276
1277        switch (device)
1278        {
1279        case MPI_MANUFACTPAGE_DEVICEID_FC909:
1280                product_str = "LSIFC909 B1";
1281                break;
1282        case MPI_MANUFACTPAGE_DEVICEID_FC919:
1283                product_str = "LSIFC919 B0";
1284                break;
1285        case MPI_MANUFACTPAGE_DEVICEID_FC929:
1286                product_str = "LSIFC929 B0";
1287                break;
1288        case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1289                if (revision < 0x80)
1290                        product_str = "LSIFC919X A0";
1291                else
1292                        product_str = "LSIFC919XL A1";
1293                break;
1294        case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1295                if (revision < 0x80)
1296                        product_str = "LSIFC929X A0";
1297                else
1298                        product_str = "LSIFC929XL A1";
1299                break;
1300        case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1301                product_str = "LSIFC939X A1";
1302                break;
1303        case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1304                product_str = "LSIFC949X A1";
1305                break;
1306        case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1307                switch (revision)
1308                {
1309                case 0x00:
1310                        product_str = "LSIFC949E A0";
1311                        break;
1312                case 0x01:
1313                        product_str = "LSIFC949E A1";
1314                        break;
1315                default:
1316                        product_str = "LSIFC949E";
1317                        break;
1318                }
1319                break;
1320        case MPI_MANUFACTPAGE_DEVID_53C1030:
1321                switch (revision)
1322                {
1323                case 0x00:
1324                        product_str = "LSI53C1030 A0";
1325                        break;
1326                case 0x01:
1327                        product_str = "LSI53C1030 B0";
1328                        break;
1329                case 0x03:
1330                        product_str = "LSI53C1030 B1";
1331                        break;
1332                case 0x07:
1333                        product_str = "LSI53C1030 B2";
1334                        break;
1335                case 0x08:
1336                        product_str = "LSI53C1030 C0";
1337                        break;
1338                case 0x80:
1339                        product_str = "LSI53C1030T A0";
1340                        break;
1341                case 0x83:
1342                        product_str = "LSI53C1030T A2";
1343                        break;
1344                case 0x87:
1345                        product_str = "LSI53C1030T A3";
1346                        break;
1347                case 0xc1:
1348                        product_str = "LSI53C1020A A1";
1349                        break;
1350                default:
1351                        product_str = "LSI53C1030";
1352                        break;
1353                }
1354                break;
1355        case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1356                switch (revision)
1357                {
1358                case 0x03:
1359                        product_str = "LSI53C1035 A2";
1360                        break;
1361                case 0x04:
1362                        product_str = "LSI53C1035 B0";
1363                        break;
1364                default:
1365                        product_str = "LSI53C1035";
1366                        break;
1367                }
1368                break;
1369        case MPI_MANUFACTPAGE_DEVID_SAS1064:
1370                switch (revision)
1371                {
1372                case 0x00:
1373                        product_str = "LSISAS1064 A1";
1374                        break;
1375                case 0x01:
1376                        product_str = "LSISAS1064 A2";
1377                        break;
1378                case 0x02:
1379                        product_str = "LSISAS1064 A3";
1380                        break;
1381                case 0x03:
1382                        product_str = "LSISAS1064 A4";
1383                        break;
1384                default:
1385                        product_str = "LSISAS1064";
1386                        break;
1387                }
1388                break;
1389        case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1390                switch (revision)
1391                {
1392                case 0x00:
1393                        product_str = "LSISAS1064E A0";
1394                        break;
1395                case 0x01:
1396                        product_str = "LSISAS1064E B0";
1397                        break;
1398                case 0x02:
1399                        product_str = "LSISAS1064E B1";
1400                        break;
1401                case 0x04:
1402                        product_str = "LSISAS1064E B2";
1403                        break;
1404                case 0x08:
1405                        product_str = "LSISAS1064E B3";
1406                        break;
1407                default:
1408                        product_str = "LSISAS1064E";
1409                        break;
1410                }
1411                break;
1412        case MPI_MANUFACTPAGE_DEVID_SAS1068:
1413                switch (revision)
1414                {
1415                case 0x00:
1416                        product_str = "LSISAS1068 A0";
1417                        break;
1418                case 0x01:
1419                        product_str = "LSISAS1068 B0";
1420                        break;
1421                case 0x02:
1422                        product_str = "LSISAS1068 B1";
1423                        break;
1424                default:
1425                        product_str = "LSISAS1068";
1426                        break;
1427                }
1428                break;
1429        case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1430                switch (revision)
1431                {
1432                case 0x00:
1433                        product_str = "LSISAS1068E A0";
1434                        break;
1435                case 0x01:
1436                        product_str = "LSISAS1068E B0";
1437                        break;
1438                case 0x02:
1439                        product_str = "LSISAS1068E B1";
1440                        break;
1441                case 0x04:
1442                        product_str = "LSISAS1068E B2";
1443                        break;
1444                case 0x08:
1445                        product_str = "LSISAS1068E B3";
1446                        break;
1447                default:
1448                        product_str = "LSISAS1068E";
1449                        break;
1450                }
1451                break;
1452        case MPI_MANUFACTPAGE_DEVID_SAS1078:
1453                switch (revision)
1454                {
1455                case 0x00:
1456                        product_str = "LSISAS1078 A0";
1457                        break;
1458                case 0x01:
1459                        product_str = "LSISAS1078 B0";
1460                        break;
1461                case 0x02:
1462                        product_str = "LSISAS1078 C0";
1463                        break;
1464                case 0x03:
1465                        product_str = "LSISAS1078 C1";
1466                        break;
1467                case 0x04:
1468                        product_str = "LSISAS1078 C2";
1469                        break;
1470                default:
1471                        product_str = "LSISAS1078";
1472                        break;
1473                }
1474                break;
1475        }
1476
1477 out:
1478        if (product_str)
1479                sprintf(prod_name, "%s", product_str);
1480}
1481
1482/**
1483 *        mpt_mapresources - map in memory mapped io
1484 *        @ioc: Pointer to pointer to IOC adapter
1485 *
1486 **/
1487static int
1488mpt_mapresources(MPT_ADAPTER *ioc)
1489{
1490        u8                __iomem *mem;
1491        int                 ii;
1492        unsigned long         mem_phys;
1493        unsigned long         port;
1494        u32                 msize;
1495        u32                 psize;
1496        u8                 revision;
1497        int                 r = -ENODEV;
1498        struct pci_dev *pdev;
1499
1500        pdev = ioc->pcidev;
1501        ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1502        if (pci_enable_device_mem(pdev)) {
1503                printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1504                    "failed\n", ioc->name);
1505                return r;
1506        }
1507        if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1508                printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1509                    "MEM failed\n", ioc->name);
1510                return r;
1511        }
1512
1513        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1514
1515        if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
1516            && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
1517                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1518                    ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1519                    ioc->name));
1520        } else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
1521            && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
1522                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1523                    ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1524                    ioc->name));
1525        } else {
1526                printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1527                    ioc->name, pci_name(pdev));
1528                pci_release_selected_regions(pdev, ioc->bars);
1529                return r;
1530        }
1531
1532        mem_phys = msize = 0;
1533        port = psize = 0;
1534        for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1535                if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1536                        if (psize)
1537                                continue;
1538                        /* Get I/O space! */
1539                        port = pci_resource_start(pdev, ii);
1540                        psize = pci_resource_len(pdev, ii);
1541                } else {
1542                        if (msize)
1543                                continue;
1544                        /* Get memmap */
1545                        mem_phys = pci_resource_start(pdev, ii);
1546                        msize = pci_resource_len(pdev, ii);
1547                }
1548        }
1549        ioc->mem_size = msize;
1550
1551        mem = NULL;
1552        /* Get logical ptr for PciMem0 space */
1553        /*mem = ioremap(mem_phys, msize);*/
1554        mem = ioremap(mem_phys, msize);
1555        if (mem == NULL) {
1556                printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1557                        " memory!\n", ioc->name);
1558                return -EINVAL;
1559        }
1560        ioc->memmap = mem;
1561        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
1562            ioc->name, mem, mem_phys));
1563
1564        ioc->mem_phys = mem_phys;
1565        ioc->chip = (SYSIF_REGS __iomem *)mem;
1566
1567        /* Save Port IO values in case we need to do downloadboot */
1568        ioc->pio_mem_phys = port;
1569        ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1570
1571        return 0;
1572}
1573
1574/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1575/**
1576 *        mpt_attach - Install a PCI intelligent MPT adapter.
1577 *        @pdev: Pointer to pci_dev structure
1578 *        @id: PCI device ID information
1579 *
1580 *        This routine performs all the steps necessary to bring the IOC of
1581 *        a MPT adapter to a OPERATIONAL state.  This includes registering
1582 *        memory regions, registering the interrupt, and allocating request
1583 *        and reply memory pools.
1584 *
1585 *        This routine also pre-fetches the LAN MAC address of a Fibre Channel
1586 *        MPT adapter.
1587 *
1588 *        Returns 0 for success, non-zero for failure.
1589 *
1590 *        TODO: Add support for polled controllers
1591 */
1592int
1593mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1594{
1595        MPT_ADAPTER        *ioc;
1596        u8                 cb_idx;
1597        int                 r = -ENODEV;
1598        u8                 revision;
1599        u8                 pcixcmd;
1600        static int         mpt_ids = 0;
1601#ifdef CONFIG_PROC_FS
1602        struct proc_dir_entry *dent, *ent;
1603#endif
1604
1605        ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1606        if (ioc == NULL) {
1607                printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1608                return -ENOMEM;
1609        }
1610
1611        ioc->id = mpt_ids++;
1612        sprintf(ioc->name, "ioc%d", ioc->id);
1613
1614        /*
1615         * set initial debug level
1616         * (refer to mptdebug.h)
1617         *
1618         */
1619        ioc->debug_level = mpt_debug_level;
1620        if (mpt_debug_level)
1621                printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1622
1623        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1624
1625        ioc->pcidev = pdev;
1626        if (mpt_mapresources(ioc)) {
1627                kfree(ioc);
1628                return r;
1629        }
1630
1631        ioc->alloc_total = sizeof(MPT_ADAPTER);
1632        ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;                /* avoid div by zero! */
1633        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1634
1635        ioc->pcidev = pdev;
1636        ioc->diagPending = 0;
1637        spin_lock_init(&ioc->diagLock);
1638        spin_lock_init(&ioc->initializing_hba_lock);
1639
1640        /* Initialize the event logging.
1641         */
1642        ioc->eventTypes = 0;        /* None */
1643        ioc->eventContext = 0;
1644        ioc->eventLogSize = 0;
1645        ioc->events = NULL;
1646
1647#ifdef MFCNT
1648        ioc->mfcnt = 0;
1649#endif
1650
1651        ioc->cached_fw = NULL;
1652
1653        /* Initilize SCSI Config Data structure
1654         */
1655        memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1656
1657        /* Initialize the running configQ head.
1658         */
1659        INIT_LIST_HEAD(&ioc->configQ);
1660
1661        /* Initialize the fc rport list head.
1662         */
1663        INIT_LIST_HEAD(&ioc->fc_rports);
1664
1665        /* Find lookup slot. */
1666        INIT_LIST_HEAD(&ioc->list);
1667
1668
1669        /* Initialize workqueue */
1670        INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1671        spin_lock_init(&ioc->fault_reset_work_lock);
1672
1673        snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
1674                 "mpt_poll_%d", ioc->id);
1675        ioc->reset_work_q =
1676                create_singlethread_workqueue(ioc->reset_work_q_name);
1677        if (!ioc->reset_work_q) {
1678                printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1679                    ioc->name);
1680                pci_release_selected_regions(pdev, ioc->bars);
1681                kfree(ioc);
1682                return -ENOMEM;
1683        }
1684
1685        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1686            ioc->name, &ioc->facts, &ioc->pfacts[0]));
1687
1688        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
1689        mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name);
1690
1691        switch (pdev->device)
1692        {
1693        case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1694        case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1695                ioc->errata_flag_1064 = 1;
1696        case MPI_MANUFACTPAGE_DEVICEID_FC909:
1697        case MPI_MANUFACTPAGE_DEVICEID_FC929:
1698        case MPI_MANUFACTPAGE_DEVICEID_FC919:
1699        case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1700                ioc->bus_type = FC;
1701                break;
1702
1703        case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1704                if (revision < XL_929) {
1705                        /* 929X Chip Fix. Set Split transactions level
1706                         * for PCIX. Set MOST bits to zero.
1707                         */
1708                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1709                        pcixcmd &= 0x8F;
1710                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1711                } else {
1712                        /* 929XL Chip Fix. Set MMRBC to 0x08.
1713                         */
1714                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1715                        pcixcmd |= 0x08;
1716                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1717                }
1718                ioc->bus_type = FC;
1719                break;
1720
1721        case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1722                /* 919X Chip Fix. Set Split transactions level
1723                 * for PCIX. Set MOST bits to zero.
1724                 */
1725                pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1726                pcixcmd &= 0x8F;
1727                pci_write_config_byte(pdev, 0x6a, pcixcmd);
1728                ioc->bus_type = FC;
1729                break;
1730
1731        case MPI_MANUFACTPAGE_DEVID_53C1030:
1732                /* 1030 Chip Fix. Disable Split transactions
1733                 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1734                 */
1735                if (revision < C0_1030) {
1736                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1737                        pcixcmd &= 0x8F;
1738                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1739                }
1740
1741        case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1742                ioc->bus_type = SPI;
1743                break;
1744
1745        case MPI_MANUFACTPAGE_DEVID_SAS1064:
1746        case MPI_MANUFACTPAGE_DEVID_SAS1068:
1747                ioc->errata_flag_1064 = 1;
1748
1749        case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1750        case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1751        case MPI_MANUFACTPAGE_DEVID_SAS1078:
1752                ioc->bus_type = SAS;
1753        }
1754
1755        if (mpt_msi_enable == -1) {
1756                /* Enable on SAS, disable on FC and SPI */
1757                if (ioc->bus_type == SAS)
1758                        ioc->msi_enable = 1;
1759                else
1760                        ioc->msi_enable = 0;
1761        } else
1762                /* follow flag: 0 - disable; 1 - enable */
1763                ioc->msi_enable = mpt_msi_enable;
1764
1765        if (ioc->errata_flag_1064)
1766                pci_disable_io_access(pdev);
1767
1768        spin_lock_init(&ioc->FreeQlock);
1769
1770        /* Disable all! */
1771        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1772        ioc->active = 0;
1773        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1774
1775        /* Set IOC ptr in the pcidev's driver data. */
1776        pci_set_drvdata(ioc->pcidev, ioc);
1777
1778        /* Set lookup ptr. */
1779        list_add_tail(&ioc->list, &ioc_list);
1780
1781        /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1782         */
1783        mpt_detect_bound_ports(ioc, pdev);
1784
1785        if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1786            CAN_SLEEP)) != 0){
1787                printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
1788                    ioc->name, r);
1789
1790                list_del(&ioc->list);
1791                if (ioc->alt_ioc)
1792                        ioc->alt_ioc->alt_ioc = NULL;
1793                iounmap(ioc->memmap);
1794                if (r != -5)
1795                        pci_release_selected_regions(pdev, ioc->bars);
1796
1797                destroy_workqueue(ioc->reset_work_q);
1798                ioc->reset_work_q = NULL;
1799
1800                kfree(ioc);
1801                pci_set_drvdata(pdev, NULL);
1802                return r;
1803        }
1804
1805        /* call per device driver probe entry point */
1806        for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1807                if(MptDeviceDriverHandlers[cb_idx] &&
1808                  MptDeviceDriverHandlers[cb_idx]->probe) {
1809                        MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
1810                }
1811        }
1812
1813#ifdef CONFIG_PROC_FS
1814        /*
1815         *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
1816         */
1817        dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
1818        if (dent) {
1819                ent = create_proc_entry("info", S_IFREG|S_IRUGO, dent);
1820                if (ent) {
1821                        ent->read_proc = procmpt_iocinfo_read;
1822                        ent->data = ioc;
1823                }
1824                ent = create_proc_entry("summary", S_IFREG|S_IRUGO, dent);
1825                if (ent) {
1826                        ent->read_proc = procmpt_summary_read;
1827                        ent->data = ioc;
1828                }
1829        }
1830#endif
1831
1832        if (!ioc->alt_ioc)
1833                queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
1834                        msecs_to_jiffies(MPT_POLLING_INTERVAL));
1835
1836        return 0;
1837}
1838
1839/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1840/**
1841 *        mpt_detach - Remove a PCI intelligent MPT adapter.
1842 *        @pdev: Pointer to pci_dev structure
1843 */
1844
1845void
1846mpt_detach(struct pci_dev *pdev)
1847{
1848        MPT_ADAPTER         *ioc = pci_get_drvdata(pdev);
1849        char pname[32];
1850        u8 cb_idx;
1851        unsigned long flags;
1852        struct workqueue_struct *wq;
1853
1854        /*
1855         * Stop polling ioc for fault condition
1856         */
1857        spin_lock_irqsave(&ioc->fault_reset_work_lock, flags);
1858        wq = ioc->reset_work_q;
1859        ioc->reset_work_q = NULL;
1860        spin_unlock_irqrestore(&ioc->fault_reset_work_lock, flags);
1861        cancel_delayed_work(&ioc->fault_reset_work);
1862        destroy_workqueue(wq);
1863
1864
1865        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
1866        remove_proc_entry(pname, NULL);
1867        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
1868        remove_proc_entry(pname, NULL);
1869        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
1870        remove_proc_entry(pname, NULL);
1871
1872        /* call per device driver remove entry point */
1873        for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
1874                if(MptDeviceDriverHandlers[cb_idx] &&
1875                  MptDeviceDriverHandlers[cb_idx]->remove) {
1876                        MptDeviceDriverHandlers[cb_idx]->remove(pdev);
1877                }
1878        }
1879
1880        /* Disable interrupts! */
1881        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1882
1883        ioc->active = 0;
1884        synchronize_irq(pdev->irq);
1885
1886        /* Clear any lingering interrupt */
1887        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1888
1889        CHIPREG_READ32(&ioc->chip->IntStatus);
1890
1891        mpt_adapter_dispose(ioc);
1892
1893        pci_set_drvdata(pdev, NULL);
1894}
1895
1896/**************************************************************************
1897 * Power Management
1898 */
1899#ifdef CONFIG_PM
1900/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1901/**
1902 *        mpt_suspend - Fusion MPT base driver suspend routine.
1903 *        @pdev: Pointer to pci_dev structure
1904 *        @state: new state to enter
1905 */
1906int
1907mpt_suspend(struct pci_dev *pdev, pm_message_t state)
1908{
1909        u32 device_state;
1910        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1911
1912        device_state = pci_choose_state(pdev, state);
1913        printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
1914            "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1915            device_state);
1916
1917        /* put ioc into READY_STATE */
1918        if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
1919                printk(MYIOC_s_ERR_FMT
1920                "pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
1921        }
1922
1923        /* disable interrupts */
1924        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1925        ioc->active = 0;
1926
1927        /* Clear any lingering interrupt */
1928        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1929
1930        free_irq(ioc->pci_irq, ioc);
1931        if (ioc->msi_enable)
1932                pci_disable_msi(ioc->pcidev);
1933        ioc->pci_irq = -1;
1934        pci_save_state(pdev);
1935        pci_disable_device(pdev);
1936        pci_release_selected_regions(pdev, ioc->bars);
1937        pci_set_power_state(pdev, device_state);
1938        return 0;
1939}
1940
1941/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1942/**
1943 *        mpt_resume - Fusion MPT base driver resume routine.
1944 *        @pdev: Pointer to pci_dev structure
1945 */
1946int
1947mpt_resume(struct pci_dev *pdev)
1948{
1949        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1950        u32 device_state = pdev->current_state;
1951        int recovery_state;
1952        int err;
1953
1954        printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
1955            "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
1956            device_state);
1957
1958        pci_set_power_state(pdev, PCI_D0);
1959        pci_enable_wake(pdev, PCI_D0, 0);
1960        pci_restore_state(pdev);
1961        ioc->pcidev = pdev;
1962        err = mpt_mapresources(ioc);
1963        if (err)
1964                return err;
1965
1966        printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
1967            ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
1968            CHIPREG_READ32(&ioc->chip->Doorbell));
1969
1970        /*
1971         * Errata workaround for SAS pci express:
1972         * Upon returning to the D0 state, the contents of the doorbell will be
1973         * stale data, and this will incorrectly signal to the host driver that
1974         * the firmware is ready to process mpt commands.   The workaround is
1975         * to issue a diagnostic reset.
1976         */
1977        if (ioc->bus_type == SAS && (pdev->device ==
1978            MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
1979            MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
1980                if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
1981                        printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
1982                            ioc->name);
1983                        goto out;
1984                }
1985        }
1986
1987        /* bring ioc to operational state */
1988        printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
1989        recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
1990                                                 CAN_SLEEP);
1991        if (recovery_state != 0)
1992                printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
1993                    "error:[%x]\n", ioc->name, recovery_state);
1994        else
1995                printk(MYIOC_s_INFO_FMT
1996                    "pci-resume: success\n", ioc->name);
1997 out:
1998        return 0;
1999
2000}
2001#endif
2002
2003static int
2004mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2005{
2006        if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2007             ioc->bus_type != SPI) ||
2008            (MptDriverClass[index] == MPTFC_DRIVER &&
2009             ioc->bus_type != FC) ||
2010            (MptDriverClass[index] == MPTSAS_DRIVER &&
2011             ioc->bus_type != SAS))
2012                /* make sure we only call the relevant reset handler
2013                 * for the bus */
2014                return 0;
2015        return (MptResetHandlers[index])(ioc, reset_phase);
2016}
2017
2018/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2019/**
2020 *        mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2021 *        @ioc: Pointer to MPT adapter structure
2022 *        @reason: Event word / reason
2023 *        @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2024 *
2025 *        This routine performs all the steps necessary to bring the IOC
2026 *        to a OPERATIONAL state.
2027 *
2028 *        This routine also pre-fetches the LAN MAC address of a Fibre Channel
2029 *        MPT adapter.
2030 *
2031 *        Returns:
2032 *                 0 for success
2033 *                -1 if failed to get board READY
2034 *                -2 if READY but IOCFacts Failed
2035 *                -3 if READY but PrimeIOCFifos Failed
2036 *                -4 if READY but IOCInit Failed
2037 *                -5 if failed to enable_device and/or request_selected_regions
2038 *                -6 if failed to upload firmware
2039 */
2040static int
2041mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2042{
2043        int         hard_reset_done = 0;
2044        int         alt_ioc_ready = 0;
2045        int         hard;
2046        int         rc=0;
2047        int         ii;
2048        u8         cb_idx;
2049        int         handlers;
2050        int         ret = 0;
2051        int         reset_alt_ioc_active = 0;
2052        int         irq_allocated = 0;
2053        u8        *a;
2054
2055        printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2056            reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2057
2058        /* Disable reply interrupts (also blocks FreeQ) */
2059        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2060        ioc->active = 0;
2061
2062        if (ioc->alt_ioc) {
2063                if (ioc->alt_ioc->active)
2064                        reset_alt_ioc_active = 1;
2065
2066                /* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
2067                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
2068                ioc->alt_ioc->active = 0;
2069        }
2070
2071        hard = 1;
2072        if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2073                hard = 0;
2074
2075        if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2076                if (hard_reset_done == -4) {
2077                        printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2078                            ioc->name);
2079
2080                        if (reset_alt_ioc_active && ioc->alt_ioc) {
2081                                /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2082                                dprintk(ioc, printk(MYIOC_s_INFO_FMT
2083                                    "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2084                                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2085                                ioc->alt_ioc->active = 1;
2086                        }
2087
2088                } else {
2089                        printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name);
2090                }
2091                return -1;
2092        }
2093
2094        /* hard_reset_done = 0 if a soft reset was performed
2095         * and 1 if a hard reset was performed.
2096         */
2097        if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2098                if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2099                        alt_ioc_ready = 1;
2100                else
2101                        printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name);
2102        }
2103
2104        for (ii=0; ii<5; ii++) {
2105                /* Get IOC facts! Allow 5 retries */
2106                if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2107                        break;
2108        }
2109
2110
2111        if (ii == 5) {
2112                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2113                    "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2114                ret = -2;
2115        } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2116                MptDisplayIocCapabilities(ioc);
2117        }
2118
2119        if (alt_ioc_ready) {
2120                if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2121                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2122                            "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
2123                        /* Retry - alt IOC was initialized once
2124                         */
2125                        rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2126                }
2127                if (rc) {
2128                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2129                            "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2130                        alt_ioc_ready = 0;
2131                        reset_alt_ioc_active = 0;
2132                } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2133                        MptDisplayIocCapabilities(ioc->alt_ioc);
2134                }
2135        }
2136
2137        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2138            (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2139                pci_release_selected_regions(ioc->pcidev, ioc->bars);
2140                ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2141                    IORESOURCE_IO);
2142                if (pci_enable_device(ioc->pcidev))
2143                        return -5;
2144                if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2145                        "mpt"))
2146                        return -5;
2147        }
2148
2149        /*
2150         * Device is reset now. It must have de-asserted the interrupt line
2151         * (if it was asserted) and it should be safe to register for the
2152         * interrupt now.
2153         */
2154        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2155                ioc->pci_irq = -1;
2156                if (ioc->pcidev->irq) {
2157                        if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2158                                printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2159                                    ioc->name);
2160                        else
2161                                ioc->msi_enable = 0;
2162                        rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2163                            IRQF_SHARED, ioc->name, ioc);
2164                        if (rc < 0) {
2165                                printk(MYIOC_s_ERR_FMT "Unable to allocate "
2166                                    "interrupt %d!\n", ioc->name, ioc->pcidev->irq);
2167                                if (ioc->msi_enable)
2168                                        pci_disable_msi(ioc->pcidev);
2169                                return -EBUSY;
2170                        }
2171                        irq_allocated = 1;
2172                        ioc->pci_irq = ioc->pcidev->irq;
2173                        pci_set_master(ioc->pcidev);                /* ?? */
2174                        dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt "
2175                            "%d\n", ioc->name, ioc->pcidev->irq));
2176                }
2177        }
2178
2179        /* Prime reply & request queues!
2180         * (mucho alloc's) Must be done prior to
2181         * init as upper addresses are needed for init.
2182         * If fails, continue with alt-ioc processing
2183         */
2184        if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2185                ret = -3;
2186
2187        /* May need to check/upload firmware & data here!
2188         * If fails, continue with alt-ioc processing
2189         */
2190        if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2191                ret = -4;
2192// NEW!
2193        if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2194                printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n",
2195                    ioc->alt_ioc->name, rc);
2196                alt_ioc_ready = 0;
2197                reset_alt_ioc_active = 0;
2198        }
2199
2200        if (alt_ioc_ready) {
2201                if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2202                        alt_ioc_ready = 0;
2203                        reset_alt_ioc_active = 0;
2204                        printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n",
2205                            ioc->alt_ioc->name, rc);
2206                }
2207        }
2208
2209        if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2210                if (ioc->upload_fw) {
2211                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2212                            "firmware upload required!\n", ioc->name));
2213
2214                        /* Controller is not operational, cannot do upload
2215                         */
2216                        if (ret == 0) {
2217                                rc = mpt_do_upload(ioc, sleepFlag);
2218                                if (rc == 0) {
2219                                        if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2220                                                /*
2221                                                 * Maintain only one pointer to FW memory
2222                                                 * so there will not be two attempt to
2223                                                 * downloadboot onboard dual function
2224                                                 * chips (mpt_adapter_disable,
2225                                                 * mpt_diag_reset)
2226                                                 */
2227                                                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2228                                                    "mpt_upload:  alt_%s has cached_fw=%p \n",
2229                                                    ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2230                                                ioc->cached_fw = NULL;
2231                                        }
2232                                } else {
2233                                        printk(MYIOC_s_WARN_FMT
2234                                            "firmware upload failure!\n", ioc->name);
2235                                        ret = -6;
2236                                }
2237                        }
2238                }
2239        }
2240
2241        if (ret == 0) {
2242                /* Enable! (reply interrupt) */
2243                CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2244                ioc->active = 1;
2245        }
2246
2247        if (reset_alt_ioc_active && ioc->alt_ioc) {
2248                /* (re)Enable alt-IOC! (reply interrupt) */
2249                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n",
2250                    ioc->alt_ioc->name));
2251                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2252                ioc->alt_ioc->active = 1;
2253        }
2254
2255        /*  Enable MPT base driver management of EventNotification
2256         *  and EventAck handling.
2257         */
2258        if ((ret == 0) && (!ioc->facts.EventState))
2259                (void) SendEventNotification(ioc, 1);        /* 1=Enable EventNotification */
2260
2261        if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2262                (void) SendEventNotification(ioc->alt_ioc, 1);        /* 1=Enable EventNotification */
2263
2264        /*        Add additional "reason" check before call to GetLanConfigPages
2265         *        (combined with GetIoUnitPage2 call).  This prevents a somewhat
2266         *        recursive scenario; GetLanConfigPages times out, timer expired
2267         *        routine calls HardResetHandler, which calls into here again,
2268         *        and we try GetLanConfigPages again...
2269         */
2270        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2271
2272                /*
2273                 * Initalize link list for inactive raid volumes.
2274                 */
2275                mutex_init(&ioc->raid_data.inactive_list_mutex);
2276                INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2277
2278                if (ioc->bus_type == SAS) {
2279
2280                        /* clear persistency table */
2281                        if(ioc->facts.IOCExceptions &
2282                            MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2283                                ret = mptbase_sas_persist_operation(ioc,
2284                                    MPI_SAS_OP_CLEAR_NOT_PRESENT);
2285                                if(ret != 0)
2286                                        goto out;
2287                        }
2288
2289                        /* Find IM volumes
2290                         */
2291                        mpt_findImVolumes(ioc);
2292
2293                } else if (ioc->bus_type == FC) {
2294                        if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
2295                            (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2296                                /*
2297                                 *  Pre-fetch the ports LAN MAC address!
2298                                 *  (LANPage1_t stuff)
2299                                 */
2300                                (void) GetLanConfigPages(ioc);
2301                                a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2302                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2303                                    "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2304                                    ioc->name, a[5], a[4], a[3], a[2], a[1], a[0]));
2305
2306                        }
2307                } else {
2308                        /* Get NVRAM and adapter maximums from SPP 0 and 2
2309                         */
2310                        mpt_GetScsiPortSettings(ioc, 0);
2311
2312                        /* Get version and length of SDP 1
2313                         */
2314                        mpt_readScsiDevicePageHeaders(ioc, 0);
2315
2316                        /* Find IM volumes
2317                         */
2318                        if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2319                                mpt_findImVolumes(ioc);
2320
2321                        /* Check, and possibly reset, the coalescing value
2322                         */
2323                        mpt_read_ioc_pg_1(ioc);
2324
2325                        mpt_read_ioc_pg_4(ioc);
2326                }
2327
2328                GetIoUnitPage2(ioc);
2329                mpt_get_manufacturing_pg_0(ioc);
2330        }
2331
2332        /*
2333         * Call each currently registered protocol IOC reset handler
2334         * with post-reset indication.
2335         * NOTE: If we're doing _IOC_BRINGUP, there can be no
2336         * MptResetHandlers[] registered yet.
2337         */
2338        if (hard_reset_done) {
2339                rc = handlers = 0;
2340                for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
2341                        if ((ret == 0) && MptResetHandlers[cb_idx]) {
2342                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2343                                    "Calling IOC post_reset handler #%d\n",
2344                                    ioc->name, cb_idx));
2345                                rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
2346                                handlers++;
2347                        }
2348
2349                        if (alt_ioc_ready && MptResetHandlers[cb_idx]) {
2350                                drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2351                                    "Calling IOC post_reset handler #%d\n",
2352                                    ioc->alt_ioc->name, cb_idx));
2353                                rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET);
2354                                handlers++;
2355                        }
2356                }
2357                /* FIXME?  Examine results here? */
2358        }
2359
2360 out:
2361        if ((ret != 0) && irq_allocated) {
2362                free_irq(ioc->pci_irq, ioc);
2363                if (ioc->msi_enable)
2364                        pci_disable_msi(ioc->pcidev);
2365        }
2366        return ret;
2367}
2368
2369/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2370/**
2371 *        mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2372 *        @ioc: Pointer to MPT adapter structure
2373 *        @pdev: Pointer to (struct pci_dev) structure
2374 *
2375 *        Search for PCI bus/dev_function which matches
2376 *        PCI bus/dev_function (+/-1) for newly discovered 929,
2377 *        929X, 1030 or 1035.
2378 *
2379 *        If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2380 *        using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2381 */
2382static void
2383mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2384{
2385        struct pci_dev *peer=NULL;
2386        unsigned int slot = PCI_SLOT(pdev->devfn);
2387        unsigned int func = PCI_FUNC(pdev->devfn);
2388        MPT_ADAPTER *ioc_srch;
2389
2390        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2391            " searching for devfn match on %x or %x\n",
2392            ioc->name, pci_name(pdev), pdev->bus->number,
2393            pdev->devfn, func-1, func+1));
2394
2395        peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2396        if (!peer) {
2397                peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2398                if (!peer)
2399                        return;
2400        }
2401
2402        list_for_each_entry(ioc_srch, &ioc_list, list) {
2403                struct pci_dev *_pcidev = ioc_srch->pcidev;
2404                if (_pcidev == peer) {
2405                        /* Paranoia checks */
2406                        if (ioc->alt_ioc != NULL) {
2407                                printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2408                                        ioc->name, ioc->alt_ioc->name);
2409                                break;
2410                        } else if (ioc_srch->alt_ioc != NULL) {
2411                                printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n",
2412                                        ioc_srch->name, ioc_srch->alt_ioc->name);
2413                                break;
2414                        }
2415                        dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n",
2416                                ioc->name, ioc_srch->name));
2417                        ioc_srch->alt_ioc = ioc;
2418                        ioc->alt_ioc = ioc_srch;
2419                }
2420        }
2421        pci_dev_put(peer);
2422}
2423
2424/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2425/**
2426 *        mpt_adapter_disable - Disable misbehaving MPT adapter.
2427 *        @ioc: Pointer to MPT adapter structure
2428 */
2429static void
2430mpt_adapter_disable(MPT_ADAPTER *ioc)
2431{
2432        int sz;
2433        int ret;
2434
2435        if (ioc->cached_fw != NULL) {
2436                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: Pushing FW onto "
2437                    "adapter\n", __func__, ioc->name));
2438                if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2439                    ioc->cached_fw, CAN_SLEEP)) < 0) {
2440                        printk(MYIOC_s_WARN_FMT
2441                            ": firmware downloadboot failure (%d)!\n",
2442                            ioc->name, ret);
2443                }
2444        }
2445
2446        /* Disable adapter interrupts! */
2447        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2448        ioc->active = 0;
2449        /* Clear any lingering interrupt */
2450        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2451
2452        if (ioc->alloc != NULL) {
2453                sz = ioc->alloc_sz;
2454                dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free  @ %p, sz=%d bytes\n",
2455                    ioc->name, ioc->alloc, ioc->alloc_sz));
2456                pci_free_consistent(ioc->pcidev, sz,
2457                                ioc->alloc, ioc->alloc_dma);
2458                ioc->reply_frames = NULL;
2459                ioc->req_frames = NULL;
2460                ioc->alloc = NULL;
2461                ioc->alloc_total -= sz;
2462        }
2463
2464        if (ioc->sense_buf_pool != NULL) {
2465                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2466                pci_free_consistent(ioc->pcidev, sz,
2467                                ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2468                ioc->sense_buf_pool = NULL;
2469                ioc->alloc_total -= sz;
2470        }
2471
2472        if (ioc->events != NULL){
2473                sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2474                kfree(ioc->events);
2475                ioc->events = NULL;
2476                ioc->alloc_total -= sz;
2477        }
2478
2479        mpt_free_fw_memory(ioc);
2480
2481        kfree(ioc->spi_data.nvram);
2482        mpt_inactive_raid_list_free(ioc);
2483        kfree(ioc->raid_data.pIocPg2);
2484        kfree(ioc->raid_data.pIocPg3);
2485        ioc->spi_data.nvram = NULL;
2486        ioc->raid_data.pIocPg3 = NULL;
2487
2488        if (ioc->spi_data.pIocPg4 != NULL) {
2489                sz = ioc->spi_data.IocPg4Sz;
2490                pci_free_consistent(ioc->pcidev, sz,
2491                        ioc->spi_data.pIocPg4,
2492                        ioc->spi_data.IocPg4_dma);
2493                ioc->spi_data.pIocPg4 = NULL;
2494                ioc->alloc_total -= sz;
2495        }
2496
2497        if (ioc->ReqToChain != NULL) {
2498                kfree(ioc->ReqToChain);
2499                kfree(ioc->RequestNB);
2500                ioc->ReqToChain = NULL;
2501        }
2502
2503        kfree(ioc->ChainToChain);
2504        ioc->ChainToChain = NULL;
2505
2506        if (ioc->HostPageBuffer != NULL) {
2507                if((ret = mpt_host_page_access_control(ioc,
2508                    MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2509                        printk(MYIOC_s_ERR_FMT
2510                           "host page buffers free failed (%d)!\n",
2511                            ioc->name, ret);
2512                }
2513                dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free  @ %p, sz=%d bytes\n",
2514                         ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz));
2515                pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2516                    ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2517                ioc->HostPageBuffer = NULL;
2518                ioc->HostPageBuffer_sz = 0;
2519                ioc->alloc_total -= ioc->HostPageBuffer_sz;
2520        }
2521}
2522
2523/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2524/**
2525 *        mpt_adapter_dispose - Free all resources associated with an MPT adapter
2526 *        @ioc: Pointer to MPT adapter structure
2527 *
2528 *        This routine unregisters h/w resources and frees all alloc'd memory
2529 *        associated with a MPT adapter structure.
2530 */
2531static void
2532mpt_adapter_dispose(MPT_ADAPTER *ioc)
2533{
2534        int sz_first, sz_last;
2535
2536        if (ioc == NULL)
2537                return;
2538
2539        sz_first = ioc->alloc_total;
2540
2541        mpt_adapter_disable(ioc);
2542
2543        if (ioc->pci_irq != -1) {
2544                free_irq(ioc->pci_irq, ioc);
2545                if (ioc->msi_enable)
2546                        pci_disable_msi(ioc->pcidev);
2547                ioc->pci_irq = -1;
2548        }
2549
2550        if (ioc->memmap != NULL) {
2551                iounmap(ioc->memmap);
2552                ioc->memmap = NULL;
2553        }
2554
2555        pci_disable_device(ioc->pcidev);
2556        pci_release_selected_regions(ioc->pcidev, ioc->bars);
2557
2558#if defined(CONFIG_MTRR) && 0
2559        if (ioc->mtrr_reg > 0) {
2560                mtrr_del(ioc->mtrr_reg, 0, 0);
2561                dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name));
2562        }
2563#endif
2564
2565        /*  Zap the adapter lookup ptr!  */
2566        list_del(&ioc->list);
2567
2568        sz_last = ioc->alloc_total;
2569        dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2570            ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2571
2572        if (ioc->alt_ioc)
2573                ioc->alt_ioc->alt_ioc = NULL;
2574
2575        kfree(ioc);
2576}
2577
2578/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2579/**
2580 *        MptDisplayIocCapabilities - Disply IOC's capabilities.
2581 *        @ioc: Pointer to MPT adapter structure
2582 */
2583static void
2584MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2585{
2586        int i = 0;
2587
2588        printk(KERN_INFO "%s: ", ioc->name);
2589        if (ioc->prod_name)
2590                printk("%s: ", ioc->prod_name);
2591        printk("Capabilities={");
2592
2593        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2594                printk("Initiator");
2595                i++;
2596        }
2597
2598        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2599                printk("%sTarget", i ? "," : "");
2600                i++;
2601        }
2602
2603        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2604                printk("%sLAN", i ? "," : "");
2605                i++;
2606        }
2607
2608#if 0
2609        /*
2610         *  This would probably evoke more questions than it's worth
2611         */
2612        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2613                printk("%sLogBusAddr", i ? "," : "");
2614                i++;
2615        }
2616#endif
2617
2618        printk("}\n");
2619}
2620
2621/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2622/**
2623 *        MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2624 *        @ioc: Pointer to MPT_ADAPTER structure
2625 *        @force: Force hard KickStart of IOC
2626 *        @sleepFlag: Specifies whether the process can sleep
2627 *
2628 *        Returns:
2629 *                 1 - DIAG reset and READY
2630 *                 0 - READY initially OR soft reset and READY
2631 *                -1 - Any failure on KickStart
2632 *                -2 - Msg Unit Reset Failed
2633 *                -3 - IO Unit Reset Failed
2634 *                -4 - IOC owned by a PEER
2635 */
2636static int
2637MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2638{
2639        u32         ioc_state;
2640        int         statefault = 0;
2641        int         cntdn;
2642        int         hard_reset_done = 0;
2643        int         r;
2644        int         ii;
2645        int         whoinit;
2646
2647        /* Get current [raw] IOC state  */
2648        ioc_state = mpt_GetIocState(ioc, 0);
2649        dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2650
2651        /*
2652         *        Check to see if IOC got left/stuck in doorbell handshake
2653         *        grip of death.  If so, hard reset the IOC.
2654         */
2655        if (ioc_state & MPI_DOORBELL_ACTIVE) {
2656                statefault = 1;
2657                printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2658                                ioc->name);
2659        }
2660
2661        /* Is it already READY? */
2662        if (!statefault && (ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)
2663                return 0;
2664
2665        /*
2666         *        Check to see if IOC is in FAULT state.
2667         */
2668        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2669                statefault = 2;
2670                printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2671                    ioc->name);
2672                printk(MYIOC_s_WARN_FMT "           FAULT code = %04xh\n",
2673                    ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2674        }
2675
2676        /*
2677         *        Hmmm...  Did it get left operational?
2678         */
2679        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2680                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2681                                ioc->name));
2682
2683                /* Check WhoInit.
2684                 * If PCI Peer, exit.
2685                 * Else, if no fault conditions are present, issue a MessageUnitReset
2686                 * Else, fall through to KickStart case
2687                 */
2688                whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2689                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2690                        "whoinit 0x%x statefault %d force %d\n",
2691                        ioc->name, whoinit, statefault, force));
2692                if (whoinit == MPI_WHOINIT_PCI_PEER)
2693                        return -4;
2694                else {
2695                        if ((statefault == 0 ) && (force == 0)) {
2696                                if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2697                                        return 0;
2698                        }
2699                        statefault = 3;
2700                }
2701        }
2702
2703        hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2704        if (hard_reset_done < 0)
2705                return -1;
2706
2707        /*
2708         *  Loop here waiting for IOC to come READY.
2709         */
2710        ii = 0;
2711        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;        /* 5 seconds */
2712
2713        while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2714                if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2715                        /*
2716                         *  BIOS or previous driver load left IOC in OP state.
2717                         *  Reset messaging FIFOs.
2718                         */
2719                        if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
2720                                printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
2721                                return -2;
2722                        }
2723                } else if (ioc_state == MPI_IOC_STATE_RESET) {
2724                        /*
2725                         *  Something is wrong.  Try to get IOC back
2726                         *  to a known state.
2727                         */
2728                        if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
2729                                printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
2730                                return -3;
2731                        }
2732                }
2733
2734                ii++; cntdn--;
2735                if (!cntdn) {
2736                        printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
2737                                        ioc->name, (int)((ii+5)/HZ));
2738                        return -ETIME;
2739                }
2740
2741                if (sleepFlag == CAN_SLEEP) {
2742                        msleep(1);
2743                } else {
2744                        mdelay (1);        /* 1 msec delay */
2745                }
2746
2747        }
2748
2749        if (statefault < 3) {
2750                printk(MYIOC_s_INFO_FMT "Recovered from %s\n",
2751                                ioc->name,
2752                                statefault==1 ? "stuck handshake" : "IOC FAULT");
2753        }
2754
2755        return hard_reset_done;
2756}
2757
2758/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2759/**
2760 *        mpt_GetIocState - Get the current state of a MPT adapter.
2761 *        @ioc: Pointer to MPT_ADAPTER structure
2762 *        @cooked: Request raw or cooked IOC state
2763 *
2764 *        Returns all IOC Doorbell register bits if cooked==0, else just the
2765 *        Doorbell bits in MPI_IOC_STATE_MASK.
2766 */
2767u32
2768mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
2769{
2770        u32 s, sc;
2771
2772        /*  Get!  */
2773        s = CHIPREG_READ32(&ioc->chip->Doorbell);
2774        sc = s & MPI_IOC_STATE_MASK;
2775
2776        /*  Save!  */
2777        ioc->last_state = sc;
2778
2779        return cooked ? sc : s;
2780}
2781
2782/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2783/**
2784 *        GetIocFacts - Send IOCFacts request to MPT adapter.
2785 *        @ioc: Pointer to MPT_ADAPTER structure
2786 *        @sleepFlag: Specifies whether the process can sleep
2787 *        @reason: If recovery, only update facts.
2788 *
2789 *        Returns 0 for success, non-zero for failure.
2790 */
2791static int
2792GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
2793{
2794        IOCFacts_t                 get_facts;
2795        IOCFactsReply_t                *facts;
2796        int                         r;
2797        int                         req_sz;
2798        int                         reply_sz;
2799        int                         sz;
2800        u32                         status, vv;
2801        u8                         shiftFactor=1;
2802
2803        /* IOC *must* NOT be in RESET state! */
2804        if (ioc->last_state == MPI_IOC_STATE_RESET) {
2805                printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n",
2806                    ioc->name, ioc->last_state );
2807                return -44;
2808        }
2809
2810        facts = &ioc->facts;
2811
2812        /* Destination (reply area)... */
2813        reply_sz = sizeof(*facts);
2814        memset(facts, 0, reply_sz);
2815
2816        /* Request area (get_facts on the stack right now!) */
2817        req_sz = sizeof(get_facts);
2818        memset(&get_facts, 0, req_sz);
2819
2820        get_facts.Function = MPI_FUNCTION_IOC_FACTS;
2821        /* Assert: All other get_facts fields are zero! */
2822
2823        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2824            "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
2825            ioc->name, req_sz, reply_sz));
2826
2827        /* No non-zero fields in the get_facts request are greater than
2828         * 1 byte in size, so we can just fire it off as is.
2829         */
2830        r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
2831                        reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
2832        if (r != 0)
2833                return r;
2834
2835        /*
2836         * Now byte swap (GRRR) the necessary fields before any further
2837         * inspection of reply contents.
2838         *
2839         * But need to do some sanity checks on MsgLength (byte) field
2840         * to make sure we don't zero IOC's req_sz!
2841         */
2842        /* Did we get a valid reply? */
2843        if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
2844                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2845                        /*
2846                         * If not been here, done that, save off first WhoInit value
2847                         */
2848                        if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
2849                                ioc->FirstWhoInit = facts->WhoInit;
2850                }
2851
2852                facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
2853                facts->MsgContext = le32_to_cpu(facts->MsgContext);
2854                facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
2855                facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
2856                facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
2857                status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
2858                /* CHECKME! IOCStatus, IOCLogInfo */
2859
2860                facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
2861                facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
2862
2863                /*
2864                 * FC f/w version changed between 1.1 and 1.2
2865                 *        Old: u16{Major(4),Minor(4),SubMinor(8)}
2866                 *        New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
2867                 */
2868                if (facts->MsgVersion < 0x0102) {
2869                        /*
2870                         *        Handle old FC f/w style, convert to new...
2871                         */
2872                        u16         oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
2873                        facts->FWVersion.Word =
2874                                        ((oldv<<12) & 0xFF000000) |
2875                                        ((oldv<<8)  & 0x000FFF00);
2876                } else
2877                        facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
2878
2879                facts->ProductID = le16_to_cpu(facts->ProductID);
2880                if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
2881                    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
2882                        ioc->ir_firmware = 1;
2883                facts->CurrentHostMfaHighAddr =
2884                                le32_to_cpu(facts->CurrentHostMfaHighAddr);
2885                facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
2886                facts->CurrentSenseBufferHighAddr =
2887                                le32_to_cpu(facts->CurrentSenseBufferHighAddr);
2888                facts->CurReplyFrameSize =
2889                                le16_to_cpu(facts->CurReplyFrameSize);
2890                facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
2891
2892                /*
2893                 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
2894                 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
2895                 * to 14 in MPI-1.01.0x.
2896                 */
2897                if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
2898                    facts->MsgVersion > 0x0100) {
2899                        facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
2900                }
2901
2902                sz = facts->FWImageSize;
2903                if ( sz & 0x01 )
2904                        sz += 1;
2905                if ( sz & 0x02 )
2906                        sz += 2;
2907                facts->FWImageSize = sz;
2908
2909                if (!facts->RequestFrameSize) {
2910                        /*  Something is wrong!  */
2911                        printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
2912                                        ioc->name);
2913                        return -55;
2914                }
2915
2916                r = sz = facts->BlockSize;
2917                vv = ((63 / (sz * 4)) + 1) & 0x03;
2918                ioc->NB_for_64_byte_frame = vv;
2919                while ( sz )
2920                {
2921                        shiftFactor++;
2922                        sz = sz >> 1;
2923                }
2924                ioc->NBShiftFactor  = shiftFactor;
2925                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2926                    "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
2927                    ioc->name, vv, shiftFactor, r));
2928
2929                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2930                        /*
2931                         * Set values for this IOC's request & reply frame sizes,
2932                         * and request & reply queue depths...
2933                         */
2934                        ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
2935                        ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
2936                        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
2937                        ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
2938
2939                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
2940                                ioc->name, ioc->reply_sz, ioc->reply_depth));
2941                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz  =%3d, req_depth  =%4d\n",
2942                                ioc->name, ioc->req_sz, ioc->req_depth));
2943
2944                        /* Get port facts! */
2945                        if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
2946                                return r;
2947                }
2948        } else {
2949                printk(MYIOC_s_ERR_FMT
2950                     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
2951                     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
2952                     RequestFrameSize)/sizeof(u32)));
2953                return -66;
2954        }
2955
2956        return 0;
2957}
2958
2959/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2960/**
2961 *        GetPortFacts - Send PortFacts request to MPT adapter.
2962 *        @ioc: Pointer to MPT_ADAPTER structure
2963 *        @portnum: Port number
2964 *        @sleepFlag: Specifies whether the process can sleep
2965 *
2966 *        Returns 0 for success, non-zero for failure.
2967 */
2968static int
2969GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
2970{
2971        PortFacts_t                 get_pfacts;
2972        PortFactsReply_t        *pfacts;
2973        int                         ii;
2974        int                         req_sz;
2975        int                         reply_sz;
2976        int                         max_id;
2977
2978        /* IOC *must* NOT be in RESET state! */
2979        if (ioc->last_state == MPI_IOC_STATE_RESET) {
2980                printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
2981                    ioc->name, ioc->last_state );
2982                return -4;
2983        }
2984
2985        pfacts = &ioc->pfacts[portnum];
2986
2987        /* Destination (reply area)...  */
2988        reply_sz = sizeof(*pfacts);
2989        memset(pfacts, 0, reply_sz);
2990
2991        /* Request area (get_pfacts on the stack right now!) */
2992        req_sz = sizeof(get_pfacts);
2993        memset(&get_pfacts, 0, req_sz);
2994
2995        get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
2996        get_pfacts.PortNumber = portnum;
2997        /* Assert: All other get_pfacts fields are zero! */
2998
2999        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3000                        ioc->name, portnum));
3001
3002        /* No non-zero fields in the get_pfacts request are greater than
3003         * 1 byte in size, so we can just fire it off as is.
3004         */
3005        ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3006                                reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3007        if (ii != 0)
3008                return ii;
3009
3010        /* Did we get a valid reply? */
3011
3012        /* Now byte swap the necessary fields in the response. */
3013        pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3014        pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3015        pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3016        pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3017        pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3018        pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3019        pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3020        pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3021        pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3022
3023        max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3024            pfacts->MaxDevices;
3025        ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3026        ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3027
3028        /*
3029         * Place all the devices on channels
3030         *
3031         * (for debuging)
3032         */
3033        if (mpt_channel_mapping) {
3034                ioc->devices_per_bus = 1;
3035                ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3036        }
3037
3038        return 0;
3039}
3040
3041/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3042/**
3043 *        SendIocInit - Send IOCInit request to MPT adapter.
3044 *        @ioc: Pointer to MPT_ADAPTER structure
3045 *        @sleepFlag: Specifies whether the process can sleep
3046 *
3047 *        Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3048 *
3049 *        Returns 0 for success, non-zero for failure.
3050 */
3051static int
3052SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3053{
3054        IOCInit_t                 ioc_init;
3055        MPIDefaultReply_t         init_reply;
3056        u32                         state;
3057        int                         r;
3058        int                         count;
3059        int                         cntdn;
3060
3061        memset(&ioc_init, 0, sizeof(ioc_init));
3062        memset(&init_reply, 0, sizeof(init_reply));
3063
3064        ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3065        ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3066
3067        /* If we are in a recovery mode and we uploaded the FW image,
3068         * then this pointer is not NULL. Skip the upload a second time.
3069         * Set this flag if cached_fw set for either IOC.
3070         */
3071        if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3072                ioc->upload_fw = 1;
3073        else
3074                ioc->upload_fw = 0;
3075        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3076                   ioc->name, ioc->upload_fw, ioc->facts.Flags));
3077
3078        ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3079        ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3080        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3081                   ioc->name, ioc->facts.MsgVersion));
3082        if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3083                // set MsgVersion and HeaderVersion host driver was built with
3084                ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3085                ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3086
3087                if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3088                        ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3089                } else if(mpt_host_page_alloc(ioc, &ioc_init))
3090                        return -99;
3091        }
3092        ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);        /* in BYTES */
3093
3094        if (sizeof(dma_addr_t) == sizeof(u64)) {
3095                /* Save the upper 32-bits of the request
3096                 * (reply) and sense buffers.
3097                 */
3098                ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3099                ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3100        } else {
3101                /* Force 32-bit addressing */
3102                ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3103                ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3104        }
3105
3106        ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3107        ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3108        ioc->facts.MaxDevices = ioc_init.MaxDevices;
3109        ioc->facts.MaxBuses = ioc_init.MaxBuses;
3110
3111        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3112                        ioc->name, &ioc_init));
3113
3114        r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3115                                sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3116        if (r != 0) {
3117                printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3118                return r;
3119        }
3120
3121        /* No need to byte swap the multibyte fields in the reply
3122         * since we don't even look at its contents.
3123         */
3124
3125        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3126                        ioc->name, &ioc_init));
3127
3128        if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3129                printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3130                return r;
3131        }
3132
3133        /* YIKES!  SUPER IMPORTANT!!!
3134         *  Poll IocState until _OPERATIONAL while IOC is doing
3135         *  LoopInit and TargetDiscovery!
3136         */
3137        count = 0;
3138        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60;        /* 60 seconds */
3139        state = mpt_GetIocState(ioc, 1);
3140        while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3141                if (sleepFlag == CAN_SLEEP) {
3142                        msleep(1);
3143                } else {
3144                        mdelay(1);
3145                }
3146
3147                if (!cntdn) {
3148                        printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3149                                        ioc->name, (int)((count+5)/HZ));
3150                        return -9;
3151                }
3152
3153                state = mpt_GetIocState(ioc, 1);
3154                count++;
3155        }
3156        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3157                        ioc->name, count));
3158
3159        ioc->aen_event_read_flag=0;
3160        return r;
3161}
3162
3163/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3164/**
3165 *        SendPortEnable - Send PortEnable request to MPT adapter port.
3166 *        @ioc: Pointer to MPT_ADAPTER structure
3167 *        @portnum: Port number to enable
3168 *        @sleepFlag: Specifies whether the process can sleep
3169 *
3170 *        Send PortEnable to bring IOC to OPERATIONAL state.
3171 *
3172 *        Returns 0 for success, non-zero for failure.
3173 */
3174static int
3175SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3176{
3177        PortEnable_t                 port_enable;
3178        MPIDefaultReply_t         reply_buf;
3179        int         rc;
3180        int         req_sz;
3181        int         reply_sz;
3182
3183        /*  Destination...  */
3184        reply_sz = sizeof(MPIDefaultReply_t);
3185        memset(&reply_buf, 0, reply_sz);
3186
3187        req_sz = sizeof(PortEnable_t);
3188        memset(&port_enable, 0, req_sz);
3189
3190        port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3191        port_enable.PortNumber = portnum;
3192/*        port_enable.ChainOffset = 0;                */
3193/*        port_enable.MsgFlags = 0;                */
3194/*        port_enable.MsgContext = 0;                */
3195
3196        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3197                        ioc->name, portnum, &port_enable));
3198
3199        /* RAID FW may take a long time to enable
3200         */
3201        if (ioc->ir_firmware || ioc->bus_type == SAS) {
3202                rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3203                (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3204                300 /*seconds*/, sleepFlag);
3205        } else {
3206                rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3207                (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3208                30 /*seconds*/, sleepFlag);
3209        }
3210        return rc;
3211}
3212
3213/**
3214 *        mpt_alloc_fw_memory - allocate firmware memory
3215 *        @ioc: Pointer to MPT_ADAPTER structure
3216 *      @size: total FW bytes
3217 *
3218 *        If memory has already been allocated, the same (cached) value
3219 *        is returned.
3220 *
3221 *        Return 0 if successfull, or non-zero for failure
3222 **/
3223int
3224mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3225{
3226        int rc;
3227
3228        if (ioc->cached_fw) {
3229                rc = 0;  /* use already allocated memory */
3230                goto out;
3231        }
3232        else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3233                ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
3234                ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3235                rc = 0;
3236                goto out;
3237        }
3238        ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3239        if (!ioc->cached_fw) {
3240                printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3241                    ioc->name);
3242                rc = -1;
3243        } else {
3244                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3245                    ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3246                ioc->alloc_total += size;
3247                rc = 0;
3248        }
3249 out:
3250        return rc;
3251}
3252
3253/**
3254 *        mpt_free_fw_memory - free firmware memory
3255 *        @ioc: Pointer to MPT_ADAPTER structure
3256 *
3257 *        If alt_img is NULL, delete from ioc structure.
3258 *        Else, delete a secondary image in same format.
3259 **/
3260void
3261mpt_free_fw_memory(MPT_ADAPTER *ioc)
3262{
3263        int sz;
3264
3265        if (!ioc->cached_fw)
3266                return;
3267
3268        sz = ioc->facts.FWImageSize;
3269        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3270                 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3271        pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3272        ioc->alloc_total -= sz;
3273        ioc->cached_fw = NULL;
3274}
3275
3276/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3277/**
3278 *        mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3279 *        @ioc: Pointer to MPT_ADAPTER structure
3280 *        @sleepFlag: Specifies whether the process can sleep
3281 *
3282 *        Returns 0 for success, >0 for handshake failure
3283 *                <0 for fw upload failure.
3284 *
3285 *        Remark: If bound IOC and a successful FWUpload was performed
3286 *        on the bound IOC, the second image is discarded
3287 *        and memory is free'd. Both channels must upload to prevent
3288 *        IOC from running in degraded mode.
3289 */
3290static int
3291mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3292{
3293        u8                         reply[sizeof(FWUploadReply_t)];
3294        FWUpload_t                *prequest;
3295        FWUploadReply_t                *preply;
3296        FWUploadTCSGE_t                *ptcsge;
3297        int                         sgeoffset;
3298        u32                         flagsLength;
3299        int                         ii, sz, reply_sz;
3300        int                         cmdStatus;
3301
3302        /* If the image size is 0, we are done.
3303         */
3304        if ((sz = ioc->facts.FWImageSize) == 0)
3305                return 0;
3306
3307        if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3308                return -ENOMEM;
3309
3310        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3311            ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3312
3313        prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3314            kzalloc(ioc->req_sz, GFP_KERNEL);
3315        if (!prequest) {
3316                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3317                    "while allocating memory \n", ioc->name));
3318                mpt_free_fw_memory(ioc);
3319                return -ENOMEM;
3320        }
3321
3322        preply = (FWUploadReply_t *)&reply;
3323
3324        reply_sz = sizeof(reply);
3325        memset(preply, 0, reply_sz);
3326
3327        prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3328        prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3329
3330        ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3331        ptcsge->DetailsLength = 12;
3332        ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3333        ptcsge->ImageSize = cpu_to_le32(sz);
3334        ptcsge++;
3335
3336        sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
3337
3338        flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3339        mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3340
3341        sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
3342        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n",
3343            ioc->name, prequest, sgeoffset));
3344        DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3345
3346        ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
3347                                reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
3348
3349        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii));
3350
3351        cmdStatus = -EFAULT;
3352        if (ii == 0) {
3353                /* Handshake transfer was complete and successful.
3354                 * Check the Reply Frame.
3355                 */
3356                int status, transfer_sz;
3357                status = le16_to_cpu(preply->IOCStatus);
3358                if (status == MPI_IOCSTATUS_SUCCESS) {
3359                        transfer_sz = le32_to_cpu(preply->ActualImageSize);
3360                        if (transfer_sz == sz)
3361                                cmdStatus = 0;
3362                }
3363        }
3364        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3365                        ioc->name, cmdStatus));
3366
3367
3368        if (cmdStatus) {
3369
3370                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": fw upload failed, freeing image \n",
3371                        ioc->name));
3372                mpt_free_fw_memory(ioc);
3373        }
3374        kfree(prequest);
3375
3376        return cmdStatus;
3377}
3378
3379/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3380/**
3381 *        mpt_downloadboot - DownloadBoot code
3382 *        @ioc: Pointer to MPT_ADAPTER structure
3383 *        @pFwHeader: Pointer to firmware header info
3384 *        @sleepFlag: Specifies whether the process can sleep
3385 *
3386 *        FwDownloadBoot requires Programmed IO access.
3387 *
3388 *        Returns 0 for success
3389 *                -1 FW Image size is 0
3390 *                -2 No valid cached_fw Pointer
3391 *                <0 for fw upload failure.
3392 */
3393static int
3394mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3395{
3396        MpiExtImageHeader_t        *pExtImage;
3397        u32                         fwSize;
3398        u32                         diag0val;
3399        int                         count;
3400        u32                        *ptrFw;
3401        u32                         diagRwData;
3402        u32                         nextImage;
3403        u32                         load_addr;
3404        u32                          ioc_state=0;
3405
3406        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3407                                ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3408
3409        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3410        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3411        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3412        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3413        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3414        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3415
3416        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3417
3418        /* wait 1 msec */
3419        if (sleepFlag == CAN_SLEEP) {
3420                msleep(1);
3421        } else {
3422                mdelay (1);
3423        }
3424
3425        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3426        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3427
3428        for (count = 0; count < 30; count ++) {
3429                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3430                if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3431                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3432                                ioc->name, count));
3433                        break;
3434                }
3435                /* wait .1 sec */
3436                if (sleepFlag == CAN_SLEEP) {
3437                        msleep (100);
3438                } else {
3439                        mdelay (100);
3440                }
3441        }
3442
3443        if ( count == 30 ) {
3444                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3445                "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3446                ioc->name, diag0val));
3447                return -3;
3448        }
3449
3450        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3451        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3452        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3453        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3454        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3455        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3456
3457        /* Set the DiagRwEn and Disable ARM bits */
3458        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3459
3460        fwSize = (pFwHeader->ImageSize + 3)/4;
3461        ptrFw = (u32 *) pFwHeader;
3462
3463        /* Write the LoadStartAddress to the DiagRw Address Register
3464         * using Programmed IO
3465         */
3466        if (ioc->errata_flag_1064)
3467                pci_enable_io_access(ioc->pcidev);
3468
3469        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3470        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3471                ioc->name, pFwHeader->LoadStartAddress));
3472
3473        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3474                                ioc->name, fwSize*4, ptrFw));
3475        while (fwSize--) {
3476                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3477        }
3478
3479        nextImage = pFwHeader->NextImageHeaderOffset;
3480        while (nextImage) {
3481                pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3482
3483                load_addr = pExtImage->LoadStartAddress;
3484
3485                fwSize = (pExtImage->ImageSize + 3) >> 2;
3486                ptrFw = (u32 *)pExtImage;
3487
3488                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3489                                                ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3490                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3491
3492                while (fwSize--) {
3493                        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3494                }
3495                nextImage = pExtImage->NextImageHeaderOffset;
3496        }
3497
3498        /* Write the IopResetVectorRegAddr */
3499        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name,         pFwHeader->IopResetRegAddr));
3500        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3501
3502        /* Write the IopResetVectorValue */
3503        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3504        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3505
3506        /* Clear the internal flash bad bit - autoincrementing register,
3507         * so must do two writes.
3508         */
3509        if (ioc->bus_type == SPI) {
3510                /*
3511                 * 1030 and 1035 H/W errata, workaround to access
3512                 * the ClearFlashBadSignatureBit
3513                 */
3514                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3515                diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3516                diagRwData |= 0x40000000;
3517                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3518                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3519
3520        } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3521                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3522                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3523                    MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3524
3525                /* wait 1 msec */
3526                if (sleepFlag == CAN_SLEEP) {
3527                        msleep (1);
3528                } else {
3529                        mdelay (1);
3530                }
3531        }
3532
3533        if (ioc->errata_flag_1064)
3534                pci_disable_io_access(ioc->pcidev);
3535
3536        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3537        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3538                "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3539                ioc->name, diag0val));
3540        diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3541        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3542                ioc->name, diag0val));
3543        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3544
3545        /* Write 0xFF to reset the sequencer */
3546        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3547
3548        if (ioc->bus_type == SAS) {
3549                ioc_state = mpt_GetIocState(ioc, 0);
3550                if ( (GetIocFacts(ioc, sleepFlag,
3551                                MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3552                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3553                                        ioc->name, ioc_state));
3554                        return -EFAULT;
3555                }
3556        }
3557
3558        for (count=0; count<HZ*20; count++) {
3559                if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3560                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3561                                "downloadboot successful! (count=%d) IocState=%x\n",
3562                                ioc->name, count, ioc_state));
3563                        if (ioc->bus_type == SAS) {
3564                                return 0;
3565                        }
3566                        if ((SendIocInit(ioc, sleepFlag)) != 0) {
3567                                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3568                                        "downloadboot: SendIocInit failed\n",
3569                                        ioc->name));
3570                                return -EFAULT;
3571                        }
3572                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3573                                        "downloadboot: SendIocInit successful\n",
3574                                        ioc->name));
3575                        return 0;
3576                }
3577                if (sleepFlag == CAN_SLEEP) {
3578                        msleep (10);
3579                } else {
3580                        mdelay (10);
3581                }
3582        }
3583        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3584                "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3585        return -EFAULT;
3586}
3587
3588/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3589/**
3590 *        KickStart - Perform hard reset of MPT adapter.
3591 *        @ioc: Pointer to MPT_ADAPTER structure
3592 *        @force: Force hard reset
3593 *        @sleepFlag: Specifies whether the process can sleep
3594 *
3595 *        This routine places MPT adapter in diagnostic mode via the
3596 *        WriteSequence register, and then performs a hard reset of adapter
3597 *        via the Diagnostic register.
3598 *
3599 *        Inputs:   sleepflag - CAN_SLEEP (non-interrupt thread)
3600 *                        or NO_SLEEP (interrupt thread, use mdelay)
3601 *                  force - 1 if doorbell active, board fault state
3602 *                                board operational, IOC_RECOVERY or
3603 *                                IOC_BRINGUP and there is an alt_ioc.
3604 *                          0 else
3605 *
3606 *        Returns:
3607 *                 1 - hard reset, READY
3608 *                 0 - no reset due to History bit, READY
3609 *                -1 - no reset due to History bit but not READY
3610 *                     OR reset but failed to come READY
3611 *                -2 - no reset, could not enter DIAG mode
3612 *                -3 - reset but bad FW bit
3613 */
3614static int
3615KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3616{
3617        int hard_reset_done = 0;
3618        u32 ioc_state=0;
3619        int cnt,cntdn;
3620
3621        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3622        if (ioc->bus_type == SPI) {
3623                /* Always issue a Msg Unit Reset first. This will clear some
3624                 * SCSI bus hang conditions.
3625                 */
3626                SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3627
3628                if (sleepFlag == CAN_SLEEP) {
3629                        msleep (1000);
3630                } else {
3631                        mdelay (1000);
3632                }
3633        }
3634
3635        hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3636        if (hard_reset_done < 0)
3637                return hard_reset_done;
3638
3639        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3640                ioc->name));
3641
3642        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;        /* 2 seconds */
3643        for (cnt=0; cnt<cntdn; cnt++) {
3644                ioc_state = mpt_GetIocState(ioc, 1);
3645                if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3646                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3647                                         ioc->name, cnt));
3648                        return hard_reset_done;
3649                }
3650                if (sleepFlag == CAN_SLEEP) {
3651                        msleep (10);
3652                } else {
3653                        mdelay (10);
3654                }
3655        }
3656
3657        dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3658                ioc->name, mpt_GetIocState(ioc, 0)));
3659        return -1;
3660}
3661
3662/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3663/**
3664 *        mpt_diag_reset - Perform hard reset of the adapter.
3665 *        @ioc: Pointer to MPT_ADAPTER structure
3666 *        @ignore: Set if to honor and clear to ignore
3667 *                the reset history bit
3668 *        @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3669 *                else set to NO_SLEEP (use mdelay instead)
3670 *
3671 *        This routine places the adapter in diagnostic mode via the
3672 *        WriteSequence register and then performs a hard reset of adapter
3673 *        via the Diagnostic register. Adapter should be in ready state
3674 *        upon successful completion.
3675 *
3676 *        Returns:  1  hard reset successful
3677 *                  0  no reset performed because reset history bit set
3678 *                 -2  enabling diagnostic mode failed
3679 *                 -3  diagnostic reset failed
3680 */
3681static int
3682mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3683{
3684        u32 diag0val;
3685        u32 doorbell;
3686        int hard_reset_done = 0;
3687        int count = 0;
3688        u32 diag1val = 0;
3689        MpiFwHeader_t *cached_fw;        /* Pointer to FW */
3690
3691        /* Clear any existing interrupts */
3692        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3693
3694        if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3695                drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3696                        "address=%p\n",  ioc->name, __func__,
3697                        &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3698                CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3699                if (sleepFlag == CAN_SLEEP)
3700                        msleep(1);
3701                else
3702                        mdelay(1);
3703
3704                for (count = 0; count < 60; count ++) {
3705                        doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3706                        doorbell &= MPI_IOC_STATE_MASK;
3707
3708                        drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3709                                "looking for READY STATE: doorbell=%x"
3710                                " count=%d\n",
3711                                ioc->name, doorbell, count));
3712                        if (doorbell == MPI_IOC_STATE_READY) {
3713                                return 1;
3714                        }
3715
3716                        /* wait 1 sec */
3717                        if (sleepFlag == CAN_SLEEP)
3718                                msleep(1000);
3719                        else
3720                                mdelay(1000);
3721                }
3722                return -1;
3723        }
3724
3725        /* Use "Diagnostic reset" method! (only thing available!) */
3726        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3727
3728        if (ioc->debug_level & MPT_DEBUG) {
3729                if (ioc->alt_ioc)
3730                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3731                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
3732                        ioc->name, diag0val, diag1val));
3733        }
3734
3735        /* Do the reset if we are told to ignore the reset history
3736         * or if the reset history is 0
3737         */
3738        if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
3739                while ((diag0val & MPI_DIAG_DRWE) == 0) {
3740                        /* Write magic sequence to WriteSequence register
3741                         * Loop until in diagnostic mode
3742                         */
3743                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3744                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3745                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3746                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3747                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3748                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3749
3750                        /* wait 100 msec */
3751                        if (sleepFlag == CAN_SLEEP) {
3752                                msleep (100);
3753                        } else {
3754                                mdelay (100);
3755                        }
3756
3757                        count++;
3758                        if (count > 20) {
3759                                printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3760                                                ioc->name, diag0val);
3761                                return -2;
3762
3763                        }
3764
3765                        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3766
3767                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
3768                                        ioc->name, diag0val));
3769                }
3770
3771                if (ioc->debug_level & MPT_DEBUG) {
3772                        if (ioc->alt_ioc)
3773                                diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3774                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
3775                                ioc->name, diag0val, diag1val));
3776                }
3777                /*
3778                 * Disable the ARM (Bug fix)
3779                 *
3780                 */
3781                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
3782                mdelay(1);
3783
3784                /*
3785                 * Now hit the reset bit in the Diagnostic register
3786                 * (THE BIG HAMMER!) (Clears DRWE bit).
3787                 */
3788                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3789                hard_reset_done = 1;
3790                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
3791                                ioc->name));
3792
3793                /*
3794                 * Call each currently registered protocol IOC reset handler
3795                 * with pre-reset indication.
3796                 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3797                 * MptResetHandlers[] registered yet.
3798                 */
3799                {
3800                        u8         cb_idx;
3801                        int         r = 0;
3802
3803                        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3804                                if (MptResetHandlers[cb_idx]) {
3805                                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3806                                                "Calling IOC pre_reset handler #%d\n",
3807                                                ioc->name, cb_idx));
3808                                        r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
3809                                        if (ioc->alt_ioc) {
3810                                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3811                                                        "Calling alt-%s pre_reset handler #%d\n",
3812                                                        ioc->name, ioc->alt_ioc->name, cb_idx));
3813                                                r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET);
3814                                        }
3815                                }
3816                        }
3817                        /* FIXME?  Examine results here? */
3818                }
3819
3820                if (ioc->cached_fw)
3821                        cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
3822                else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
3823                        cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
3824                else
3825                        cached_fw = NULL;
3826                if (cached_fw) {
3827                        /* If the DownloadBoot operation fails, the
3828                         * IOC will be left unusable. This is a fatal error
3829                         * case.  _diag_reset will return < 0
3830                         */
3831                        for (count = 0; count < 30; count ++) {
3832                                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3833                                if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3834                                        break;
3835                                }
3836
3837                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
3838                                        ioc->name, diag0val, count));
3839                                /* wait 1 sec */
3840                                if (sleepFlag == CAN_SLEEP) {
3841                                        msleep (1000);
3842                                } else {
3843                                        mdelay (1000);
3844                                }
3845                        }
3846                        if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
3847                                printk(MYIOC_s_WARN_FMT
3848                                        "firmware downloadboot failure (%d)!\n", ioc->name, count);
3849                        }
3850
3851                } else {
3852                        /* Wait for FW to reload and for board
3853                         * to go to the READY state.
3854                         * Maximum wait is 60 seconds.
3855                         * If fail, no error will check again
3856                         * with calling program.
3857                         */
3858                        for (count = 0; count < 60; count ++) {
3859                                doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
3860                                doorbell &= MPI_IOC_STATE_MASK;
3861
3862                                if (doorbell == MPI_IOC_STATE_READY) {
3863                                        break;
3864                                }
3865
3866                                /* wait 1 sec */
3867                                if (sleepFlag == CAN_SLEEP) {
3868                                        msleep (1000);
3869                                } else {
3870                                        mdelay (1000);
3871                                }
3872                        }
3873                }
3874        }
3875
3876        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3877        if (ioc->debug_level & MPT_DEBUG) {
3878                if (ioc->alt_ioc)
3879                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3880                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
3881                        ioc->name, diag0val, diag1val));
3882        }
3883
3884        /* Clear RESET_HISTORY bit!  Place board in the
3885         * diagnostic mode to update the diag register.
3886         */
3887        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3888        count = 0;
3889        while ((diag0val & MPI_DIAG_DRWE) == 0) {
3890                /* Write magic sequence to WriteSequence register
3891                 * Loop until in diagnostic mode
3892                 */
3893                CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3894                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3895                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3896                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3897                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3898                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3899
3900                /* wait 100 msec */
3901                if (sleepFlag == CAN_SLEEP) {
3902                        msleep (100);
3903                } else {
3904                        mdelay (100);
3905                }
3906
3907                count++;
3908                if (count > 20) {
3909                        printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
3910                                        ioc->name, diag0val);
3911                        break;
3912                }
3913                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3914        }
3915        diag0val &= ~MPI_DIAG_RESET_HISTORY;
3916        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3917        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3918        if (diag0val & MPI_DIAG_RESET_HISTORY) {
3919                printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
3920                                ioc->name);
3921        }
3922
3923        /* Disable Diagnostic Mode
3924         */
3925        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
3926
3927        /* Check FW reload status flags.
3928         */
3929        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3930        if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
3931                printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
3932                                ioc->name, diag0val);
3933                return -3;
3934        }
3935
3936        if (ioc->debug_level & MPT_DEBUG) {
3937                if (ioc->alt_ioc)
3938                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
3939                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
3940                        ioc->name, diag0val, diag1val));
3941        }
3942
3943        /*
3944         * Reset flag that says we've enabled event notification
3945         */
3946        ioc->facts.EventState = 0;
3947
3948        if (ioc->alt_ioc)
3949                ioc->alt_ioc->facts.EventState = 0;
3950
3951        return hard_reset_done;
3952}
3953
3954/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3955/**
3956 *        SendIocReset - Send IOCReset request to MPT adapter.
3957 *        @ioc: Pointer to MPT_ADAPTER structure
3958 *        @reset_type: reset type, expected values are
3959 *        %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
3960 *        @sleepFlag: Specifies whether the process can sleep
3961 *
3962 *        Send IOCReset request to the MPT adapter.
3963 *
3964 *        Returns 0 for success, non-zero for failure.
3965 */
3966static int
3967SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
3968{
3969        int r;
3970        u32 state;
3971        int cntdn, count;
3972
3973        drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
3974                        ioc->name, reset_type));
3975        CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
3976        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
3977                return r;
3978
3979        /* FW ACK'd request, wait for READY state
3980         */
3981        count = 0;
3982        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;        /* 15 seconds */
3983
3984        while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
3985                cntdn--;
3986                count++;
3987                if (!cntdn) {
3988                        if (sleepFlag != CAN_SLEEP)
3989                                count *= 10;
3990
3991                        printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
3992                            ioc->name, (int)((count+5)/HZ));
3993                        return -ETIME;
3994                }
3995
3996                if (sleepFlag == CAN_SLEEP) {
3997                        msleep(1);
3998                } else {
3999                        mdelay (1);        /* 1 msec delay */
4000                }
4001        }
4002
4003        /* TODO!
4004         *  Cleanup all event stuff for this IOC; re-issue EventNotification
4005         *  request if needed.
4006         */
4007        if (ioc->facts.Function)
4008                ioc->facts.EventState = 0;
4009
4010        return 0;
4011}
4012
4013/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4014/**
4015 *        initChainBuffers - Allocate memory for and initialize chain buffers
4016 *        @ioc: Pointer to MPT_ADAPTER structure
4017 *
4018 *        Allocates memory for and initializes chain buffers,
4019 *        chain buffer control arrays and spinlock.
4020 */
4021static int
4022initChainBuffers(MPT_ADAPTER *ioc)
4023{
4024        u8                *mem;
4025        int                sz, ii, num_chain;
4026        int                 scale, num_sge, numSGE;
4027
4028        /* ReqToChain size must equal the req_depth
4029         * index = req_idx
4030         */
4031        if (ioc->ReqToChain == NULL) {
4032                sz = ioc->req_depth * sizeof(int);
4033                mem = kmalloc(sz, GFP_ATOMIC);
4034                if (mem == NULL)
4035                        return -1;
4036
4037                ioc->ReqToChain = (int *) mem;
4038                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc  @ %p, sz=%d bytes\n",
4039                                 ioc->name, mem, sz));
4040                mem = kmalloc(sz, GFP_ATOMIC);
4041                if (mem == NULL)
4042                        return -1;
4043
4044                ioc->RequestNB = (int *) mem;
4045                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc  @ %p, sz=%d bytes\n",
4046                                 ioc->name, mem, sz));
4047        }
4048        for (ii = 0; ii < ioc->req_depth; ii++) {
4049                ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4050        }
4051
4052        /* ChainToChain size must equal the total number
4053         * of chain buffers to be allocated.
4054         * index = chain_idx
4055         *
4056         * Calculate the number of chain buffers needed(plus 1) per I/O
4057         * then multiply the maximum number of simultaneous cmds
4058         *
4059         * num_sge = num sge in request frame + last chain buffer
4060         * scale = num sge per chain buffer if no chain element
4061         */
4062        scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
4063        if (sizeof(dma_addr_t) == sizeof(u64))
4064                num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4065        else
4066                num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4067
4068        if (sizeof(dma_addr_t) == sizeof(u64)) {
4069                numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4070                        (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
4071        } else {
4072                numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4073                        (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
4074        }
4075        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4076                ioc->name, num_sge, numSGE));
4077
4078        if ( numSGE > MPT_SCSI_SG_DEPTH        )
4079                numSGE = MPT_SCSI_SG_DEPTH;
4080
4081        num_chain = 1;
4082        while (numSGE - num_sge > 0) {
4083                num_chain++;
4084                num_sge += (scale - 1);
4085        }
4086        num_chain++;
4087
4088        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4089                ioc->name, numSGE, num_sge, num_chain));
4090
4091        if (ioc->bus_type == SPI)
4092                num_chain *= MPT_SCSI_CAN_QUEUE;
4093        else
4094                num_chain *= MPT_FC_CAN_QUEUE;
4095
4096        ioc->num_chain = num_chain;
4097
4098        sz = num_chain * sizeof(int);
4099        if (ioc->ChainToChain == NULL) {
4100                mem = kmalloc(sz, GFP_ATOMIC);
4101                if (mem == NULL)
4102                        return -1;
4103
4104                ioc->ChainToChain = (int *) mem;
4105                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4106                                 ioc->name, mem, sz));
4107        } else {
4108                mem = (u8 *) ioc->ChainToChain;
4109        }
4110        memset(mem, 0xFF, sz);
4111        return num_chain;
4112}
4113
4114/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4115/**
4116 *        PrimeIocFifos - Initialize IOC request and reply FIFOs.
4117 *        @ioc: Pointer to MPT_ADAPTER structure
4118 *
4119 *        This routine allocates memory for the MPT reply and request frame
4120 *        pools (if necessary), and primes the IOC reply FIFO with
4121 *        reply frames.
4122 *
4123 *        Returns 0 for success, non-zero for failure.
4124 */
4125static int
4126PrimeIocFifos(MPT_ADAPTER *ioc)
4127{
4128        MPT_FRAME_HDR *mf;
4129        unsigned long flags;
4130        dma_addr_t alloc_dma;
4131        u8 *mem;
4132        int i, reply_sz, sz, total_size, num_chain;
4133
4134        /*  Prime reply FIFO...  */
4135
4136        if (ioc->reply_frames == NULL) {
4137                if ( (num_chain = initChainBuffers(ioc)) < 0)
4138                        return -1;
4139
4140                total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4141                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4142                                 ioc->name, ioc->reply_sz, ioc->reply_depth));
4143                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4144                                 ioc->name, reply_sz, reply_sz));
4145
4146                sz = (ioc->req_sz * ioc->req_depth);
4147                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4148                                 ioc->name, ioc->req_sz, ioc->req_depth));
4149                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4150                                 ioc->name, sz, sz));
4151                total_size += sz;
4152
4153                sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4154                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4155                                 ioc->name, ioc->req_sz, num_chain));
4156                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4157                                 ioc->name, sz, sz, num_chain));
4158
4159                total_size += sz;
4160                mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4161                if (mem == NULL) {
4162                        printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4163                                ioc->name);
4164                        goto out_fail;
4165                }
4166
4167                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4168                                 ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4169
4170                memset(mem, 0, total_size);
4171                ioc->alloc_total += total_size;
4172                ioc->alloc = mem;
4173                ioc->alloc_dma = alloc_dma;
4174                ioc->alloc_sz = total_size;
4175                ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4176                ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4177
4178                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4179                         ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4180
4181                alloc_dma += reply_sz;
4182                mem += reply_sz;
4183
4184                /*  Request FIFO - WE manage this!  */
4185
4186                ioc->req_frames = (MPT_FRAME_HDR *) mem;
4187                ioc->req_frames_dma = alloc_dma;
4188
4189                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4190                                 ioc->name, mem, (void *)(ulong)alloc_dma));
4191
4192                ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4193
4194#if defined(CONFIG_MTRR) && 0
4195                /*
4196                 *  Enable Write Combining MTRR for IOC's memory region.
4197                 *  (at least as much as we can; "size and base must be
4198                 *  multiples of 4 kiB"
4199                 */
4200                ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
4201                                         sz,
4202                                         MTRR_TYPE_WRCOMB, 1);
4203                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MTRR region registered (base:size=%08x:%x)\n",
4204                                ioc->name, ioc->req_frames_dma, sz));
4205#endif
4206
4207                for (i = 0; i < ioc->req_depth; i++) {
4208                        alloc_dma += ioc->req_sz;
4209                        mem += ioc->req_sz;
4210                }
4211
4212                ioc->ChainBuffer = mem;
4213                ioc->ChainBufferDMA = alloc_dma;
4214
4215                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4216                        ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4217
4218                /* Initialize the free chain Q.
4219                 */
4220
4221                INIT_LIST_HEAD(&ioc->FreeChainQ);
4222
4223                /* Post the chain buffers to the FreeChainQ.
4224                 */
4225                mem = (u8 *)ioc->ChainBuffer;
4226                for (i=0; i < num_chain; i++) {
4227                        mf = (MPT_FRAME_HDR *) mem;
4228                        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4229                        mem += ioc->req_sz;
4230                }
4231
4232                /* Initialize Request frames linked list
4233                 */
4234                alloc_dma = ioc->req_frames_dma;
4235                mem = (u8 *) ioc->req_frames;
4236
4237                spin_lock_irqsave(&ioc->FreeQlock, flags);
4238                INIT_LIST_HEAD(&ioc->FreeQ);
4239                for (i = 0; i < ioc->req_depth; i++) {
4240                        mf = (MPT_FRAME_HDR *) mem;
4241
4242                        /*  Queue REQUESTs *internally*!  */
4243                        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4244
4245                        mem += ioc->req_sz;
4246                }
4247                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4248
4249                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4250                ioc->sense_buf_pool =
4251                        pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4252                if (ioc->sense_buf_pool == NULL) {
4253                        printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4254                                ioc->name);
4255                        goto out_fail;
4256                }
4257
4258                ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4259                ioc->alloc_total += sz;
4260                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4261                         ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4262
4263        }
4264
4265        /* Post Reply frames to FIFO
4266         */
4267        alloc_dma = ioc->alloc_dma;
4268        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4269                 ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4270
4271        for (i = 0; i < ioc->reply_depth; i++) {
4272                /*  Write each address to the IOC!  */
4273                CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4274                alloc_dma += ioc->reply_sz;
4275        }
4276
4277        return 0;
4278
4279out_fail:
4280        if (ioc->alloc != NULL) {
4281                sz = ioc->alloc_sz;
4282                pci_free_consistent(ioc->pcidev,
4283                                sz,
4284                                ioc->alloc, ioc->alloc_dma);
4285                ioc->reply_frames = NULL;
4286                ioc->req_frames = NULL;
4287                ioc->alloc_total -= sz;
4288        }
4289        if (ioc->sense_buf_pool != NULL) {
4290                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4291                pci_free_consistent(ioc->pcidev,
4292                                sz,
4293                                ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
4294                ioc->sense_buf_pool = NULL;
4295        }
4296        return -1;
4297}
4298
4299/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4300/**
4301 *        mpt_handshake_req_reply_wait - Send MPT request to and receive reply
4302 *        from IOC via doorbell handshake method.
4303 *        @ioc: Pointer to MPT_ADAPTER structure
4304 *        @reqBytes: Size of the request in bytes
4305 *        @req: Pointer to MPT request frame
4306 *        @replyBytes: Expected size of the reply in bytes
4307 *        @u16reply: Pointer to area where reply should be written
4308 *        @maxwait: Max wait time for a reply (in seconds)
4309 *        @sleepFlag: Specifies whether the process can sleep
4310 *
4311 *        NOTES: It is the callers responsibility to byte-swap fields in the
4312 *        request which are greater than 1 byte in size.  It is also the
4313 *        callers responsibility to byte-swap response fields which are
4314 *        greater than 1 byte in size.
4315 *
4316 *        Returns 0 for success, non-zero for failure.
4317 */
4318static int
4319mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
4320                int replyBytes, u16 *u16reply, int maxwait, int sleepFlag)
4321{
4322        MPIDefaultReply_t *mptReply;
4323        int failcnt = 0;
4324        int t;
4325
4326        /*
4327         * Get ready to cache a handshake reply
4328         */
4329        ioc->hs_reply_idx = 0;
4330        mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4331        mptReply->MsgLength = 0;
4332
4333        /*
4334         * Make sure there are no doorbells (WRITE 0 to IntStatus reg),
4335         * then tell IOC that we want to handshake a request of N words.
4336         * (WRITE u32val to Doorbell reg).
4337         */
4338        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4339        CHIPREG_WRITE32(&ioc->chip->Doorbell,
4340                        ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
4341                         ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
4342
4343        /*
4344         * Wait for IOC's doorbell handshake int
4345         */
4346        if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4347                failcnt++;
4348
4349        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
4350                        ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4351
4352        /* Read doorbell and check for active bit */
4353        if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
4354                        return -1;
4355
4356        /*
4357         * Clear doorbell int (WRITE 0 to IntStatus reg),
4358         * then wait for IOC to ACKnowledge that it's ready for
4359         * our handshake request.
4360         */
4361        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4362        if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4363                failcnt++;
4364
4365        if (!failcnt) {
4366                int         ii;
4367                u8        *req_as_bytes = (u8 *) req;
4368
4369                /*
4370                 * Stuff request words via doorbell handshake,
4371                 * with ACK from IOC for each.
4372                 */
4373                for (ii = 0; !failcnt && ii < reqBytes/4; ii++) {
4374                        u32 word = ((req_as_bytes[(ii*4) + 0] <<  0) |
4375                                    (req_as_bytes[(ii*4) + 1] <<  8) |
4376                                    (req_as_bytes[(ii*4) + 2] << 16) |
4377                                    (req_as_bytes[(ii*4) + 3] << 24));
4378
4379                        CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
4380                        if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4381                                failcnt++;
4382                }
4383
4384                dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req));
4385                DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req);
4386
4387                dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n",
4388                                ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : ""));
4389
4390                /*
4391                 * Wait for completion of doorbell handshake reply from the IOC
4392                 */
4393                if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
4394                        failcnt++;
4395
4396                dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n",
4397                                ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
4398
4399                /*
4400                 * Copy out the cached reply...
4401                 */
4402                for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++)
4403                        u16reply[ii] = ioc->hs_reply[ii];
4404        } else {
4405                return -99;
4406        }
4407
4408        return -failcnt;
4409}
4410
4411/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4412/**
4413 *        WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge
4414 *        @ioc: Pointer to MPT_ADAPTER structure
4415 *        @howlong: How long to wait (in seconds)
4416 *        @sleepFlag: Specifies whether the process can sleep
4417 *
4418 *        This routine waits (up to ~2 seconds max) for IOC doorbell
4419 *        handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS
4420 *        bit in its IntStatus register being clear.
4421 *
4422 *        Returns a negative value on failure, else wait loop count.
4423 */
4424static int
4425WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4426{
4427        int cntdn;
4428        int count = 0;
4429        u32 intstat=0;
4430
4431        cntdn = 1000 * howlong;
4432
4433        if (sleepFlag == CAN_SLEEP) {
4434                while (--cntdn) {
4435                        msleep (1);
4436                        intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4437                        if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4438                                break;
4439                        count++;
4440                }
4441        } else {
4442                while (--cntdn) {
4443                        udelay (1000);
4444                        intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4445                        if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
4446                                break;
4447                        count++;
4448                }
4449        }
4450
4451        if (cntdn) {
4452                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n",
4453                                ioc->name, count));
4454                return count;
4455        }
4456
4457        printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
4458                        ioc->name, count, intstat);
4459        return -1;
4460}
4461
4462/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4463/**
4464 *        WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit
4465 *        @ioc: Pointer to MPT_ADAPTER structure
4466 *        @howlong: How long to wait (in seconds)
4467 *        @sleepFlag: Specifies whether the process can sleep
4468 *
4469 *        This routine waits (up to ~2 seconds max) for IOC doorbell interrupt
4470 *        (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register.
4471 *
4472 *        Returns a negative value on failure, else wait loop count.
4473 */
4474static int
4475WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4476{
4477        int cntdn;
4478        int count = 0;
4479        u32 intstat=0;
4480
4481        cntdn = 1000 * howlong;
4482        if (sleepFlag == CAN_SLEEP) {
4483                while (--cntdn) {
4484                        intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4485                        if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4486                                break;
4487                        msleep(1);
4488                        count++;
4489                }
4490        } else {
4491                while (--cntdn) {
4492                        intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
4493                        if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
4494                                break;
4495                        udelay (1000);
4496                        count++;
4497                }
4498        }
4499
4500        if (cntdn) {
4501                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
4502                                ioc->name, count, howlong));
4503                return count;
4504        }
4505
4506        printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
4507                        ioc->name, count, intstat);
4508        return -1;
4509}
4510
4511/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4512/**
4513 *        WaitForDoorbellReply - Wait for and capture an IOC handshake reply.
4514 *        @ioc: Pointer to MPT_ADAPTER structure
4515 *        @howlong: How long to wait (in seconds)
4516 *        @sleepFlag: Specifies whether the process can sleep
4517 *
4518 *        This routine polls the IOC for a handshake reply, 16 bits at a time.
4519 *        Reply is cached to IOC private area large enough to hold a maximum
4520 *        of 128 bytes of reply data.
4521 *
4522 *        Returns a negative value on failure, else size of reply in WORDS.
4523 */
4524static int
4525WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
4526{
4527        int u16cnt = 0;
4528        int failcnt = 0;
4529        int t;
4530        u16 *hs_reply = ioc->hs_reply;
4531        volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply;
4532        u16 hword;
4533
4534        hs_reply[0] = hs_reply[1] = hs_reply[7] = 0;
4535
4536        /*
4537         * Get first two u16's so we can look at IOC's intended reply MsgLength
4538         */
4539        u16cnt=0;
4540        if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
4541                failcnt++;
4542        } else {
4543                hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4544                CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4545                if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4546                        failcnt++;
4547                else {
4548                        hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4549                        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4550                }
4551        }
4552
4553        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
4554                        ioc->name, t, le32_to_cpu(*(u32 *)hs_reply),
4555                        failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
4556
4557        /*
4558         * If no error (and IOC said MsgLength is > 0), piece together
4559         * reply 16 bits at a time.
4560         */
4561        for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
4562                if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4563                        failcnt++;
4564                hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
4565                /* don't overflow our IOC hs_reply[] buffer! */
4566                if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
4567                        hs_reply[u16cnt] = hword;
4568                CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4569        }
4570
4571        if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
4572                failcnt++;
4573        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
4574
4575        if (failcnt) {
4576                printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",
4577                                ioc->name);
4578                return -failcnt;
4579        }
4580#if 0
4581        else if (u16cnt != (2 * mptReply->MsgLength)) {
4582                return -101;
4583        }
4584        else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
4585                return -102;
4586        }
4587#endif
4588
4589        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name));
4590        DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply);
4591
4592        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
4593                        ioc->name, t, u16cnt/2));
4594        return u16cnt/2;
4595}
4596
4597/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4598/**
4599 *        GetLanConfigPages - Fetch LANConfig pages.
4600 *        @ioc: Pointer to MPT_ADAPTER structure
4601 *
4602 *        Return: 0 for success
4603 *        -ENOMEM if no memory available
4604 *                -EPERM if not allowed due to ISR context
4605 *                -EAGAIN if no msg frames currently available
4606 *                -EFAULT for non-successful reply or no reply (timeout)
4607 */
4608static int
4609GetLanConfigPages(MPT_ADAPTER *ioc)
4610{
4611        ConfigPageHeader_t         hdr;
4612        CONFIGPARMS                 cfg;
4613        LANPage0_t                *ppage0_alloc;
4614        dma_addr_t                 page0_dma;
4615        LANPage1_t                *ppage1_alloc;
4616        dma_addr_t                 page1_dma;
4617        int                         rc = 0;
4618        int                         data_sz;
4619        int                         copy_sz;
4620
4621        /* Get LAN Page 0 header */
4622        hdr.PageVersion = 0;
4623        hdr.PageLength = 0;
4624        hdr.PageNumber = 0;
4625        hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4626        cfg.cfghdr.hdr = &hdr;
4627        cfg.physAddr = -1;
4628        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4629        cfg.dir = 0;
4630        cfg.pageAddr = 0;
4631        cfg.timeout = 0;
4632
4633        if ((rc = mpt_config(ioc, &cfg)) != 0)
4634                return rc;
4635
4636        if (hdr.PageLength > 0) {
4637                data_sz = hdr.PageLength * 4;
4638                ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
4639                rc = -ENOMEM;
4640                if (ppage0_alloc) {
4641                        memset((u8 *)ppage0_alloc, 0, data_sz);
4642                        cfg.physAddr = page0_dma;
4643                        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4644
4645                        if ((rc = mpt_config(ioc, &cfg)) == 0) {
4646                                /* save the data */
4647                                copy_sz = min_t(int, sizeof(LANPage0_t), data_sz);
4648                                memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz);
4649
4650                        }
4651
4652                        pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
4653
4654                        /* FIXME!
4655                         *        Normalize endianness of structure data,
4656                         *        by byte-swapping all > 1 byte fields!
4657                         */
4658
4659                }
4660
4661                if (rc)
4662                        return rc;
4663        }
4664
4665        /* Get LAN Page 1 header */
4666        hdr.PageVersion = 0;
4667        hdr.PageLength = 0;
4668        hdr.PageNumber = 1;
4669        hdr.PageType = MPI_CONFIG_PAGETYPE_LAN;
4670        cfg.cfghdr.hdr = &hdr;
4671        cfg.physAddr = -1;
4672        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4673        cfg.dir = 0;
4674        cfg.pageAddr = 0;
4675
4676        if ((rc = mpt_config(ioc, &cfg)) != 0)
4677                return rc;
4678
4679        if (hdr.PageLength == 0)
4680                return 0;
4681
4682        data_sz = hdr.PageLength * 4;
4683        rc = -ENOMEM;
4684        ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma);
4685        if (ppage1_alloc) {
4686                memset((u8 *)ppage1_alloc, 0, data_sz);
4687                cfg.physAddr = page1_dma;
4688                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4689
4690                if ((rc = mpt_config(ioc, &cfg)) == 0) {
4691                        /* save the data */
4692                        copy_sz = min_t(int, sizeof(LANPage1_t), data_sz);
4693                        memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz);
4694                }
4695
4696                pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma);
4697
4698                /* FIXME!
4699                 *        Normalize endianness of structure data,
4700                 *        by byte-swapping all > 1 byte fields!
4701                 */
4702
4703        }
4704
4705        return rc;
4706}
4707
4708/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4709/**
4710 *        mptbase_sas_persist_operation - Perform operation on SAS Persistent Table
4711 *        @ioc: Pointer to MPT_ADAPTER structure
4712 *        @persist_opcode: see below
4713 *
4714 *        MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for
4715 *                devices not currently present.
4716 *        MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings
4717 *
4718 *        NOTE: Don't use not this function during interrupt time.
4719 *
4720 *        Returns 0 for success, non-zero error
4721 */
4722
4723/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4724int
4725mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)
4726{
4727        SasIoUnitControlRequest_t        *sasIoUnitCntrReq;
4728        SasIoUnitControlReply_t                *sasIoUnitCntrReply;
4729        MPT_FRAME_HDR                        *mf = NULL;
4730        MPIHeader_t                        *mpi_hdr;
4731
4732
4733        /* insure garbage is not sent to fw */
4734        switch(persist_opcode) {
4735
4736        case MPI_SAS_OP_CLEAR_NOT_PRESENT:
4737        case MPI_SAS_OP_CLEAR_ALL_PERSISTENT:
4738                break;
4739
4740        default:
4741                return -1;
4742                break;
4743        }
4744
4745        printk("%s: persist_opcode=%x\n",__func__, persist_opcode);
4746
4747        /* Get a MF for this command.
4748         */
4749        if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
4750                printk("%s: no msg frames!\n",__func__);
4751                return -1;
4752        }
4753
4754        mpi_hdr = (MPIHeader_t *) mf;
4755        sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf;
4756        memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t));
4757        sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
4758        sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext;
4759        sasIoUnitCntrReq->Operation = persist_opcode;
4760
4761        init_timer(&ioc->persist_timer);
4762        ioc->persist_timer.data = (unsigned long) ioc;
4763        ioc->persist_timer.function = mpt_timer_expired;
4764        ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */;
4765        ioc->persist_wait_done=0;
4766        add_timer(&ioc->persist_timer);
4767        mpt_put_msg_frame(mpt_base_index, ioc, mf);
4768        wait_event(mpt_waitq, ioc->persist_wait_done);
4769
4770        sasIoUnitCntrReply =
4771            (SasIoUnitControlReply_t *)ioc->persist_reply_frame;
4772        if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) {
4773                printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
4774                    __func__,
4775                    sasIoUnitCntrReply->IOCStatus,
4776                    sasIoUnitCntrReply->IOCLogInfo);
4777                return -1;
4778        }
4779
4780        printk("%s: success\n",__func__);
4781        return 0;
4782}
4783
4784/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4785
4786static void
4787mptbase_raid_process_event_data(MPT_ADAPTER *ioc,
4788    MpiEventDataRaid_t * pRaidEventData)
4789{
4790        int         volume;
4791        int         reason;
4792        int         disk;
4793        int         status;
4794        int         flags;
4795        int         state;
4796
4797        volume        = pRaidEventData->VolumeID;
4798        reason        = pRaidEventData->ReasonCode;
4799        disk        = pRaidEventData->PhysDiskNum;
4800        status        = le32_to_cpu(pRaidEventData->SettingsStatus);
4801        flags        = (status >> 0) & 0xff;
4802        state        = (status >> 8) & 0xff;
4803
4804        if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
4805                return;
4806        }
4807
4808        if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED &&
4809             reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) ||
4810            (reason == MPI_EVENT_RAID_RC_SMART_DATA)) {
4811                printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n",
4812                        ioc->name, disk, volume);
4813        } else {
4814                printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n",
4815                        ioc->name, volume);
4816        }
4817
4818        switch(reason) {
4819        case MPI_EVENT_RAID_RC_VOLUME_CREATED:
4820                printk(MYIOC_s_INFO_FMT "  volume has been created\n",
4821                        ioc->name);
4822                break;
4823
4824        case MPI_EVENT_RAID_RC_VOLUME_DELETED:
4825
4826                printk(MYIOC_s_INFO_FMT "  volume has been deleted\n",
4827                        ioc->name);
4828                break;
4829
4830        case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
4831                printk(MYIOC_s_INFO_FMT "  volume settings have been changed\n",
4832                        ioc->name);
4833                break;
4834
4835        case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
4836                printk(MYIOC_s_INFO_FMT "  volume is now %s%s%s%s\n",
4837                        ioc->name,
4838                        state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL
4839                         ? "optimal"
4840                         : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED
4841                          ? "degraded"
4842                          : state == MPI_RAIDVOL0_STATUS_STATE_FAILED
4843                           ? "failed"
4844                           : "state unknown",
4845                        flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED
4846                         ? ", enabled" : "",
4847                        flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED
4848                         ? ", quiesced" : "",
4849                        flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
4850                         ? ", resync in progress" : "" );
4851                break;
4852
4853        case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
4854                printk(MYIOC_s_INFO_FMT "  volume membership of PhysDisk %d has changed\n",
4855                        ioc->name, disk);
4856                break;
4857
4858        case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
4859                printk(MYIOC_s_INFO_FMT "  PhysDisk has been created\n",
4860                        ioc->name);
4861                break;
4862
4863        case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
4864                printk(MYIOC_s_INFO_FMT "  PhysDisk has been deleted\n",
4865                        ioc->name);
4866                break;
4867
4868        case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
4869                printk(MYIOC_s_INFO_FMT "  PhysDisk settings have been changed\n",
4870                        ioc->name);
4871                break;
4872
4873        case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4874                printk(MYIOC_s_INFO_FMT "  PhysDisk is now %s%s%s\n",
4875                        ioc->name,
4876                        state == MPI_PHYSDISK0_STATUS_ONLINE
4877                         ? "online"
4878                         : state == MPI_PHYSDISK0_STATUS_MISSING
4879                          ? "missing"
4880                          : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE
4881                           ? "not compatible"
4882                           : state == MPI_PHYSDISK0_STATUS_FAILED
4883                            ? "failed"
4884                            : state == MPI_PHYSDISK0_STATUS_INITIALIZING
4885                             ? "initializing"
4886                             : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED
4887                              ? "offline requested"
4888                              : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED
4889                               ? "failed requested"
4890                               : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE
4891                                ? "offline"
4892                                : "state unknown",
4893                        flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
4894                         ? ", out of sync" : "",
4895                        flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED
4896                         ? ", quiesced" : "" );
4897                break;
4898
4899        case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
4900                printk(MYIOC_s_INFO_FMT "  Domain Validation needed for PhysDisk %d\n",
4901                        ioc->name, disk);
4902                break;
4903
4904        case MPI_EVENT_RAID_RC_SMART_DATA:
4905                printk(MYIOC_s_INFO_FMT "  SMART data received, ASC/ASCQ = %02xh/%02xh\n",
4906                        ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ);
4907                break;
4908
4909        case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
4910                printk(MYIOC_s_INFO_FMT "  replacement of PhysDisk %d has started\n",
4911                        ioc->name, disk);
4912                break;
4913        }
4914}
4915
4916/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4917/**
4918 *        GetIoUnitPage2 - Retrieve BIOS version and boot order information.
4919 *        @ioc: Pointer to MPT_ADAPTER structure
4920 *
4921 *        Returns: 0 for success
4922 *        -ENOMEM if no memory available
4923 *                -EPERM if not allowed due to ISR context
4924 *                -EAGAIN if no msg frames currently available
4925 *                -EFAULT for non-successful reply or no reply (timeout)
4926 */
4927static int
4928GetIoUnitPage2(MPT_ADAPTER *ioc)
4929{
4930        ConfigPageHeader_t         hdr;
4931        CONFIGPARMS                 cfg;
4932        IOUnitPage2_t                *ppage_alloc;
4933        dma_addr_t                 page_dma;
4934        int                         data_sz;
4935        int                         rc;
4936
4937        /* Get the page header */
4938        hdr.PageVersion = 0;
4939        hdr.PageLength = 0;
4940        hdr.PageNumber = 2;
4941        hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT;
4942        cfg.cfghdr.hdr = &hdr;
4943        cfg.physAddr = -1;
4944        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4945        cfg.dir = 0;
4946        cfg.pageAddr = 0;
4947        cfg.timeout = 0;
4948
4949        if ((rc = mpt_config(ioc, &cfg)) != 0)
4950                return rc;
4951
4952        if (hdr.PageLength == 0)
4953                return 0;
4954
4955        /* Read the config page */
4956        data_sz = hdr.PageLength * 4;
4957        rc = -ENOMEM;
4958        ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma);
4959        if (ppage_alloc) {
4960                memset((u8 *)ppage_alloc, 0, data_sz);
4961                cfg.physAddr = page_dma;
4962                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4963
4964                /* If Good, save data */
4965                if ((rc = mpt_config(ioc, &cfg)) == 0)
4966                        ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion);
4967
4968                pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma);
4969        }
4970
4971        return rc;
4972}
4973
4974/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4975/**
4976 *        mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2
4977 *        @ioc: Pointer to a Adapter Strucutre
4978 *        @portnum: IOC port number
4979 *
4980 *        Return: -EFAULT if read of config page header fails
4981 *                        or if no nvram
4982 *        If read of SCSI Port Page 0 fails,
4983 *                NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4984 *                Adapter settings: async, narrow
4985 *                Return 1
4986 *        If read of SCSI Port Page 2 fails,
4987 *                Adapter settings valid
4988 *                NVRAM = MPT_HOST_NVRAM_INVALID  (0xFFFFFFFF)
4989 *                Return 1
4990 *        Else
4991 *                Both valid
4992 *                Return 0
4993 *        CHECK - what type of locking mechanisms should be used????
4994 */
4995static int
4996mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
4997{
4998        u8                        *pbuf;
4999        dma_addr_t                 buf_dma;
5000        CONFIGPARMS                 cfg;
5001        ConfigPageHeader_t         header;
5002        int                         ii;
5003        int                         data, rc = 0;
5004
5005        /* Allocate memory
5006         */
5007        if (!ioc->spi_data.nvram) {
5008                int         sz;
5009                u8        *mem;
5010                sz = MPT_MAX_SCSI_DEVICES * sizeof(int);
5011                mem = kmalloc(sz, GFP_ATOMIC);
5012                if (mem == NULL)
5013                        return -EFAULT;
5014
5015                ioc->spi_data.nvram = (int *) mem;
5016
5017                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n",
5018                        ioc->name, ioc->spi_data.nvram, sz));
5019        }
5020
5021        /* Invalidate NVRAM information
5022         */
5023        for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5024                ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID;
5025        }
5026
5027        /* Read SPP0 header, allocate memory, then read page.
5028         */
5029        header.PageVersion = 0;
5030        header.PageLength = 0;
5031        header.PageNumber = 0;
5032        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5033        cfg.cfghdr.hdr = &header;
5034        cfg.physAddr = -1;
5035        cfg.pageAddr = portnum;
5036        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5037        cfg.dir = 0;
5038        cfg.timeout = 0;        /* use default */
5039        if (mpt_config(ioc, &cfg) != 0)
5040                 return -EFAULT;
5041
5042        if (header.PageLength > 0) {
5043                pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5044                if (pbuf) {
5045                        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5046                        cfg.physAddr = buf_dma;
5047                        if (mpt_config(ioc, &cfg) != 0) {
5048                                ioc->spi_data.maxBusWidth = MPT_NARROW;
5049                                ioc->spi_data.maxSyncOffset = 0;
5050                                ioc->spi_data.minSyncFactor = MPT_ASYNC;
5051                                ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN;
5052                                rc = 1;
5053                                ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5054                                        "Unable to read PortPage0 minSyncFactor=%x\n",
5055                                        ioc->name, ioc->spi_data.minSyncFactor));
5056                        } else {
5057                                /* Save the Port Page 0 data
5058                                 */
5059                                SCSIPortPage0_t  *pPP0 = (SCSIPortPage0_t  *) pbuf;
5060                                pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
5061                                pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
5062
5063                                if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
5064                                        ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
5065                                        ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5066                                                "noQas due to Capabilities=%x\n",
5067                                                ioc->name, pPP0->Capabilities));
5068                                }
5069                                ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
5070                                data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
5071                                if (data) {
5072                                        ioc->spi_data.maxSyncOffset = (u8) (data >> 16);
5073                                        data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK;
5074                                        ioc->spi_data.minSyncFactor = (u8) (data >> 8);
5075                                        ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5076                                                "PortPage0 minSyncFactor=%x\n",
5077                                                ioc->name, ioc->spi_data.minSyncFactor));
5078                                } else {
5079                                        ioc->spi_data.maxSyncOffset = 0;
5080                                        ioc->spi_data.minSyncFactor = MPT_ASYNC;
5081                                }
5082
5083                                ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK;
5084
5085                                /* Update the minSyncFactor based on bus type.
5086                                 */
5087                                if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
5088                                        (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
5089
5090                                        if (ioc->spi_data.minSyncFactor < MPT_ULTRA) {
5091                                                ioc->spi_data.minSyncFactor = MPT_ULTRA;
5092                                                ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5093                                                        "HVD or SE detected, minSyncFactor=%x\n",
5094                                                        ioc->name, ioc->spi_data.minSyncFactor));
5095                                        }
5096                                }
5097                        }
5098                        if (pbuf) {
5099                                pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5100                        }
5101                }
5102        }
5103
5104        /* SCSI Port Page 2 - Read the header then the page.
5105         */
5106        header.PageVersion = 0;
5107        header.PageLength = 0;
5108        header.PageNumber = 2;
5109        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT;
5110        cfg.cfghdr.hdr = &header;
5111        cfg.physAddr = -1;
5112        cfg.pageAddr = portnum;
5113        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5114        cfg.dir = 0;
5115        if (mpt_config(ioc, &cfg) != 0)
5116                return -EFAULT;
5117
5118        if (header.PageLength > 0) {
5119                /* Allocate memory and read SCSI Port Page 2
5120                 */
5121                pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma);
5122                if (pbuf) {
5123                        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM;
5124                        cfg.physAddr = buf_dma;
5125                        if (mpt_config(ioc, &cfg) != 0) {
5126                                /* Nvram data is left with INVALID mark
5127                                 */
5128                                rc = 1;
5129                        } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) {
5130
5131                                /* This is an ATTO adapter, read Page2 accordingly
5132                                */
5133                                ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t  *) pbuf;
5134                                ATTODeviceInfo_t *pdevice = NULL;
5135                                u16 ATTOFlags;
5136
5137                                /* Save the Port Page 2 data
5138                                 * (reformat into a 32bit quantity)
5139                                 */
5140                                for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5141                                  pdevice = &pPP2->DeviceSettings[ii];
5142                                  ATTOFlags = le16_to_cpu(pdevice->ATTOFlags);
5143                                  data = 0;
5144
5145                                  /* Translate ATTO device flags to LSI format
5146                                   */
5147                                  if (ATTOFlags & ATTOFLAG_DISC)
5148                                    data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE);
5149                                  if (ATTOFlags & ATTOFLAG_ID_ENB)
5150                                    data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE);
5151                                  if (ATTOFlags & ATTOFLAG_LUN_ENB)
5152                                    data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE);
5153                                  if (ATTOFlags & ATTOFLAG_TAGGED)
5154                                    data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE);
5155                                  if (!(ATTOFlags & ATTOFLAG_WIDE_ENB))
5156                                    data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE);
5157
5158                                  data = (data << 16) | (pdevice->Period << 8) | 10;
5159                                  ioc->spi_data.nvram[ii] = data;
5160                                }
5161                        } else {
5162                                SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t  *) pbuf;
5163                                MpiDeviceInfo_t        *pdevice = NULL;
5164
5165                                /*
5166                                 * Save "Set to Avoid SCSI Bus Resets" flag
5167                                 */
5168                                ioc->spi_data.bus_reset =
5169                                    (le32_to_cpu(pPP2->PortFlags) &
5170                                MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ?
5171                                    0 : 1 ;
5172
5173                                /* Save the Port Page 2 data
5174                                 * (reformat into a 32bit quantity)
5175                                 */
5176                                data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK;
5177                                ioc->spi_data.PortFlags = data;
5178                                for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5179                                        pdevice = &pPP2->DeviceSettings[ii];
5180                                        data = (le16_to_cpu(pdevice->DeviceFlags) << 16) |
5181                                                (pdevice->SyncFactor << 8) | pdevice->Timeout;
5182                                        ioc->spi_data.nvram[ii] = data;
5183                                }
5184                        }
5185
5186                        pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma);
5187                }
5188        }
5189
5190        /* Update Adapter limits with those from NVRAM
5191         * Comment: Don't need to do this. Target performance
5192         * parameters will never exceed the adapters limits.
5193         */
5194
5195        return rc;
5196}
5197
5198/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5199/**
5200 *        mpt_readScsiDevicePageHeaders - save version and length of SDP1
5201 *        @ioc: Pointer to a Adapter Strucutre
5202 *        @portnum: IOC port number
5203 *
5204 *        Return: -EFAULT if read of config page header fails
5205 *                or 0 if success.
5206 */
5207static int
5208mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum)
5209{
5210        CONFIGPARMS                 cfg;
5211        ConfigPageHeader_t         header;
5212
5213        /* Read the SCSI Device Page 1 header
5214         */
5215        header.PageVersion = 0;
5216        header.PageLength = 0;
5217        header.PageNumber = 1;
5218        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5219        cfg.cfghdr.hdr = &header;
5220        cfg.physAddr = -1;
5221        cfg.pageAddr = portnum;
5222        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5223        cfg.dir = 0;
5224        cfg.timeout = 0;
5225        if (mpt_config(ioc, &cfg) != 0)
5226                 return -EFAULT;
5227
5228        ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion;
5229        ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength;
5230
5231        header.PageVersion = 0;
5232        header.PageLength = 0;
5233        header.PageNumber = 0;
5234        header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5235        if (mpt_config(ioc, &cfg) != 0)
5236                 return -EFAULT;
5237
5238        ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion;
5239        ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength;
5240
5241        dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n",
5242                        ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length));
5243
5244        dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n",
5245                        ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length));
5246        return 0;
5247}
5248
5249/**
5250 * mpt_inactive_raid_list_free - This clears this link list.
5251 * @ioc : pointer to per adapter structure
5252 **/
5253static void
5254mpt_inactive_raid_list_free(MPT_ADAPTER *ioc)
5255{
5256        struct inactive_raid_component_info *component_info, *pNext;
5257
5258        if (list_empty(&ioc->raid_data.inactive_list))
5259                return;
5260
5261        mutex_lock(&ioc->raid_data.inactive_list_mutex);
5262        list_for_each_entry_safe(component_info, pNext,
5263            &ioc->raid_data.inactive_list, list) {
5264                list_del(&component_info->list);
5265                kfree(component_info);
5266        }
5267        mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5268}
5269
5270/**
5271 * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume
5272 *
5273 * @ioc : pointer to per adapter structure
5274 * @channel : volume channel
5275 * @id : volume target id
5276 **/
5277static void
5278mpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id)
5279{
5280        CONFIGPARMS                        cfg;
5281        ConfigPageHeader_t                hdr;
5282        dma_addr_t                        dma_handle;
5283        pRaidVolumePage0_t                buffer = NULL;
5284        int                                i;
5285        RaidPhysDiskPage0_t                 phys_disk;
5286        struct inactive_raid_component_info *component_info;
5287        int                                handle_inactive_volumes;
5288
5289        memset(&cfg, 0 , sizeof(CONFIGPARMS));
5290        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5291        hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
5292        cfg.pageAddr = (channel << 8) + id;
5293        cfg.cfghdr.hdr = &hdr;
5294        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5295
5296        if (mpt_config(ioc, &cfg) != 0)
5297                goto out;
5298
5299        if (!hdr.PageLength)
5300                goto out;
5301
5302        buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5303            &dma_handle);
5304
5305        if (!buffer)
5306                goto out;
5307
5308        cfg.physAddr = dma_handle;
5309        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5310
5311        if (mpt_config(ioc, &cfg) != 0)
5312                goto out;
5313
5314        if (!buffer->NumPhysDisks)
5315                goto out;
5316
5317        handle_inactive_volumes =
5318           (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE ||
5319           (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 ||
5320            buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED ||
5321            buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0;
5322
5323        if (!handle_inactive_volumes)
5324                goto out;
5325
5326        mutex_lock(&ioc->raid_data.inactive_list_mutex);
5327        for (i = 0; i < buffer->NumPhysDisks; i++) {
5328                if(mpt_raid_phys_disk_pg0(ioc,
5329                    buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
5330                        continue;
5331
5332                if ((component_info = kmalloc(sizeof (*component_info),
5333                 GFP_KERNEL)) == NULL)
5334                        continue;
5335
5336                component_info->volumeID = id;
5337                component_info->volumeBus = channel;
5338                component_info->d.PhysDiskNum = phys_disk.PhysDiskNum;
5339                component_info->d.PhysDiskBus = phys_disk.PhysDiskBus;
5340                component_info->d.PhysDiskID = phys_disk.PhysDiskID;
5341                component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC;
5342
5343                list_add_tail(&component_info->list,
5344                    &ioc->raid_data.inactive_list);
5345        }
5346        mutex_unlock(&ioc->raid_data.inactive_list_mutex);
5347
5348 out:
5349        if (buffer)
5350                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5351                    dma_handle);
5352}
5353
5354/**
5355 *        mpt_raid_phys_disk_pg0 - returns phys disk page zero
5356 *        @ioc: Pointer to a Adapter Structure
5357 *        @phys_disk_num: io unit unique phys disk num generated by the ioc
5358 *        @phys_disk: requested payload data returned
5359 *
5360 *        Return:
5361 *        0 on success
5362 *        -EFAULT if read of config page header fails or data pointer not NULL
5363 *        -ENOMEM if pci_alloc failed
5364 **/
5365int
5366mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk)
5367{
5368        CONFIGPARMS                         cfg;
5369        ConfigPageHeader_t                 hdr;
5370        dma_addr_t                        dma_handle;
5371        pRaidPhysDiskPage0_t                buffer = NULL;
5372        int                                rc;
5373
5374        memset(&cfg, 0 , sizeof(CONFIGPARMS));
5375        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5376
5377        hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK;
5378        cfg.cfghdr.hdr = &hdr;
5379        cfg.physAddr = -1;
5380        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5381
5382        if (mpt_config(ioc, &cfg) != 0) {
5383                rc = -EFAULT;
5384                goto out;
5385        }
5386
5387        if (!hdr.PageLength) {
5388                rc = -EFAULT;
5389                goto out;
5390        }
5391
5392        buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
5393            &dma_handle);
5394
5395        if (!buffer) {
5396                rc = -ENOMEM;
5397                goto out;
5398        }
5399
5400        cfg.physAddr = dma_handle;
5401        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5402        cfg.pageAddr = phys_disk_num;
5403
5404        if (mpt_config(ioc, &cfg) != 0) {
5405                rc = -EFAULT;
5406                goto out;
5407        }
5408
5409        rc = 0;
5410        memcpy(phys_disk, buffer, sizeof(*buffer));
5411        phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA);
5412
5413 out:
5414
5415        if (buffer)
5416                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
5417                    dma_handle);
5418
5419        return rc;
5420}
5421
5422/**
5423 *        mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes
5424 *        @ioc: Pointer to a Adapter Strucutre
5425 *        @portnum: IOC port number
5426 *
5427 *        Return:
5428 *        0 on success
5429 *        -EFAULT if read of config page header fails or data pointer not NULL
5430 *        -ENOMEM if pci_alloc failed
5431 **/
5432int
5433mpt_findImVolumes(MPT_ADAPTER *ioc)
5434{
5435        IOCPage2_t                *pIoc2;
5436        u8                        *mem;
5437        dma_addr_t                 ioc2_dma;
5438        CONFIGPARMS                 cfg;
5439        ConfigPageHeader_t         header;
5440        int                         rc = 0;
5441        int                         iocpage2sz;
5442        int                         i;
5443
5444        if (!ioc->ir_firmware)
5445                return 0;
5446
5447        /* Free the old page
5448         */
5449        kfree(ioc->raid_data.pIocPg2);
5450        ioc->raid_data.pIocPg2 = NULL;
5451        mpt_inactive_raid_list_free(ioc);
5452
5453        /* Read IOCP2 header then the page.
5454         */
5455        header.PageVersion = 0;
5456        header.PageLength = 0;
5457        header.PageNumber = 2;
5458        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5459        cfg.cfghdr.hdr = &header;
5460        cfg.physAddr = -1;
5461        cfg.pageAddr = 0;
5462        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5463        cfg.dir = 0;
5464        cfg.timeout = 0;
5465        if (mpt_config(ioc, &cfg) != 0)
5466                 return -EFAULT;
5467
5468        if (header.PageLength == 0)
5469                return -EFAULT;
5470
5471        iocpage2sz = header.PageLength * 4;
5472        pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma);
5473        if (!pIoc2)
5474                return -ENOMEM;
5475
5476        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5477        cfg.physAddr = ioc2_dma;
5478        if (mpt_config(ioc, &cfg) != 0)
5479                goto out;
5480
5481        mem = kmalloc(iocpage2sz, GFP_KERNEL);
5482        if (!mem)
5483                goto out;
5484
5485        memcpy(mem, (u8 *)pIoc2, iocpage2sz);
5486        ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem;
5487
5488        mpt_read_ioc_pg_3(ioc);
5489
5490        for (i = 0; i < pIoc2->NumActiveVolumes ; i++)
5491                mpt_inactive_raid_volumes(ioc,
5492                    pIoc2->RaidVolume[i].VolumeBus,
5493                    pIoc2->RaidVolume[i].VolumeID);
5494
5495 out:
5496        pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma);
5497
5498        return rc;
5499}
5500
5501static int
5502mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
5503{
5504        IOCPage3_t                *pIoc3;
5505        u8                        *mem;
5506        CONFIGPARMS                 cfg;
5507        ConfigPageHeader_t         header;
5508        dma_addr_t                 ioc3_dma;
5509        int                         iocpage3sz = 0;
5510
5511        /* Free the old page
5512         */
5513        kfree(ioc->raid_data.pIocPg3);
5514        ioc->raid_data.pIocPg3 = NULL;
5515
5516        /* There is at least one physical disk.
5517         * Read and save IOC Page 3
5518         */
5519        header.PageVersion = 0;
5520        header.PageLength = 0;
5521        header.PageNumber = 3;
5522        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5523        cfg.cfghdr.hdr = &header;
5524        cfg.physAddr = -1;
5525        cfg.pageAddr = 0;
5526        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5527        cfg.dir = 0;
5528        cfg.timeout = 0;
5529        if (mpt_config(ioc, &cfg) != 0)
5530                return 0;
5531
5532        if (header.PageLength == 0)
5533                return 0;
5534
5535        /* Read Header good, alloc memory
5536         */
5537        iocpage3sz = header.PageLength * 4;
5538        pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma);
5539        if (!pIoc3)
5540                return 0;
5541
5542        /* Read the Page and save the data
5543         * into malloc'd memory.
5544         */
5545        cfg.physAddr = ioc3_dma;
5546        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5547        if (mpt_config(ioc, &cfg) == 0) {
5548                mem = kmalloc(iocpage3sz, GFP_KERNEL);
5549                if (mem) {
5550                        memcpy(mem, (u8 *)pIoc3, iocpage3sz);
5551                        ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem;
5552                }
5553        }
5554
5555        pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma);
5556
5557        return 0;
5558}
5559
5560static void
5561mpt_read_ioc_pg_4(MPT_ADAPTER *ioc)
5562{
5563        IOCPage4_t                *pIoc4;
5564        CONFIGPARMS                 cfg;
5565        ConfigPageHeader_t         header;
5566        dma_addr_t                 ioc4_dma;
5567        int                         iocpage4sz;
5568
5569        /* Read and save IOC Page 4
5570         */
5571        header.PageVersion = 0;
5572        header.PageLength = 0;
5573        header.PageNumber = 4;
5574        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5575        cfg.cfghdr.hdr = &header;
5576        cfg.physAddr = -1;
5577        cfg.pageAddr = 0;
5578        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5579        cfg.dir = 0;
5580        cfg.timeout = 0;
5581        if (mpt_config(ioc, &cfg) != 0)
5582                return;
5583
5584        if (header.PageLength == 0)
5585                return;
5586
5587        if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) {
5588                iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */
5589                pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma);
5590                if (!pIoc4)
5591                        return;
5592                ioc->alloc_total += iocpage4sz;
5593        } else {
5594                ioc4_dma = ioc->spi_data.IocPg4_dma;
5595                iocpage4sz = ioc->spi_data.IocPg4Sz;
5596        }
5597
5598        /* Read the Page into dma memory.
5599         */
5600        cfg.physAddr = ioc4_dma;
5601        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5602        if (mpt_config(ioc, &cfg) == 0) {
5603                ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4;
5604                ioc->spi_data.IocPg4_dma = ioc4_dma;
5605                ioc->spi_data.IocPg4Sz = iocpage4sz;
5606        } else {
5607                pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma);
5608                ioc->spi_data.pIocPg4 = NULL;
5609                ioc->alloc_total -= iocpage4sz;
5610        }
5611}
5612
5613static void
5614mpt_read_ioc_pg_1(MPT_ADAPTER *ioc)
5615{
5616        IOCPage1_t                *pIoc1;
5617        CONFIGPARMS                 cfg;
5618        ConfigPageHeader_t         header;
5619        dma_addr_t                 ioc1_dma;
5620        int                         iocpage1sz = 0;
5621        u32                         tmp;
5622
5623        /* Check the Coalescing Timeout in IOC Page 1
5624         */
5625        header.PageVersion = 0;
5626        header.PageLength = 0;
5627        header.PageNumber = 1;
5628        header.PageType = MPI_CONFIG_PAGETYPE_IOC;
5629        cfg.cfghdr.hdr = &header;
5630        cfg.physAddr = -1;
5631        cfg.pageAddr = 0;
5632        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5633        cfg.dir = 0;
5634        cfg.timeout = 0;
5635        if (mpt_config(ioc, &cfg) != 0)
5636                return;
5637
5638        if (header.PageLength == 0)
5639                return;
5640
5641        /* Read Header good, alloc memory
5642         */
5643        iocpage1sz = header.PageLength * 4;
5644        pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma);
5645        if (!pIoc1)
5646                return;
5647
5648        /* Read the Page and check coalescing timeout
5649         */
5650        cfg.physAddr = ioc1_dma;
5651        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5652        if (mpt_config(ioc, &cfg) == 0) {
5653
5654                tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING;
5655                if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) {
5656                        tmp = le32_to_cpu(pIoc1->CoalescingTimeout);
5657
5658                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n",
5659                                        ioc->name, tmp));
5660
5661                        if (tmp > MPT_COALESCING_TIMEOUT) {
5662                                pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT);
5663
5664                                /* Write NVRAM and current
5665                                 */
5666                                cfg.dir = 1;
5667                                cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5668                                if (mpt_config(ioc, &cfg) == 0) {
5669                                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n",
5670                                                        ioc->name, MPT_COALESCING_TIMEOUT));
5671
5672                                        cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM;
5673                                        if (mpt_config(ioc, &cfg) == 0) {
5674                                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5675                                                                "Reset NVRAM Coalescing Timeout to = %d\n",
5676                                                                ioc->name, MPT_COALESCING_TIMEOUT));
5677                                        } else {
5678                                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5679                                                                "Reset NVRAM Coalescing Timeout Failed\n",
5680                                                                ioc->name));
5681                                        }
5682
5683                                } else {
5684                                        dprintk(ioc, printk(MYIOC_s_WARN_FMT
5685                                                "Reset of Current Coalescing Timeout Failed!\n",
5686                                                ioc->name));
5687                                }
5688                        }
5689
5690                } else {
5691                        dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name));
5692                }
5693        }
5694
5695        pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma);
5696
5697        return;
5698}
5699
5700static void
5701mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
5702{
5703        CONFIGPARMS                cfg;
5704        ConfigPageHeader_t        hdr;
5705        dma_addr_t                buf_dma;
5706        ManufacturingPage0_t        *pbuf = NULL;
5707
5708        memset(&cfg, 0 , sizeof(CONFIGPARMS));
5709        memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
5710
5711        hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING;
5712        cfg.cfghdr.hdr = &hdr;
5713        cfg.physAddr = -1;
5714        cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
5715        cfg.timeout = 10;
5716
5717        if (mpt_config(ioc, &cfg) != 0)
5718                goto out;
5719
5720        if (!cfg.cfghdr.hdr->PageLength)
5721                goto out;
5722
5723        cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
5724        pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma);
5725        if (!pbuf)
5726                goto out;
5727
5728        cfg.physAddr = buf_dma;
5729
5730        if (mpt_config(ioc, &cfg) != 0)
5731                goto out;
5732
5733        memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name));
5734        memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
5735        memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
5736
5737        out:
5738
5739        if (pbuf)
5740                pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
5741}
5742
5743/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5744/**
5745 *        SendEventNotification - Send EventNotification (on or off) request to adapter
5746 *        @ioc: Pointer to MPT_ADAPTER structure
5747 *        @EvSwitch: Event switch flags
5748 */
5749static int
5750SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch)
5751{
5752        EventNotification_t        *evnp;
5753
5754        evnp = (EventNotification_t *) mpt_get_msg_frame(mpt_base_index, ioc);
5755        if (evnp == NULL) {
5756                devtverboseprintk(ioc, printk(MYIOC_s_WARN_FMT "Unable to allocate event request frame!\n",
5757                                ioc->name));
5758                return 0;
5759        }
5760        memset(evnp, 0, sizeof(*evnp));
5761
5762        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventNotification (%d) request %p\n", ioc->name, EvSwitch, evnp));
5763
5764        evnp->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
5765        evnp->ChainOffset = 0;
5766        evnp->MsgFlags = 0;
5767        evnp->Switch = EvSwitch;
5768
5769        mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)evnp);
5770
5771        return 0;
5772}
5773
5774/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5775/**
5776 *        SendEventAck - Send EventAck request to MPT adapter.
5777 *        @ioc: Pointer to MPT_ADAPTER structure
5778 *        @evnp: Pointer to original EventNotification request
5779 */
5780static int
5781SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp)
5782{
5783        EventAck_t        *pAck;
5784
5785        if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5786                dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n",
5787                    ioc->name,__func__));
5788                return -1;
5789        }
5790
5791        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name));
5792
5793        pAck->Function     = MPI_FUNCTION_EVENT_ACK;
5794        pAck->ChainOffset  = 0;
5795        pAck->Reserved[0]  = pAck->Reserved[1] = 0;
5796        pAck->MsgFlags     = 0;
5797        pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0;
5798        pAck->Event        = evnp->Event;
5799        pAck->EventContext = evnp->EventContext;
5800
5801        mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck);
5802
5803        return 0;
5804}
5805
5806/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5807/**
5808 *        mpt_config - Generic function to issue config message
5809 *        @ioc:   Pointer to an adapter structure
5810 *        @pCfg:  Pointer to a configuration structure. Struct contains
5811 *                action, page address, direction, physical address
5812 *                and pointer to a configuration page header
5813 *                Page header is updated.
5814 *
5815 *        Returns 0 for success
5816 *        -EPERM if not allowed due to ISR context
5817 *        -EAGAIN if no msg frames currently available
5818 *        -EFAULT for non-successful reply or no reply (timeout)
5819 */
5820int
5821mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
5822{
5823        Config_t        *pReq;
5824        ConfigExtendedPageHeader_t  *pExtHdr = NULL;
5825        MPT_FRAME_HDR        *mf;
5826        unsigned long         flags;
5827        int                 ii, rc;
5828        int                 flagsLength;
5829        int                 in_isr;
5830
5831        /*        Prevent calling wait_event() (below), if caller happens
5832         *        to be in ISR context, because that is fatal!
5833         */
5834        in_isr = in_interrupt();
5835        if (in_isr) {
5836                dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n",
5837                                ioc->name));
5838                return -EPERM;
5839        }
5840
5841        /* Get and Populate a free Frame
5842         */
5843        if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) {
5844                dcprintk(ioc, printk(MYIOC_s_WARN_FMT "mpt_config: no msg frames!\n",
5845                                ioc->name));
5846                return -EAGAIN;
5847        }
5848        pReq = (Config_t *)mf;
5849        pReq->Action = pCfg->action;
5850        pReq->Reserved = 0;
5851        pReq->ChainOffset = 0;
5852        pReq->Function = MPI_FUNCTION_CONFIG;
5853
5854        /* Assume page type is not extended and clear "reserved" fields. */
5855        pReq->ExtPageLength = 0;
5856        pReq->ExtPageType = 0;
5857        pReq->MsgFlags = 0;
5858
5859        for (ii=0; ii < 8; ii++)
5860                pReq->Reserved2[ii] = 0;
5861
5862        pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion;
5863        pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength;
5864        pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber;
5865        pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
5866
5867        if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5868                pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr;
5869                pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength);
5870                pReq->ExtPageType = pExtHdr->ExtPageType;
5871                pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
5872
5873                /* Page Length must be treated as a reserved field for the extended header. */
5874                pReq->Header.PageLength = 0;
5875        }
5876
5877        pReq->PageAddress = cpu_to_le32(pCfg->pageAddr);
5878
5879        /* Add a SGE to the config request.
5880         */
5881        if (pCfg->dir)
5882                flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE;
5883        else
5884                flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
5885
5886        if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) {
5887                flagsLength |= pExtHdr->ExtPageLength * 4;
5888
5889                dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5890                        ioc->name, pReq->ExtPageType, pReq->Header.PageNumber, pReq->Action));
5891        }
5892        else {
5893                flagsLength |= pCfg->cfghdr.hdr->PageLength * 4;
5894
5895                dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Config request type %d, page %d and action %d\n",
5896                        ioc->name, pReq->Header.PageType, pReq->Header.PageNumber, pReq->Action));
5897        }
5898
5899        mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr);
5900
5901        /* Append pCfg pointer to end of mf
5902         */
5903        *((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
5904
5905        /* Initalize the timer
5906         */
5907        init_timer(&pCfg->timer);
5908        pCfg->timer.data = (unsigned long) ioc;
5909        pCfg->timer.function = mpt_timer_expired;
5910        pCfg->wait_done = 0;
5911
5912        /* Set the timer; ensure 10 second minimum */
5913        if (pCfg->timeout < 10)
5914                pCfg->timer.expires = jiffies + HZ*10;
5915        else
5916                pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
5917
5918        /* Add to end of Q, set timer and then issue this command */
5919        spin_lock_irqsave(&ioc->FreeQlock, flags);
5920        list_add_tail(&pCfg->linkage, &ioc->configQ);
5921        spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5922
5923        add_timer(&pCfg->timer);
5924        mpt_put_msg_frame(mpt_base_index, ioc, mf);
5925        wait_event(mpt_waitq, pCfg->wait_done);
5926
5927        /* mf has been freed - do not access */
5928
5929        rc = pCfg->status;
5930
5931        return rc;
5932}
5933
5934/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5935/**
5936 *        mpt_timer_expired - Callback for timer process.
5937 *        Used only internal config functionality.
5938 *        @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5939 */
5940static void
5941mpt_timer_expired(unsigned long data)
5942{
5943        MPT_ADAPTER *ioc = (MPT_ADAPTER *) data;
5944
5945        dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired! \n", ioc->name));
5946
5947        /* Perform a FW reload */
5948        if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
5949                printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name);
5950
5951        /* No more processing.
5952         * Hard reset clean-up will wake up
5953         * process and free all resources.
5954         */
5955        dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_timer_expired complete!\n", ioc->name));
5956
5957        return;
5958}
5959
5960/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5961/**
5962 *        mpt_ioc_reset - Base cleanup for hard reset
5963 *        @ioc: Pointer to the adapter structure
5964 *        @reset_phase: Indicates pre- or post-reset functionality
5965 *
5966 *        Remark: Frees resources with internally generated commands.
5967 */
5968static int
5969mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
5970{
5971        CONFIGPARMS *pCfg;
5972        unsigned long flags;
5973
5974        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5975            ": IOC %s_reset routed to MPT base driver!\n",
5976            ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
5977            reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
5978
5979        if (reset_phase == MPT_IOC_SETUP_RESET) {
5980                ;
5981        } else if (reset_phase == MPT_IOC_PRE_RESET) {
5982                /* If the internal config Q is not empty -
5983                 * delete timer. MF resources will be freed when
5984                 * the FIFO's are primed.
5985                 */
5986                spin_lock_irqsave(&ioc->FreeQlock, flags);
5987                list_for_each_entry(pCfg, &ioc->configQ, linkage)
5988                        del_timer(&pCfg->timer);
5989                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5990
5991        } else {
5992                CONFIGPARMS *pNext;
5993
5994                /* Search the configQ for internal commands.
5995                 * Flush the Q, and wake up all suspended threads.
5996                 */
5997                spin_lock_irqsave(&ioc->FreeQlock, flags);
5998                list_for_each_entry_safe(pCfg, pNext, &ioc->configQ, linkage) {
5999                        list_del(&pCfg->linkage);
6000
6001                        pCfg->status = MPT_CONFIG_ERROR;
6002                        pCfg->wait_done = 1;
6003                        wake_up(&mpt_waitq);
6004                }
6005                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
6006        }
6007
6008        return 1;                /* currently means nothing really */
6009}
6010
6011
6012#ifdef CONFIG_PROC_FS                /* { */
6013/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6014/*
6015 *        procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff...
6016 */
6017/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6018/**
6019 *        procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries.
6020 *
6021 *        Returns 0 for success, non-zero for failure.
6022 */
6023static int
6024procmpt_create(void)
6025{
6026        struct proc_dir_entry        *ent;
6027
6028        mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL);
6029        if (mpt_proc_root_dir == NULL)
6030                return -ENOTDIR;
6031
6032        ent = create_proc_entry("summary", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6033        if (ent)
6034                ent->read_proc = procmpt_summary_read;
6035
6036        ent = create_proc_entry("version", S_IFREG|S_IRUGO, mpt_proc_root_dir);
6037        if (ent)
6038                ent->read_proc = procmpt_version_read;
6039
6040        return 0;
6041}
6042
6043/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6044/**
6045 *        procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6046 *
6047 *        Returns 0 for success, non-zero for failure.
6048 */
6049static void
6050procmpt_destroy(void)
6051{
6052        remove_proc_entry("version", mpt_proc_root_dir);
6053        remove_proc_entry("summary", mpt_proc_root_dir);
6054        remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6055}
6056
6057/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6058/**
6059 *        procmpt_summary_read - Handle read request of a summary file
6060 *        @buf: Pointer to area to write information
6061 *        @start: Pointer to start pointer
6062 *        @offset: Offset to start writing
6063 *        @request: Amount of read data requested
6064 *        @eof: Pointer to EOF integer
6065 *        @data: Pointer
6066 *
6067 *        Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6068 *        Returns number of characters written to process performing the read.
6069 */
6070static int
6071procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6072{
6073        MPT_ADAPTER *ioc;
6074        char *out = buf;
6075        int len;
6076
6077        if (data) {
6078                int more = 0;
6079
6080                ioc = data;
6081                mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6082
6083                out += more;
6084        } else {
6085                list_for_each_entry(ioc, &ioc_list, list) {
6086                        int        more = 0;
6087
6088                        mpt_print_ioc_summary(ioc, out, &more, 0, 1);
6089
6090                        out += more;
6091                        if ((out-buf) >= request)
6092                                break;
6093                }
6094        }
6095
6096        len = out - buf;
6097
6098        MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6099}
6100
6101/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6102/**
6103 *        procmpt_version_read - Handle read request from /proc/mpt/version.
6104 *        @buf: Pointer to area to write information
6105 *        @start: Pointer to start pointer
6106 *        @offset: Offset to start writing
6107 *        @request: Amount of read data requested
6108 *        @eof: Pointer to EOF integer
6109 *        @data: Pointer
6110 *
6111 *        Returns number of characters written to process performing the read.
6112 */
6113static int
6114procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6115{
6116        u8         cb_idx;
6117        int         scsi, fc, sas, lan, ctl, targ, dmp;
6118        char        *drvname;
6119        int         len;
6120
6121        len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6122        len += sprintf(buf+len, "  Fusion MPT base driver\n");
6123
6124        scsi = fc = sas = lan = ctl = targ = dmp = 0;
6125        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6126                drvname = NULL;
6127                if (MptCallbacks[cb_idx]) {
6128                        switch (MptDriverClass[cb_idx]) {
6129                        case MPTSPI_DRIVER:
6130                                if (!scsi++) drvname = "SPI host";
6131                                break;
6132                        case MPTFC_DRIVER:
6133                                if (!fc++) drvname = "FC host";
6134                                break;
6135                        case MPTSAS_DRIVER:
6136                                if (!sas++) drvname = "SAS host";
6137                                break;
6138                        case MPTLAN_DRIVER:
6139                                if (!lan++) drvname = "LAN";
6140                                break;
6141                        case MPTSTM_DRIVER:
6142                                if (!targ++) drvname = "SCSI target";
6143                                break;
6144                        case MPTCTL_DRIVER:
6145                                if (!ctl++) drvname = "ioctl";
6146                                break;
6147                        }
6148
6149                        if (drvname)
6150                                len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
6151                }
6152        }
6153
6154        MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6155}
6156
6157/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6158/**
6159 *        procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info.
6160 *        @buf: Pointer to area to write information
6161 *        @start: Pointer to start pointer
6162 *        @offset: Offset to start writing
6163 *        @request: Amount of read data requested
6164 *        @eof: Pointer to EOF integer
6165 *        @data: Pointer
6166 *
6167 *        Returns number of characters written to process performing the read.
6168 */
6169static int
6170procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
6171{
6172        MPT_ADAPTER        *ioc = data;
6173        int                 len;
6174        char                 expVer[32];
6175        int                 sz;
6176        int                 p;
6177
6178        mpt_get_fw_exp_ver(expVer, ioc);
6179
6180        len = sprintf(buf, "%s:", ioc->name);
6181        if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6182                len += sprintf(buf+len, "  (f/w download boot flag set)");
6183//        if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6184//                len += sprintf(buf+len, "  CONFIG_CHECKSUM_FAIL!");
6185
6186        len += sprintf(buf+len, "\n  ProductID = 0x%04x (%s)\n",
6187                        ioc->facts.ProductID,
6188                        ioc->prod_name);
6189        len += sprintf(buf+len, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6190        if (ioc->facts.FWImageSize)
6191                len += sprintf(buf+len, " (fw_size=%d)", ioc->facts.FWImageSize);
6192        len += sprintf(buf+len, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6193        len += sprintf(buf+len, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6194        len += sprintf(buf+len, "  EventState = 0x%02x\n", ioc->facts.EventState);
6195
6196        len += sprintf(buf+len, "  CurrentHostMfaHighAddr = 0x%08x\n",
6197                        ioc->facts.CurrentHostMfaHighAddr);
6198        len += sprintf(buf+len, "  CurrentSenseBufferHighAddr = 0x%08x\n",
6199                        ioc->facts.CurrentSenseBufferHighAddr);
6200
6201        len += sprintf(buf+len, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6202        len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6203
6204        len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6205                                        (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6206        /*
6207         *  Rounding UP to nearest 4-kB boundary here...
6208         */
6209        sz = (ioc->req_sz * ioc->req_depth) + 128;
6210        sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6211        len += sprintf(buf+len, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6212                                        ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6213        len += sprintf(buf+len, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
6214                                        4*ioc->facts.RequestFrameSize,
6215                                        ioc->facts.GlobalCredits);
6216
6217        len += sprintf(buf+len, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
6218                                        (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6219        sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6220        len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6221                                        ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6222        len += sprintf(buf+len, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
6223                                        ioc->facts.CurReplyFrameSize,
6224                                        ioc->facts.ReplyQueueDepth);
6225
6226        len += sprintf(buf+len, "  MaxDevices = %d\n",
6227                        (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6228        len += sprintf(buf+len, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
6229
6230        /* per-port info */
6231        for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6232                len += sprintf(buf+len, "  PortNumber = %d (of %d)\n",
6233                                p+1,
6234                                ioc->facts.NumberOfPorts);
6235                if (ioc->bus_type == FC) {
6236                        if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6237                                u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6238                                len += sprintf(buf+len, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6239                                                a[5], a[4], a[3], a[2], a[1], a[0]);
6240                        }
6241                        len += sprintf(buf+len, "    WWN = %08X%08X:%08X%08X\n",
6242                                        ioc->fc_port_page0[p].WWNN.High,
6243                                        ioc->fc_port_page0[p].WWNN.Low,
6244                                        ioc->fc_port_page0[p].WWPN.High,
6245                                        ioc->fc_port_page0[p].WWPN.Low);
6246                }
6247        }
6248
6249        MPT_PROC_READ_RETURN(buf,start,offset,request,eof,len);
6250}
6251
6252#endif                /* CONFIG_PROC_FS } */
6253
6254/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6255static void
6256mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6257{
6258        buf[0] ='\0';
6259        if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6260                sprintf(buf, " (Exp %02d%02d)",
6261                        (ioc->facts.FWVersion.Word >> 16) & 0x00FF,        /* Month */
6262                        (ioc->facts.FWVersion.Word >> 8) & 0x1F);        /* Day */
6263
6264                /* insider hack! */
6265                if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6266                        strcat(buf, " [MDBG]");
6267        }
6268}
6269
6270/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6271/**
6272 *        mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6273 *        @ioc: Pointer to MPT_ADAPTER structure
6274 *        @buffer: Pointer to buffer where IOC summary info should be written
6275 *        @size: Pointer to number of bytes we wrote (set by this routine)
6276 *        @len: Offset at which to start writing in buffer
6277 *        @showlan: Display LAN stuff?
6278 *
6279 *        This routine writes (english readable) ASCII text, which represents
6280 *        a summary of IOC information, to a buffer.
6281 */
6282void
6283mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6284{
6285        char expVer[32];
6286        int y;
6287
6288        mpt_get_fw_exp_ver(expVer, ioc);
6289
6290        /*
6291         *  Shorter summary of attached ioc's...
6292         */
6293        y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6294                        ioc->name,
6295                        ioc->prod_name,
6296                        MPT_FW_REV_MAGIC_ID_STRING,        /* "FwRev=" or somesuch */
6297                        ioc->facts.FWVersion.Word,
6298                        expVer,
6299                        ioc->facts.NumberOfPorts,
6300                        ioc->req_depth);
6301
6302        if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6303                u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6304                y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6305                        a[5], a[4], a[3], a[2], a[1], a[0]);
6306        }
6307
6308        y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6309
6310        if (!ioc->active)
6311                y += sprintf(buffer+len+y, " (disabled)");
6312
6313        y += sprintf(buffer+len+y, "\n");
6314
6315        *size = y;
6316}
6317
6318/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6319/*
6320 *        Reset Handling
6321 */
6322/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6323/**
6324 *        mpt_HardResetHandler - Generic reset handler
6325 *        @ioc: Pointer to MPT_ADAPTER structure
6326 *        @sleepFlag: Indicates if sleep or schedule must be called.
6327 *
6328 *        Issues SCSI Task Management call based on input arg values.
6329 *        If TaskMgmt fails, returns associated SCSI request.
6330 *
6331 *        Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
6332 *        or a non-interrupt thread.  In the former, must not call schedule().
6333 *
6334 *        Note: A return of -1 is a FATAL error case, as it means a
6335 *        FW reload/initialization failed.
6336 *
6337 *        Returns 0 for SUCCESS or -1 if FAILED.
6338 */
6339int
6340mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
6341{
6342        int                 rc;
6343        unsigned long         flags;
6344
6345        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
6346#ifdef MFCNT
6347        printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
6348        printk("MF count 0x%x !\n", ioc->mfcnt);
6349#endif
6350
6351        /* Reset the adapter. Prevent more than 1 call to
6352         * mpt_do_ioc_recovery at any instant in time.
6353         */
6354        spin_lock_irqsave(&ioc->diagLock, flags);
6355        if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)){
6356                spin_unlock_irqrestore(&ioc->diagLock, flags);
6357                return 0;
6358        } else {
6359                ioc->diagPending = 1;
6360        }
6361        spin_unlock_irqrestore(&ioc->diagLock, flags);
6362
6363        /* FIXME: If do_ioc_recovery fails, repeat....
6364         */
6365
6366        /* The SCSI driver needs to adjust timeouts on all current
6367         * commands prior to the diagnostic reset being issued.
6368         * Prevents timeouts occurring during a diagnostic reset...very bad.
6369         * For all other protocol drivers, this is a no-op.
6370         */
6371        {
6372                u8         cb_idx;
6373                int         r = 0;
6374
6375                for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6376                        if (MptResetHandlers[cb_idx]) {
6377                                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n",
6378                                                ioc->name, cb_idx));
6379                                r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
6380                                if (ioc->alt_ioc) {
6381                                        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n",
6382                                                        ioc->name, ioc->alt_ioc->name, cb_idx));
6383                                        r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
6384                                }
6385                        }
6386                }
6387        }
6388
6389        if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) {
6390                printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc);
6391        }
6392        ioc->reload_fw = 0;
6393        if (ioc->alt_ioc)
6394                ioc->alt_ioc->reload_fw = 0;
6395
6396        spin_lock_irqsave(&ioc->diagLock, flags);
6397        ioc->diagPending = 0;
6398        if (ioc->alt_ioc)
6399                ioc->alt_ioc->diagPending = 0;
6400        spin_unlock_irqrestore(&ioc->diagLock, flags);
6401
6402        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler rc = %d!\n", ioc->name, rc));
6403
6404        return rc;
6405}
6406
6407/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6408static void
6409EventDescriptionStr(u8 event, u32 evData0, char *evStr)
6410{
6411        char *ds = NULL;
6412
6413        switch(event) {
6414        case MPI_EVENT_NONE:
6415                ds = "None";
6416                break;
6417        case MPI_EVENT_LOG_DATA:
6418                ds = "Log Data";
6419                break;
6420        case MPI_EVENT_STATE_CHANGE:
6421                ds = "State Change";
6422                break;
6423        case MPI_EVENT_UNIT_ATTENTION:
6424                ds = "Unit Attention";
6425                break;
6426        case MPI_EVENT_IOC_BUS_RESET:
6427                ds = "IOC Bus Reset";
6428                break;
6429        case MPI_EVENT_EXT_BUS_RESET:
6430                ds = "External Bus Reset";
6431                break;
6432        case MPI_EVENT_RESCAN:
6433                ds = "Bus Rescan Event";
6434                break;
6435        case MPI_EVENT_LINK_STATUS_CHANGE:
6436                if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
6437                        ds = "Link Status(FAILURE) Change";
6438                else
6439                        ds = "Link Status(ACTIVE) Change";
6440                break;
6441        case MPI_EVENT_LOOP_STATE_CHANGE:
6442                if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
6443                        ds = "Loop State(LIP) Change";
6444                else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
6445                        ds = "Loop State(LPE) Change";                /* ??? */
6446                else
6447                        ds = "Loop State(LPB) Change";                /* ??? */
6448                break;
6449        case MPI_EVENT_LOGOUT:
6450                ds = "Logout";
6451                break;
6452        case MPI_EVENT_EVENT_CHANGE:
6453                if (evData0)
6454                        ds = "Events ON";
6455                else
6456                        ds = "Events OFF";
6457                break;
6458        case MPI_EVENT_INTEGRATED_RAID:
6459        {
6460                u8 ReasonCode = (u8)(evData0 >> 16);
6461                switch (ReasonCode) {
6462                case MPI_EVENT_RAID_RC_VOLUME_CREATED :
6463                        ds = "Integrated Raid: Volume Created";
6464                        break;
6465                case MPI_EVENT_RAID_RC_VOLUME_DELETED :
6466                        ds = "Integrated Raid: Volume Deleted";
6467                        break;
6468                case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
6469                        ds = "Integrated Raid: Volume Settings Changed";
6470                        break;
6471                case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
6472                        ds = "Integrated Raid: Volume Status Changed";
6473                        break;
6474                case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
6475                        ds = "Integrated Raid: Volume Physdisk Changed";
6476                        break;
6477                case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
6478                        ds = "Integrated Raid: Physdisk Created";
6479                        break;
6480                case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
6481                        ds = "Integrated Raid: Physdisk Deleted";
6482                        break;
6483                case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
6484                        ds = "Integrated Raid: Physdisk Settings Changed";
6485                        break;
6486                case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
6487                        ds = "Integrated Raid: Physdisk Status Changed";
6488                        break;
6489                case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
6490                        ds = "Integrated Raid: Domain Validation Needed";
6491                        break;
6492                case MPI_EVENT_RAID_RC_SMART_DATA :
6493                        ds = "Integrated Raid; Smart Data";
6494                        break;
6495                case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
6496                        ds = "Integrated Raid: Replace Action Started";
6497                        break;
6498                default:
6499                        ds = "Integrated Raid";
6500                break;
6501                }
6502                break;
6503        }
6504        case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
6505                ds = "SCSI Device Status Change";
6506                break;
6507        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
6508        {
6509                u8 id = (u8)(evData0);
6510                u8 channel = (u8)(evData0 >> 8);
6511                u8 ReasonCode = (u8)(evData0 >> 16);
6512                switch (ReasonCode) {
6513                case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
6514                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6515                            "SAS Device Status Change: Added: "
6516                            "id=%d channel=%d", id, channel);
6517                        break;
6518                case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
6519                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6520                            "SAS Device Status Change: Deleted: "
6521                            "id=%d channel=%d", id, channel);
6522                        break;
6523                case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
6524                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6525                            "SAS Device Status Change: SMART Data: "
6526                            "id=%d channel=%d", id, channel);
6527                        break;
6528                case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
6529                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6530                            "SAS Device Status Change: No Persistancy: "
6531                            "id=%d channel=%d", id, channel);
6532                        break;
6533                case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
6534                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6535                            "SAS Device Status Change: Unsupported Device "
6536                            "Discovered : id=%d channel=%d", id, channel);
6537                        break;
6538                case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
6539                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6540                            "SAS Device Status Change: Internal Device "
6541                            "Reset : id=%d channel=%d", id, channel);
6542                        break;
6543                case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
6544                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6545                            "SAS Device Status Change: Internal Task "
6546                            "Abort : id=%d channel=%d", id, channel);
6547                        break;
6548                case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
6549                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6550                            "SAS Device Status Change: Internal Abort "
6551                            "Task Set : id=%d channel=%d", id, channel);
6552                        break;
6553                case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
6554                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6555                            "SAS Device Status Change: Internal Clear "
6556                            "Task Set : id=%d channel=%d", id, channel);
6557                        break;
6558                case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
6559                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6560                            "SAS Device Status Change: Internal Query "
6561                            "Task : id=%d channel=%d", id, channel);
6562                        break;
6563                default:
6564                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6565                            "SAS Device Status Change: Unknown: "
6566                            "id=%d channel=%d", id, channel);
6567                        break;
6568                }
6569                break;
6570        }
6571        case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
6572                ds = "Bus Timer Expired";
6573                break;
6574        case MPI_EVENT_QUEUE_FULL:
6575        {
6576                u16 curr_depth = (u16)(evData0 >> 16);
6577                u8 channel = (u8)(evData0 >> 8);
6578                u8 id = (u8)(evData0);
6579
6580                snprintf(evStr, EVENT_DESCR_STR_SZ,
6581                   "Queue Full: channel=%d id=%d depth=%d",
6582                   channel, id, curr_depth);
6583                break;
6584        }
6585        case MPI_EVENT_SAS_SES:
6586                ds = "SAS SES Event";
6587                break;
6588        case MPI_EVENT_PERSISTENT_TABLE_FULL:
6589                ds = "Persistent Table Full";
6590                break;
6591        case MPI_EVENT_SAS_PHY_LINK_STATUS:
6592        {
6593                u8 LinkRates = (u8)(evData0 >> 8);
6594                u8 PhyNumber = (u8)(evData0);
6595                LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
6596                        MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
6597                switch (LinkRates) {
6598                case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
6599                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6600                           "SAS PHY Link Status: Phy=%d:"
6601                           " Rate Unknown",PhyNumber);
6602                        break;
6603                case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
6604                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6605                           "SAS PHY Link Status: Phy=%d:"
6606                           " Phy Disabled",PhyNumber);
6607                        break;
6608                case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
6609                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6610                           "SAS PHY Link Status: Phy=%d:"
6611                           " Failed Speed Nego",PhyNumber);
6612                        break;
6613                case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
6614                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6615                           "SAS PHY Link Status: Phy=%d:"
6616                           " Sata OOB Completed",PhyNumber);
6617                        break;
6618                case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
6619                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6620                           "SAS PHY Link Status: Phy=%d:"
6621                           " Rate 1.5 Gbps",PhyNumber);
6622                        break;
6623                case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
6624                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6625                           "SAS PHY Link Status: Phy=%d:"
6626                           " Rate 3.0 Gpbs",PhyNumber);
6627                        break;
6628                default:
6629                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6630                           "SAS PHY Link Status: Phy=%d", PhyNumber);
6631                        break;
6632                }
6633                break;
6634        }
6635        case MPI_EVENT_SAS_DISCOVERY_ERROR:
6636                ds = "SAS Discovery Error";
6637                break;
6638        case MPI_EVENT_IR_RESYNC_UPDATE:
6639        {
6640                u8 resync_complete = (u8)(evData0 >> 16);
6641                snprintf(evStr, EVENT_DESCR_STR_SZ,
6642                    "IR Resync Update: Complete = %d:",resync_complete);
6643                break;
6644        }
6645        case MPI_EVENT_IR2:
6646        {
6647                u8 ReasonCode = (u8)(evData0 >> 16);
6648                switch (ReasonCode) {
6649                case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
6650                        ds = "IR2: LD State Changed";
6651                        break;
6652                case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
6653                        ds = "IR2: PD State Changed";
6654                        break;
6655                case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
6656                        ds = "IR2: Bad Block Table Full";
6657                        break;
6658                case MPI_EVENT_IR2_RC_PD_INSERTED:
6659                        ds = "IR2: PD Inserted";
6660                        break;
6661                case MPI_EVENT_IR2_RC_PD_REMOVED:
6662                        ds = "IR2: PD Removed";
6663                        break;
6664                case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
6665                        ds = "IR2: Foreign CFG Detected";
6666                        break;
6667                case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
6668                        ds = "IR2: Rebuild Medium Error";
6669                        break;
6670                default:
6671                        ds = "IR2";
6672                break;
6673                }
6674                break;
6675        }
6676        case MPI_EVENT_SAS_DISCOVERY:
6677        {
6678                if (evData0)
6679                        ds = "SAS Discovery: Start";
6680                else
6681                        ds = "SAS Discovery: Stop";
6682                break;
6683        }
6684        case MPI_EVENT_LOG_ENTRY_ADDED:
6685                ds = "SAS Log Entry Added";
6686                break;
6687
6688        case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
6689        {
6690                u8 phy_num = (u8)(evData0);
6691                u8 port_num = (u8)(evData0 >> 8);
6692                u8 port_width = (u8)(evData0 >> 16);
6693                u8 primative = (u8)(evData0 >> 24);
6694                snprintf(evStr, EVENT_DESCR_STR_SZ,
6695                    "SAS Broadcase Primative: phy=%d port=%d "
6696                    "width=%d primative=0x%02x",
6697                    phy_num, port_num, port_width, primative);
6698                break;
6699        }
6700
6701        case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
6702        {
6703                u8 reason = (u8)(evData0);
6704                u8 port_num = (u8)(evData0 >> 8);
6705                u16 handle = le16_to_cpu(evData0 >> 16);
6706
6707                snprintf(evStr, EVENT_DESCR_STR_SZ,
6708                    "SAS Initiator Device Status Change: reason=0x%02x "
6709                    "port=%d handle=0x%04x",
6710                    reason, port_num, handle);
6711                break;
6712        }
6713
6714        case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
6715        {
6716                u8 max_init = (u8)(evData0);
6717                u8 current_init = (u8)(evData0 >> 8);
6718
6719                snprintf(evStr, EVENT_DESCR_STR_SZ,
6720                    "SAS Initiator Device Table Overflow: max initiators=%02d "
6721                    "current initators=%02d",
6722                    max_init, current_init);
6723                break;
6724        }
6725        case MPI_EVENT_SAS_SMP_ERROR:
6726        {
6727                u8 status = (u8)(evData0);
6728                u8 port_num = (u8)(evData0 >> 8);
6729                u8 result = (u8)(evData0 >> 16);
6730
6731                if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
6732                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6733                            "SAS SMP Error: port=%d result=0x%02x",
6734                            port_num, result);
6735                else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
6736                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6737                            "SAS SMP Error: port=%d : CRC Error",
6738                            port_num);
6739                else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
6740                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6741                            "SAS SMP Error: port=%d : Timeout",
6742                            port_num);
6743                else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
6744                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6745                            "SAS SMP Error: port=%d : No Destination",
6746                            port_num);
6747                else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
6748                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6749                            "SAS SMP Error: port=%d : Bad Destination",
6750                            port_num);
6751                else
6752                        snprintf(evStr, EVENT_DESCR_STR_SZ,
6753                            "SAS SMP Error: port=%d : status=0x%02x",
6754                            port_num, status);
6755                break;
6756        }
6757
6758        /*
6759         *  MPT base "custom" events may be added here...
6760         */
6761        default:
6762                ds = "Unknown";
6763                break;
6764        }
6765        if (ds)
6766                strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
6767}
6768
6769/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6770/**
6771 *        ProcessEventNotification - Route EventNotificationReply to all event handlers
6772 *        @ioc: Pointer to MPT_ADAPTER structure
6773 *        @pEventReply: Pointer to EventNotification reply frame
6774 *        @evHandlers: Pointer to integer, number of event handlers
6775 *
6776 *        Routes a received EventNotificationReply to all currently registered
6777 *        event handlers.
6778 *        Returns sum of event handlers return values.
6779 */
6780static int
6781ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
6782{
6783        u16 evDataLen;
6784        u32 evData0 = 0;
6785//        u32 evCtx;
6786        int ii;
6787        u8 cb_idx;
6788        int r = 0;
6789        int handlers = 0;
6790        char evStr[EVENT_DESCR_STR_SZ];
6791        u8 event;
6792
6793        /*
6794         *  Do platform normalization of values
6795         */
6796        event = le32_to_cpu(pEventReply->Event) & 0xFF;
6797//        evCtx = le32_to_cpu(pEventReply->EventContext);
6798        evDataLen = le16_to_cpu(pEventReply->EventDataLength);
6799        if (evDataLen) {
6800                evData0 = le32_to_cpu(pEventReply->Data[0]);
6801        }
6802
6803        EventDescriptionStr(event, evData0, evStr);
6804        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event:(%02Xh) : %s\n",
6805                        ioc->name,
6806                        event,
6807                        evStr));
6808
6809#ifdef CONFIG_FUSION_LOGGING
6810        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6811            ": Event data:\n", ioc->name));
6812        for (ii = 0; ii < evDataLen; ii++)
6813                devtverboseprintk(ioc, printk(" %08x",
6814                    le32_to_cpu(pEventReply->Data[ii])));
6815        devtverboseprintk(ioc, printk("\n"));
6816#endif
6817
6818        /*
6819         *  Do general / base driver event processing
6820         */
6821        switch(event) {
6822        case MPI_EVENT_EVENT_CHANGE:                /* 0A */
6823                if (evDataLen) {
6824                        u8 evState = evData0 & 0xFF;
6825
6826                        /* CHECKME! What if evState unexpectedly says OFF (0)? */
6827
6828                        /* Update EventState field in cached IocFacts */
6829                        if (ioc->facts.Function) {
6830                                ioc->facts.EventState = evState;
6831                        }
6832                }
6833                break;
6834        case MPI_EVENT_INTEGRATED_RAID:
6835                mptbase_raid_process_event_data(ioc,
6836                    (MpiEventDataRaid_t *)pEventReply->Data);
6837                break;
6838        default:
6839                break;
6840        }
6841
6842        /*
6843         * Should this event be logged? Events are written sequentially.
6844         * When buffer is full, start again at the top.
6845         */
6846        if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
6847                int idx;
6848
6849                idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
6850
6851                ioc->events[idx].event = event;
6852                ioc->events[idx].eventContext = ioc->eventContext;
6853
6854                for (ii = 0; ii < 2; ii++) {
6855                        if (ii < evDataLen)
6856                                ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
6857                        else
6858                                ioc->events[idx].data[ii] =  0;
6859                }
6860
6861                ioc->eventContext++;
6862        }
6863
6864
6865        /*
6866         *  Call each currently registered protocol event handler.
6867         */
6868        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6869                if (MptEvHandlers[cb_idx]) {
6870                        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n",
6871                                        ioc->name, cb_idx));
6872                        r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
6873                        handlers++;
6874                }
6875        }
6876        /* FIXME?  Examine results here? */
6877
6878        /*
6879         *  If needed, send (a single) EventAck.
6880         */
6881        if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
6882                devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
6883                        "EventAck required\n",ioc->name));
6884                if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
6885                        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
6886                                        ioc->name, ii));
6887                }
6888        }
6889
6890        *evHandlers = handlers;
6891        return r;
6892}
6893
6894/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6895/**
6896 *        mpt_fc_log_info - Log information returned from Fibre Channel IOC.
6897 *        @ioc: Pointer to MPT_ADAPTER structure
6898 *        @log_info: U32 LogInfo reply word from the IOC
6899 *
6900 *        Refer to lsi/mpi_log_fc.h.
6901 */
6902static void
6903mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
6904{
6905        char *desc = "unknown";
6906
6907        switch (log_info & 0xFF000000) {
6908        case MPI_IOCLOGINFO_FC_INIT_BASE:
6909                desc = "FCP Initiator";
6910                break;
6911        case MPI_IOCLOGINFO_FC_TARGET_BASE:
6912                desc = "FCP Target";
6913                break;
6914        case MPI_IOCLOGINFO_FC_LAN_BASE:
6915                desc = "LAN";
6916                break;
6917        case MPI_IOCLOGINFO_FC_MSG_BASE:
6918                desc = "MPI Message Layer";
6919                break;
6920        case MPI_IOCLOGINFO_FC_LINK_BASE:
6921                desc = "FC Link";
6922                break;
6923        case MPI_IOCLOGINFO_FC_CTX_BASE:
6924                desc = "Context Manager";
6925                break;
6926        case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
6927                desc = "Invalid Field Offset";
6928                break;
6929        case MPI_IOCLOGINFO_FC_STATE_CHANGE:
6930                desc = "State Change Info";
6931                break;
6932        }
6933
6934        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
6935                        ioc->name, log_info, desc, (log_info & 0xFFFFFF));
6936}
6937
6938/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6939/**
6940 *        mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
6941 *        @ioc: Pointer to MPT_ADAPTER structure
6942 *        @mr: Pointer to MPT reply frame
6943 *        @log_info: U32 LogInfo word from the IOC
6944 *
6945 *        Refer to lsi/sp_log.h.
6946 */
6947static void
6948mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
6949{
6950        u32 info = log_info & 0x00FF0000;
6951        char *desc = "unknown";
6952
6953        switch (info) {
6954        case 0x00010000:
6955                desc = "bug! MID not found";
6956                if (ioc->reload_fw == 0)
6957                        ioc->reload_fw++;
6958                break;
6959
6960        case 0x00020000:
6961                desc = "Parity Error";
6962                break;
6963
6964        case 0x00030000:
6965                desc = "ASYNC Outbound Overrun";
6966                break;
6967
6968        case 0x00040000:
6969                desc = "SYNC Offset Error";
6970                break;
6971
6972        case 0x00050000:
6973                desc = "BM Change";
6974                break;
6975
6976        case 0x00060000:
6977                desc = "Msg In Overflow";
6978                break;
6979
6980        case 0x00070000:
6981                desc = "DMA Error";
6982                break;
6983
6984        case 0x00080000:
6985                desc = "Outbound DMA Overrun";
6986                break;
6987
6988        case 0x00090000:
6989                desc = "Task Management";
6990                break;
6991
6992        case 0x000A0000:
6993                desc = "Device Problem";
6994                break;
6995
6996        case 0x000B0000:
6997                desc = "Invalid Phase Change";
6998                break;
6999
7000        case 0x000C0000:
7001                desc = "Untagged Table Size";
7002                break;
7003
7004        }
7005
7006        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7007}
7008
7009/* strings for sas loginfo */
7010        static char *originator_str[] = {
7011                "IOP",                                                /* 00h */
7012                "PL",                                                /* 01h */
7013                "IR"                                                /* 02h */
7014        };
7015        static char *iop_code_str[] = {
7016                NULL,                                                /* 00h */
7017                "Invalid SAS Address",                                /* 01h */
7018                NULL,                                                /* 02h */
7019                "Invalid Page",                                        /* 03h */
7020                "Diag Message Error",                                /* 04h */
7021                "Task Terminated",                                /* 05h */
7022                "Enclosure Management",                                /* 06h */
7023                "Target Mode"                                        /* 07h */
7024        };
7025        static char *pl_code_str[] = {
7026                NULL,                                                /* 00h */
7027                "Open Failure",                                        /* 01h */
7028                "Invalid Scatter Gather List",                        /* 02h */
7029                "Wrong Relative Offset or Frame Length",        /* 03h */
7030                "Frame Transfer Error",                                /* 04h */
7031                "Transmit Frame Connected Low",                        /* 05h */
7032                "SATA Non-NCQ RW Error Bit Set",                /* 06h */
7033                "SATA Read Log Receive Data Error",                /* 07h */
7034                "SATA NCQ Fail All Commands After Error",        /* 08h */
7035                "SATA Error in Receive Set Device Bit FIS",        /* 09h */
7036                "Receive Frame Invalid Message",                /* 0Ah */
7037                "Receive Context Message Valid Error",                /* 0Bh */
7038                "Receive Frame Current Frame Error",                /* 0Ch */
7039                "SATA Link Down",                                /* 0Dh */
7040                "Discovery SATA Init W IOS",                        /* 0Eh */
7041                "Config Invalid Page",                                /* 0Fh */
7042                "Discovery SATA Init Timeout",                        /* 10h */
7043                "Reset",                                        /* 11h */
7044                "Abort",                                        /* 12h */
7045                "IO Not Yet Executed",                                /* 13h */
7046                "IO Executed",                                        /* 14h */
7047                "Persistent Reservation Out Not Affiliation "
7048                    "Owner",                                         /* 15h */
7049                "Open Transmit DMA Abort",                        /* 16h */
7050                "IO Device Missing Delay Retry",                /* 17h */
7051                "IO Cancelled Due to Recieve Error",                /* 18h */
7052                NULL,                                                /* 19h */
7053                NULL,                                                /* 1Ah */
7054                NULL,                                                /* 1Bh */
7055                NULL,                                                /* 1Ch */
7056                NULL,                                                /* 1Dh */
7057                NULL,                                                /* 1Eh */
7058                NULL,                                                /* 1Fh */
7059                "Enclosure Management"                                /* 20h */
7060        };
7061        static char *ir_code_str[] = {
7062                "Raid Action Error",                                /* 00h */
7063                NULL,                                                /* 00h */
7064                NULL,                                                /* 01h */
7065                NULL,                                                /* 02h */
7066                NULL,                                                /* 03h */
7067                NULL,                                                /* 04h */
7068                NULL,                                                /* 05h */
7069                NULL,                                                /* 06h */
7070                NULL                                                /* 07h */
7071        };
7072        static char *raid_sub_code_str[] = {
7073                NULL,                                                 /* 00h */
7074                "Volume Creation Failed: Data Passed too "
7075                    "Large",                                         /* 01h */
7076                "Volume Creation Failed: Duplicate Volumes "
7077                    "Attempted",                                 /* 02h */
7078                "Volume Creation Failed: Max Number "
7079                    "Supported Volumes Exceeded",                /* 03h */
7080                "Volume Creation Failed: DMA Error",                /* 04h */
7081                "Volume Creation Failed: Invalid Volume Type",        /* 05h */
7082                "Volume Creation Failed: Error Reading "
7083                    "MFG Page 4",                                 /* 06h */
7084                "Volume Creation Failed: Creating Internal "
7085                    "Structures",                                 /* 07h */
7086                NULL,                                                /* 08h */
7087                NULL,                                                /* 09h */
7088                NULL,                                                /* 0Ah */
7089                NULL,                                                /* 0Bh */
7090                NULL,                                                /* 0Ch */
7091                NULL,                                                /* 0Dh */
7092                NULL,                                                /* 0Eh */
7093                NULL,                                                /* 0Fh */
7094                "Activation failed: Already Active Volume",         /* 10h */
7095                "Activation failed: Unsupported Volume Type",         /* 11h */
7096                "Activation failed: Too Many Active Volumes",         /* 12h */
7097                "Activation failed: Volume ID in Use",                 /* 13h */
7098                "Activation failed: Reported Failure",                 /* 14h */
7099                "Activation failed: Importing a Volume",         /* 15h */
7100                NULL,                                                /* 16h */
7101                NULL,                                                /* 17h */
7102                NULL,                                                /* 18h */
7103                NULL,                                                /* 19h */
7104                NULL,                                                /* 1Ah */
7105                NULL,                                                /* 1Bh */
7106                NULL,                                                /* 1Ch */
7107                NULL,                                                /* 1Dh */
7108                NULL,                                                /* 1Eh */
7109                NULL,                                                /* 1Fh */
7110                "Phys Disk failed: Too Many Phys Disks",         /* 20h */
7111                "Phys Disk failed: Data Passed too Large",        /* 21h */
7112                "Phys Disk failed: DMA Error",                         /* 22h */
7113                "Phys Disk failed: Invalid <channel:id>",         /* 23h */
7114                "Phys Disk failed: Creating Phys Disk Config "
7115                    "Page",                                         /* 24h */
7116                NULL,                                                /* 25h */
7117                NULL,                                                /* 26h */
7118                NULL,                                                /* 27h */
7119                NULL,                                                /* 28h */
7120                NULL,                                                /* 29h */
7121                NULL,                                                /* 2Ah */
7122                NULL,                                                /* 2Bh */
7123                NULL,                                                /* 2Ch */
7124                NULL,                                                /* 2Dh */
7125                NULL,                                                /* 2Eh */
7126                NULL,                                                /* 2Fh */
7127                "Compatibility Error: IR Disabled",                /* 30h */
7128                "Compatibility Error: Inquiry Comand Failed",        /* 31h */
7129                "Compatibility Error: Device not Direct Access "
7130                    "Device ",                                        /* 32h */
7131                "Compatibility Error: Removable Device Found",        /* 33h */
7132                "Compatibility Error: Device SCSI Version not "
7133                    "2 or Higher",                                 /* 34h */
7134                "Compatibility Error: SATA Device, 48 BIT LBA "
7135                    "not Supported",                                 /* 35h */
7136                "Compatibility Error: Device doesn't have "
7137                    "512 Byte Block Sizes",                         /* 36h */
7138                "Compatibility Error: Volume Type Check Failed", /* 37h */
7139                "Compatibility Error: Volume Type is "
7140                    "Unsupported by FW",                         /* 38h */
7141                "Compatibility Error: Disk Drive too Small for "
7142                    "use in Volume",                                 /* 39h */
7143                "Compatibility Error: Phys Disk for Create "
7144                    "Volume not Found",                         /* 3Ah */
7145                "Compatibility Error: Too Many or too Few "
7146                    "Disks for Volume Type",                         /* 3Bh */
7147                "Compatibility Error: Disk stripe Sizes "
7148                    "Must be 64KB",                                 /* 3Ch */
7149                "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
7150        };
7151
7152/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7153/**
7154 *        mpt_sas_log_info - Log information returned from SAS IOC.
7155 *        @ioc: Pointer to MPT_ADAPTER structure
7156 *        @log_info: U32 LogInfo reply word from the IOC
7157 *
7158 *        Refer to lsi/mpi_log_sas.h.
7159 **/
7160static void
7161mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info)
7162{
7163union loginfo_type {
7164        u32        loginfo;
7165        struct {
7166                u32        subcode:16;
7167                u32        code:8;
7168                u32        originator:4;
7169                u32        bus_type:4;
7170        }dw;
7171};
7172        union loginfo_type sas_loginfo;
7173        char *originator_desc = NULL;
7174        char *code_desc = NULL;
7175        char *sub_code_desc = NULL;
7176
7177        sas_loginfo.loginfo = log_info;
7178        if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
7179            (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*)))
7180                return;
7181
7182        originator_desc = originator_str[sas_loginfo.dw.originator];
7183
7184        switch (sas_loginfo.dw.originator) {
7185
7186                case 0:  /* IOP */
7187                        if (sas_loginfo.dw.code <
7188                            sizeof(iop_code_str)/sizeof(char*))
7189                                code_desc = iop_code_str[sas_loginfo.dw.code];
7190                        break;
7191                case 1:  /* PL */
7192                        if (sas_loginfo.dw.code <
7193                            sizeof(pl_code_str)/sizeof(char*))
7194                                code_desc = pl_code_str[sas_loginfo.dw.code];
7195                        break;
7196                case 2:  /* IR */
7197                        if (sas_loginfo.dw.code >=
7198                            sizeof(ir_code_str)/sizeof(char*))
7199                                break;
7200                        code_desc = ir_code_str[sas_loginfo.dw.code];
7201                        if (sas_loginfo.dw.subcode >=
7202                            sizeof(raid_sub_code_str)/sizeof(char*))
7203                        break;
7204                        if (sas_loginfo.dw.code == 0)
7205                                sub_code_desc =
7206                                    raid_sub_code_str[sas_loginfo.dw.subcode];
7207                        break;
7208                default:
7209                        return;
7210        }
7211
7212        if (sub_code_desc != NULL)
7213                printk(MYIOC_s_INFO_FMT
7214                        "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7215                        " SubCode={%s}\n",
7216                        ioc->name, log_info, originator_desc, code_desc,
7217                        sub_code_desc);
7218        else if (code_desc != NULL)
7219                printk(MYIOC_s_INFO_FMT
7220                        "LogInfo(0x%08x): Originator={%s}, Code={%s},"
7221                        " SubCode(0x%04x)\n",
7222                        ioc->name, log_info, originator_desc, code_desc,
7223                        sas_loginfo.dw.subcode);
7224        else
7225                printk(MYIOC_s_INFO_FMT
7226                        "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
7227                        " SubCode(0x%04x)\n",
7228                        ioc->name, log_info, originator_desc,
7229                        sas_loginfo.dw.code, sas_loginfo.dw.subcode);
7230}
7231
7232/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7233/**
7234 *        mpt_iocstatus_info_config - IOCSTATUS information for config pages
7235 *        @ioc: Pointer to MPT_ADAPTER structure
7236 *        @ioc_status: U32 IOCStatus word from IOC
7237 *        @mf: Pointer to MPT request frame
7238 *
7239 *        Refer to lsi/mpi.h.
7240 **/
7241static void
7242mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7243{
7244        Config_t *pReq = (Config_t *)mf;
7245        char extend_desc[EVENT_DESCR_STR_SZ];
7246        char *desc = NULL;
7247        u32 form;
7248        u8 page_type;
7249
7250        if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
7251                page_type = pReq->ExtPageType;
7252        else
7253                page_type = pReq->Header.PageType;
7254
7255        /*
7256         * ignore invalid page messages for GET_NEXT_HANDLE
7257         */
7258        form = le32_to_cpu(pReq->PageAddress);
7259        if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
7260                if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
7261                    page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
7262                    page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
7263                        if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
7264                                MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
7265                                return;
7266                }
7267                if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
7268                        if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
7269                                MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
7270                                return;
7271        }
7272
7273        snprintf(extend_desc, EVENT_DESCR_STR_SZ,
7274            "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
7275            page_type, pReq->Header.PageNumber, pReq->Action, form);
7276
7277        switch (ioc_status) {
7278
7279        case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7280                desc = "Config Page Invalid Action";
7281                break;
7282
7283        case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
7284                desc = "Config Page Invalid Type";
7285                break;
7286
7287        case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
7288                desc = "Config Page Invalid Page";
7289                break;
7290
7291        case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
7292                desc = "Config Page Invalid Data";
7293                break;
7294
7295        case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
7296                desc = "Config Page No Defaults";
7297                break;
7298
7299        case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
7300                desc = "Config Page Can't Commit";
7301                break;
7302        }
7303
7304        if (!desc)
7305                return;
7306
7307        dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
7308            ioc->name, ioc_status, desc, extend_desc));
7309}
7310
7311/**
7312 *        mpt_iocstatus_info - IOCSTATUS information returned from IOC.
7313 *        @ioc: Pointer to MPT_ADAPTER structure
7314 *        @ioc_status: U32 IOCStatus word from IOC
7315 *        @mf: Pointer to MPT request frame
7316 *
7317 *        Refer to lsi/mpi.h.
7318 **/
7319static void
7320mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
7321{
7322        u32 status = ioc_status & MPI_IOCSTATUS_MASK;
7323        char *desc = NULL;
7324
7325        switch (status) {
7326
7327/****************************************************************************/
7328/*  Common IOCStatus values for all replies                                 */
7329/****************************************************************************/
7330
7331        case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
7332                desc = "Invalid Function";
7333                break;
7334
7335        case MPI_IOCSTATUS_BUSY: /* 0x0002 */
7336                desc = "Busy";
7337                break;
7338
7339        case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
7340                desc = "Invalid SGL";
7341                break;
7342
7343        case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
7344                desc = "Internal Error";
7345                break;
7346
7347        case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
7348                desc = "Reserved";
7349                break;
7350
7351        case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
7352                desc = "Insufficient Resources";
7353                break;
7354
7355        case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
7356                desc = "Invalid Field";
7357                break;
7358
7359        case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
7360                desc = "Invalid State";
7361                break;
7362
7363/****************************************************************************/
7364/*  Config IOCStatus values                                                 */
7365/****************************************************************************/
7366
7367        case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
7368        case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
7369        case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
7370        case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
7371        case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
7372        case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
7373                mpt_iocstatus_info_config(ioc, status, mf);
7374                break;
7375
7376/****************************************************************************/
7377/*  SCSIIO Reply (SPI, FCP, SAS) initiator values                           */
7378/*                                                                          */
7379/*  Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
7380/*                                                                          */
7381/****************************************************************************/
7382
7383        case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
7384        case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
7385        case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
7386        case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
7387        case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
7388        case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
7389        case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
7390        case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
7391        case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
7392        case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
7393        case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
7394        case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
7395        case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
7396                break;
7397
7398/****************************************************************************/
7399/*  SCSI Target values                                                      */
7400/****************************************************************************/
7401
7402        case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
7403                desc = "Target: Priority IO";
7404                break;
7405
7406        case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
7407                desc = "Target: Invalid Port";
7408                break;
7409
7410        case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
7411                desc = "Target Invalid IO Index:";
7412                break;
7413
7414        case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
7415                desc = "Target: Aborted";
7416                break;
7417
7418        case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
7419                desc = "Target: No Conn Retryable";
7420                break;
7421
7422        case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
7423                desc = "Target: No Connection";
7424                break;
7425
7426        case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
7427                desc = "Target: Transfer Count Mismatch";
7428                break;
7429
7430        case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
7431                desc = "Target: STS Data not Sent";
7432                break;
7433
7434        case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
7435                desc = "Target: Data Offset Error";
7436                break;
7437
7438        case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
7439                desc = "Target: Too Much Write Data";
7440                break;
7441
7442        case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
7443                desc = "Target: IU Too Short";
7444                break;
7445
7446        case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
7447                desc = "Target: ACK NAK Timeout";
7448                break;
7449
7450        case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
7451                desc = "Target: Nak Received";
7452                break;
7453
7454/****************************************************************************/
7455/*  Fibre Channel Direct Access values                                      */
7456/****************************************************************************/
7457
7458        case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
7459                desc = "FC: Aborted";
7460                break;
7461
7462        case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
7463                desc = "FC: RX ID Invalid";
7464                break;
7465
7466        case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
7467                desc = "FC: DID Invalid";
7468                break;
7469
7470        case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
7471                desc = "FC: Node Logged Out";
7472                break;
7473
7474        case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
7475                desc = "FC: Exchange Canceled";
7476                break;
7477
7478/****************************************************************************/
7479/*  LAN values                                                              */
7480/****************************************************************************/
7481
7482        case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
7483                desc = "LAN: Device not Found";
7484                break;
7485
7486        case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
7487                desc = "LAN: Device Failure";
7488                break;
7489
7490        case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
7491                desc = "LAN: Transmit Error";
7492                break;
7493
7494        case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
7495                desc = "LAN: Transmit Aborted";
7496                break;
7497
7498        case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
7499                desc = "LAN: Receive Error";
7500                break;
7501
7502        case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
7503                desc = "LAN: Receive Aborted";
7504                break;
7505
7506        case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
7507                desc = "LAN: Partial Packet";
7508                break;
7509
7510        case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
7511                desc = "LAN: Canceled";
7512                break;
7513
7514/****************************************************************************/
7515/*  Serial Attached SCSI values                                             */
7516/****************************************************************************/
7517
7518        case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
7519                desc = "SAS: SMP Request Failed";
7520                break;
7521
7522        case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
7523                desc = "SAS: SMP Data Overrun";
7524                break;
7525
7526        default:
7527                desc = "Others";
7528                break;
7529        }
7530
7531        if (!desc)
7532                return;
7533
7534        dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
7535            ioc->name, status, desc));
7536}
7537
7538/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7539EXPORT_SYMBOL(mpt_attach);
7540EXPORT_SYMBOL(mpt_detach);
7541#ifdef CONFIG_PM
7542EXPORT_SYMBOL(mpt_resume);
7543EXPORT_SYMBOL(mpt_suspend);
7544#endif
7545EXPORT_SYMBOL(ioc_list);
7546EXPORT_SYMBOL(mpt_register);
7547EXPORT_SYMBOL(mpt_deregister);
7548EXPORT_SYMBOL(mpt_event_register);
7549EXPORT_SYMBOL(mpt_event_deregister);
7550EXPORT_SYMBOL(mpt_reset_register);
7551EXPORT_SYMBOL(mpt_reset_deregister);
7552EXPORT_SYMBOL(mpt_device_driver_register);
7553EXPORT_SYMBOL(mpt_device_driver_deregister);
7554EXPORT_SYMBOL(mpt_get_msg_frame);
7555EXPORT_SYMBOL(mpt_put_msg_frame);
7556EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
7557EXPORT_SYMBOL(mpt_free_msg_frame);
7558EXPORT_SYMBOL(mpt_add_sge);
7559EXPORT_SYMBOL(mpt_send_handshake_request);
7560EXPORT_SYMBOL(mpt_verify_adapter);
7561EXPORT_SYMBOL(mpt_GetIocState);
7562EXPORT_SYMBOL(mpt_print_ioc_summary);
7563EXPORT_SYMBOL(mpt_HardResetHandler);
7564EXPORT_SYMBOL(mpt_config);
7565EXPORT_SYMBOL(mpt_findImVolumes);
7566EXPORT_SYMBOL(mpt_alloc_fw_memory);
7567EXPORT_SYMBOL(mpt_free_fw_memory);
7568EXPORT_SYMBOL(mptbase_sas_persist_operation);
7569EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
7570
7571/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7572/**
7573 *        fusion_init - Fusion MPT base driver initialization routine.
7574 *
7575 *        Returns 0 for success, non-zero for failure.
7576 */
7577static int __init
7578fusion_init(void)
7579{
7580        u8 cb_idx;
7581
7582        show_mptmod_ver(my_NAME, my_VERSION);
7583        printk(KERN_INFO COPYRIGHT "\n");
7584
7585        for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
7586                MptCallbacks[cb_idx] = NULL;
7587                MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
7588                MptEvHandlers[cb_idx] = NULL;
7589                MptResetHandlers[cb_idx] = NULL;
7590        }
7591
7592        /*  Register ourselves (mptbase) in order to facilitate
7593         *  EventNotification handling.
7594         */
7595        mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
7596
7597        /* Register for hard reset handling callbacks.
7598         */
7599        mpt_reset_register(mpt_base_index, mpt_ioc_reset);
7600
7601#ifdef CONFIG_PROC_FS
7602        (void) procmpt_create();
7603#endif
7604        return 0;
7605}
7606
7607/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7608/**
7609 *        fusion_exit - Perform driver unload cleanup.
7610 *
7611 *        This routine frees all resources associated with each MPT adapter
7612 *        and removes all %MPT_PROCFS_MPTBASEDIR entries.
7613 */
7614static void __exit
7615fusion_exit(void)
7616{
7617
7618        mpt_reset_deregister(mpt_base_index);
7619
7620#ifdef CONFIG_PROC_FS
7621        procmpt_destroy();
7622#endif
7623}
7624
7625module_init(fusion_init);
7626module_exit(fusion_exit);