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