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