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