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, 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 const struct file_operations mpt_summary_proc_fops;
 201static const struct file_operations mpt_version_proc_fops;
 202static const struct file_operations mpt_iocinfo_proc_fops;
 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, 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                pChain->Length = cpu_to_le16(length);
1133                pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT;
1134                pChain->NextChainOffset = next;
1135                pChain->Address = cpu_to_le32(dma_addr);
1136}
1137
1138/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1139/**
1140 *      mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr.
1141 *      @pAddr: virtual address for SGE
1142 *      @next: nextChainOffset value (u32's)
1143 *      @length: length of next SGL segment
1144 *      @dma_addr: Physical address
1145 *
1146 */
1147static void
1148mpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
1149{
1150                SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
1151                u32 tmp = dma_addr & 0xFFFFFFFF;
1152
1153                pChain->Length = cpu_to_le16(length);
1154                pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT |
1155                                 MPI_SGE_FLAGS_64_BIT_ADDRESSING);
1156
1157                pChain->NextChainOffset = next;
1158
1159                pChain->Address.Low = cpu_to_le32(tmp);
1160                tmp = (u32)(upper_32_bits(dma_addr));
1161                pChain->Address.High = cpu_to_le32(tmp);
1162}
1163
1164/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1165/**
1166 *      mpt_send_handshake_request - Send MPT request via doorbell handshake method.
1167 *      @cb_idx: Handle of registered MPT protocol driver
1168 *      @ioc: Pointer to MPT adapter structure
1169 *      @reqBytes: Size of the request in bytes
1170 *      @req: Pointer to MPT request frame
1171 *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
1172 *
1173 *      This routine is used exclusively to send MptScsiTaskMgmt
1174 *      requests since they are required to be sent via doorbell handshake.
1175 *
1176 *      NOTE: It is the callers responsibility to byte-swap fields in the
1177 *      request which are greater than 1 byte in size.
1178 *
1179 *      Returns 0 for success, non-zero for failure.
1180 */
1181int
1182mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
1183{
1184        int     r = 0;
1185        u8      *req_as_bytes;
1186        int      ii;
1187
1188        /* State is known to be good upon entering
1189         * this function so issue the bus reset
1190         * request.
1191         */
1192
1193        /*
1194         * Emulate what mpt_put_msg_frame() does /wrt to sanity
1195         * setting cb_idx/req_idx.  But ONLY if this request
1196         * is in proper (pre-alloc'd) request buffer range...
1197         */
1198        ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
1199        if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
1200                MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
1201                mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
1202                mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx;
1203        }
1204
1205        /* Make sure there are no doorbells */
1206        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1207
1208        CHIPREG_WRITE32(&ioc->chip->Doorbell,
1209                        ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
1210                         ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
1211
1212        /* Wait for IOC doorbell int */
1213        if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
1214                return ii;
1215        }
1216
1217        /* Read doorbell and check for active bit */
1218        if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
1219                return -5;
1220
1221        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n",
1222                ioc->name, ii));
1223
1224        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1225
1226        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1227                return -2;
1228        }
1229
1230        /* Send request via doorbell handshake */
1231        req_as_bytes = (u8 *) req;
1232        for (ii = 0; ii < reqBytes/4; ii++) {
1233                u32 word;
1234
1235                word = ((req_as_bytes[(ii*4) + 0] <<  0) |
1236                        (req_as_bytes[(ii*4) + 1] <<  8) |
1237                        (req_as_bytes[(ii*4) + 2] << 16) |
1238                        (req_as_bytes[(ii*4) + 3] << 24));
1239                CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
1240                if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1241                        r = -3;
1242                        break;
1243                }
1244        }
1245
1246        if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
1247                r = 0;
1248        else
1249                r = -4;
1250
1251        /* Make sure there are no doorbells */
1252        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1253
1254        return r;
1255}
1256
1257/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1258/**
1259 * mpt_host_page_access_control - control the IOC's Host Page Buffer access
1260 * @ioc: Pointer to MPT adapter structure
1261 * @access_control_value: define bits below
1262 * @sleepFlag: Specifies whether the process can sleep
1263 *
1264 * Provides mechanism for the host driver to control the IOC's
1265 * Host Page Buffer access.
1266 *
1267 * Access Control Value - bits[15:12]
1268 * 0h Reserved
1269 * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS }
1270 * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS }
1271 * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER }
1272 *
1273 * Returns 0 for success, non-zero for failure.
1274 */
1275
1276static int
1277mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag)
1278{
1279        int      r = 0;
1280
1281        /* return if in use */
1282        if (CHIPREG_READ32(&ioc->chip->Doorbell)
1283            & MPI_DOORBELL_ACTIVE)
1284            return -1;
1285
1286        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1287
1288        CHIPREG_WRITE32(&ioc->chip->Doorbell,
1289                ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
1290                 <<MPI_DOORBELL_FUNCTION_SHIFT) |
1291                 (access_control_value<<12)));
1292
1293        /* Wait for IOC to clear Doorbell Status bit */
1294        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
1295                return -2;
1296        }else
1297                return 0;
1298}
1299
1300/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1301/**
1302 *      mpt_host_page_alloc - allocate system memory for the fw
1303 *      @ioc: Pointer to pointer to IOC adapter
1304 *      @ioc_init: Pointer to ioc init config page
1305 *
1306 *      If we already allocated memory in past, then resend the same pointer.
1307 *      Returns 0 for success, non-zero for failure.
1308 */
1309static int
1310mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init)
1311{
1312        char    *psge;
1313        int     flags_length;
1314        u32     host_page_buffer_sz=0;
1315
1316        if(!ioc->HostPageBuffer) {
1317
1318                host_page_buffer_sz =
1319                    le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF;
1320
1321                if(!host_page_buffer_sz)
1322                        return 0; /* fw doesn't need any host buffers */
1323
1324                /* spin till we get enough memory */
1325                while(host_page_buffer_sz > 0) {
1326
1327                        if((ioc->HostPageBuffer = pci_alloc_consistent(
1328                            ioc->pcidev,
1329                            host_page_buffer_sz,
1330                            &ioc->HostPageBuffer_dma)) != NULL) {
1331
1332                                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1333                                    "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n",
1334                                    ioc->name, ioc->HostPageBuffer,
1335                                    (u32)ioc->HostPageBuffer_dma,
1336                                    host_page_buffer_sz));
1337                                ioc->alloc_total += host_page_buffer_sz;
1338                                ioc->HostPageBuffer_sz = host_page_buffer_sz;
1339                                break;
1340                        }
1341
1342                        host_page_buffer_sz -= (4*1024);
1343                }
1344        }
1345
1346        if(!ioc->HostPageBuffer) {
1347                printk(MYIOC_s_ERR_FMT
1348                    "Failed to alloc memory for host_page_buffer!\n",
1349                    ioc->name);
1350                return -999;
1351        }
1352
1353        psge = (char *)&ioc_init->HostPageBufferSGE;
1354        flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1355            MPI_SGE_FLAGS_SYSTEM_ADDRESS |
1356            MPI_SGE_FLAGS_HOST_TO_IOC |
1357            MPI_SGE_FLAGS_END_OF_BUFFER;
1358        flags_length = flags_length << MPI_SGE_FLAGS_SHIFT;
1359        flags_length |= ioc->HostPageBuffer_sz;
1360        ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma);
1361        ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE;
1362
1363return 0;
1364}
1365
1366/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1367/**
1368 *      mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure.
1369 *      @iocid: IOC unique identifier (integer)
1370 *      @iocpp: Pointer to pointer to IOC adapter
1371 *
1372 *      Given a unique IOC identifier, set pointer to the associated MPT
1373 *      adapter structure.
1374 *
1375 *      Returns iocid and sets iocpp if iocid is found.
1376 *      Returns -1 if iocid is not found.
1377 */
1378int
1379mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
1380{
1381        MPT_ADAPTER *ioc;
1382
1383        list_for_each_entry(ioc,&ioc_list,list) {
1384                if (ioc->id == iocid) {
1385                        *iocpp =ioc;
1386                        return iocid;
1387                }
1388        }
1389
1390        *iocpp = NULL;
1391        return -1;
1392}
1393
1394/**
1395 *      mpt_get_product_name - returns product string
1396 *      @vendor: pci vendor id
1397 *      @device: pci device id
1398 *      @revision: pci revision id
1399 *
1400 *      Returns product string displayed when driver loads,
1401 *      in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product
1402 *
1403 **/
1404static const char*
1405mpt_get_product_name(u16 vendor, u16 device, u8 revision)
1406{
1407        char *product_str = NULL;
1408
1409        if (vendor == PCI_VENDOR_ID_BROCADE) {
1410                switch (device)
1411                {
1412                case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1413                        switch (revision)
1414                        {
1415                        case 0x00:
1416                                product_str = "BRE040 A0";
1417                                break;
1418                        case 0x01:
1419                                product_str = "BRE040 A1";
1420                                break;
1421                        default:
1422                                product_str = "BRE040";
1423                                break;
1424                        }
1425                        break;
1426                }
1427                goto out;
1428        }
1429
1430        switch (device)
1431        {
1432        case MPI_MANUFACTPAGE_DEVICEID_FC909:
1433                product_str = "LSIFC909 B1";
1434                break;
1435        case MPI_MANUFACTPAGE_DEVICEID_FC919:
1436                product_str = "LSIFC919 B0";
1437                break;
1438        case MPI_MANUFACTPAGE_DEVICEID_FC929:
1439                product_str = "LSIFC929 B0";
1440                break;
1441        case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1442                if (revision < 0x80)
1443                        product_str = "LSIFC919X A0";
1444                else
1445                        product_str = "LSIFC919XL A1";
1446                break;
1447        case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1448                if (revision < 0x80)
1449                        product_str = "LSIFC929X A0";
1450                else
1451                        product_str = "LSIFC929XL A1";
1452                break;
1453        case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1454                product_str = "LSIFC939X A1";
1455                break;
1456        case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1457                product_str = "LSIFC949X A1";
1458                break;
1459        case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1460                switch (revision)
1461                {
1462                case 0x00:
1463                        product_str = "LSIFC949E A0";
1464                        break;
1465                case 0x01:
1466                        product_str = "LSIFC949E A1";
1467                        break;
1468                default:
1469                        product_str = "LSIFC949E";
1470                        break;
1471                }
1472                break;
1473        case MPI_MANUFACTPAGE_DEVID_53C1030:
1474                switch (revision)
1475                {
1476                case 0x00:
1477                        product_str = "LSI53C1030 A0";
1478                        break;
1479                case 0x01:
1480                        product_str = "LSI53C1030 B0";
1481                        break;
1482                case 0x03:
1483                        product_str = "LSI53C1030 B1";
1484                        break;
1485                case 0x07:
1486                        product_str = "LSI53C1030 B2";
1487                        break;
1488                case 0x08:
1489                        product_str = "LSI53C1030 C0";
1490                        break;
1491                case 0x80:
1492                        product_str = "LSI53C1030T A0";
1493                        break;
1494                case 0x83:
1495                        product_str = "LSI53C1030T A2";
1496                        break;
1497                case 0x87:
1498                        product_str = "LSI53C1030T A3";
1499                        break;
1500                case 0xc1:
1501                        product_str = "LSI53C1020A A1";
1502                        break;
1503                default:
1504                        product_str = "LSI53C1030";
1505                        break;
1506                }
1507                break;
1508        case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1509                switch (revision)
1510                {
1511                case 0x03:
1512                        product_str = "LSI53C1035 A2";
1513                        break;
1514                case 0x04:
1515                        product_str = "LSI53C1035 B0";
1516                        break;
1517                default:
1518                        product_str = "LSI53C1035";
1519                        break;
1520                }
1521                break;
1522        case MPI_MANUFACTPAGE_DEVID_SAS1064:
1523                switch (revision)
1524                {
1525                case 0x00:
1526                        product_str = "LSISAS1064 A1";
1527                        break;
1528                case 0x01:
1529                        product_str = "LSISAS1064 A2";
1530                        break;
1531                case 0x02:
1532                        product_str = "LSISAS1064 A3";
1533                        break;
1534                case 0x03:
1535                        product_str = "LSISAS1064 A4";
1536                        break;
1537                default:
1538                        product_str = "LSISAS1064";
1539                        break;
1540                }
1541                break;
1542        case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1543                switch (revision)
1544                {
1545                case 0x00:
1546                        product_str = "LSISAS1064E A0";
1547                        break;
1548                case 0x01:
1549                        product_str = "LSISAS1064E B0";
1550                        break;
1551                case 0x02:
1552                        product_str = "LSISAS1064E B1";
1553                        break;
1554                case 0x04:
1555                        product_str = "LSISAS1064E B2";
1556                        break;
1557                case 0x08:
1558                        product_str = "LSISAS1064E B3";
1559                        break;
1560                default:
1561                        product_str = "LSISAS1064E";
1562                        break;
1563                }
1564                break;
1565        case MPI_MANUFACTPAGE_DEVID_SAS1068:
1566                switch (revision)
1567                {
1568                case 0x00:
1569                        product_str = "LSISAS1068 A0";
1570                        break;
1571                case 0x01:
1572                        product_str = "LSISAS1068 B0";
1573                        break;
1574                case 0x02:
1575                        product_str = "LSISAS1068 B1";
1576                        break;
1577                default:
1578                        product_str = "LSISAS1068";
1579                        break;
1580                }
1581                break;
1582        case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1583                switch (revision)
1584                {
1585                case 0x00:
1586                        product_str = "LSISAS1068E A0";
1587                        break;
1588                case 0x01:
1589                        product_str = "LSISAS1068E B0";
1590                        break;
1591                case 0x02:
1592                        product_str = "LSISAS1068E B1";
1593                        break;
1594                case 0x04:
1595                        product_str = "LSISAS1068E B2";
1596                        break;
1597                case 0x08:
1598                        product_str = "LSISAS1068E B3";
1599                        break;
1600                default:
1601                        product_str = "LSISAS1068E";
1602                        break;
1603                }
1604                break;
1605        case MPI_MANUFACTPAGE_DEVID_SAS1078:
1606                switch (revision)
1607                {
1608                case 0x00:
1609                        product_str = "LSISAS1078 A0";
1610                        break;
1611                case 0x01:
1612                        product_str = "LSISAS1078 B0";
1613                        break;
1614                case 0x02:
1615                        product_str = "LSISAS1078 C0";
1616                        break;
1617                case 0x03:
1618                        product_str = "LSISAS1078 C1";
1619                        break;
1620                case 0x04:
1621                        product_str = "LSISAS1078 C2";
1622                        break;
1623                default:
1624                        product_str = "LSISAS1078";
1625                        break;
1626                }
1627                break;
1628        }
1629
1630 out:
1631        return product_str;
1632}
1633
1634/**
1635 *      mpt_mapresources - map in memory mapped io
1636 *      @ioc: Pointer to pointer to IOC adapter
1637 *
1638 **/
1639static int
1640mpt_mapresources(MPT_ADAPTER *ioc)
1641{
1642        u8              __iomem *mem;
1643        int              ii;
1644        resource_size_t  mem_phys;
1645        unsigned long    port;
1646        u32              msize;
1647        u32              psize;
1648        int              r = -ENODEV;
1649        struct pci_dev *pdev;
1650
1651        pdev = ioc->pcidev;
1652        ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
1653        if (pci_enable_device_mem(pdev)) {
1654                printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() "
1655                    "failed\n", ioc->name);
1656                return r;
1657        }
1658        if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) {
1659                printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with "
1660                    "MEM failed\n", ioc->name);
1661                goto out_pci_disable_device;
1662        }
1663
1664        if (sizeof(dma_addr_t) > 4) {
1665                const uint64_t required_mask = dma_get_required_mask
1666                    (&pdev->dev);
1667                if (required_mask > DMA_BIT_MASK(32)
1668                        && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1669                        && !pci_set_consistent_dma_mask(pdev,
1670                                                 DMA_BIT_MASK(64))) {
1671                        ioc->dma_mask = DMA_BIT_MASK(64);
1672                        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1673                                ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1674                                ioc->name));
1675                } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1676                        && !pci_set_consistent_dma_mask(pdev,
1677                                                DMA_BIT_MASK(32))) {
1678                        ioc->dma_mask = DMA_BIT_MASK(32);
1679                        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1680                                ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1681                                ioc->name));
1682                } else {
1683                        printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1684                            ioc->name, pci_name(pdev));
1685                        goto out_pci_release_region;
1686                }
1687        } else {
1688                if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1689                        && !pci_set_consistent_dma_mask(pdev,
1690                                                DMA_BIT_MASK(32))) {
1691                        ioc->dma_mask = DMA_BIT_MASK(32);
1692                        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
1693                                ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n",
1694                                ioc->name));
1695                } else {
1696                        printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n",
1697                            ioc->name, pci_name(pdev));
1698                        goto out_pci_release_region;
1699                }
1700        }
1701
1702        mem_phys = msize = 0;
1703        port = psize = 0;
1704        for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) {
1705                if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) {
1706                        if (psize)
1707                                continue;
1708                        /* Get I/O space! */
1709                        port = pci_resource_start(pdev, ii);
1710                        psize = pci_resource_len(pdev, ii);
1711                } else {
1712                        if (msize)
1713                                continue;
1714                        /* Get memmap */
1715                        mem_phys = pci_resource_start(pdev, ii);
1716                        msize = pci_resource_len(pdev, ii);
1717                }
1718        }
1719        ioc->mem_size = msize;
1720
1721        mem = NULL;
1722        /* Get logical ptr for PciMem0 space */
1723        /*mem = ioremap(mem_phys, msize);*/
1724        mem = ioremap(mem_phys, msize);
1725        if (mem == NULL) {
1726                printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter"
1727                        " memory!\n", ioc->name);
1728                r = -EINVAL;
1729                goto out_pci_release_region;
1730        }
1731        ioc->memmap = mem;
1732        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
1733            ioc->name, mem, (unsigned long long)mem_phys));
1734
1735        ioc->mem_phys = mem_phys;
1736        ioc->chip = (SYSIF_REGS __iomem *)mem;
1737
1738        /* Save Port IO values in case we need to do downloadboot */
1739        ioc->pio_mem_phys = port;
1740        ioc->pio_chip = (SYSIF_REGS __iomem *)port;
1741
1742        return 0;
1743
1744out_pci_release_region:
1745        pci_release_selected_regions(pdev, ioc->bars);
1746out_pci_disable_device:
1747        pci_disable_device(pdev);
1748        return r;
1749}
1750
1751/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1752/**
1753 *      mpt_attach - Install a PCI intelligent MPT adapter.
1754 *      @pdev: Pointer to pci_dev structure
1755 *      @id: PCI device ID information
1756 *
1757 *      This routine performs all the steps necessary to bring the IOC of
1758 *      a MPT adapter to a OPERATIONAL state.  This includes registering
1759 *      memory regions, registering the interrupt, and allocating request
1760 *      and reply memory pools.
1761 *
1762 *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
1763 *      MPT adapter.
1764 *
1765 *      Returns 0 for success, non-zero for failure.
1766 *
1767 *      TODO: Add support for polled controllers
1768 */
1769int
1770mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
1771{
1772        MPT_ADAPTER     *ioc;
1773        u8               cb_idx;
1774        int              r = -ENODEV;
1775        u8               pcixcmd;
1776        static int       mpt_ids = 0;
1777#ifdef CONFIG_PROC_FS
1778        struct proc_dir_entry *dent;
1779#endif
1780
1781        ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
1782        if (ioc == NULL) {
1783                printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
1784                return -ENOMEM;
1785        }
1786
1787        ioc->id = mpt_ids++;
1788        sprintf(ioc->name, "ioc%d", ioc->id);
1789        dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n"));
1790
1791        /*
1792         * set initial debug level
1793         * (refer to mptdebug.h)
1794         *
1795         */
1796        ioc->debug_level = mpt_debug_level;
1797        if (mpt_debug_level)
1798                printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level);
1799
1800        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name));
1801
1802        ioc->pcidev = pdev;
1803        if (mpt_mapresources(ioc)) {
1804                goto out_free_ioc;
1805        }
1806
1807        /*
1808         * Setting up proper handlers for scatter gather handling
1809         */
1810        if (ioc->dma_mask == DMA_BIT_MASK(64)) {
1811                if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
1812                        ioc->add_sge = &mpt_add_sge_64bit_1078;
1813                else
1814                        ioc->add_sge = &mpt_add_sge_64bit;
1815                ioc->add_chain = &mpt_add_chain_64bit;
1816                ioc->sg_addr_size = 8;
1817        } else {
1818                ioc->add_sge = &mpt_add_sge;
1819                ioc->add_chain = &mpt_add_chain;
1820                ioc->sg_addr_size = 4;
1821        }
1822        ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
1823
1824        ioc->alloc_total = sizeof(MPT_ADAPTER);
1825        ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
1826        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
1827
1828
1829        spin_lock_init(&ioc->taskmgmt_lock);
1830        mutex_init(&ioc->internal_cmds.mutex);
1831        init_completion(&ioc->internal_cmds.done);
1832        mutex_init(&ioc->mptbase_cmds.mutex);
1833        init_completion(&ioc->mptbase_cmds.done);
1834        mutex_init(&ioc->taskmgmt_cmds.mutex);
1835        init_completion(&ioc->taskmgmt_cmds.done);
1836
1837        /* Initialize the event logging.
1838         */
1839        ioc->eventTypes = 0;    /* None */
1840        ioc->eventContext = 0;
1841        ioc->eventLogSize = 0;
1842        ioc->events = NULL;
1843
1844#ifdef MFCNT
1845        ioc->mfcnt = 0;
1846#endif
1847
1848        ioc->sh = NULL;
1849        ioc->cached_fw = NULL;
1850
1851        /* Initialize SCSI Config Data structure
1852         */
1853        memset(&ioc->spi_data, 0, sizeof(SpiCfgData));
1854
1855        /* Initialize the fc rport list head.
1856         */
1857        INIT_LIST_HEAD(&ioc->fc_rports);
1858
1859        /* Find lookup slot. */
1860        INIT_LIST_HEAD(&ioc->list);
1861
1862
1863        /* Initialize workqueue */
1864        INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
1865
1866        snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN,
1867                 "mpt_poll_%d", ioc->id);
1868        ioc->reset_work_q =
1869                create_singlethread_workqueue(ioc->reset_work_q_name);
1870        if (!ioc->reset_work_q) {
1871                printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1872                    ioc->name);
1873                r = -ENOMEM;
1874                goto out_unmap_resources;
1875        }
1876
1877        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
1878            ioc->name, &ioc->facts, &ioc->pfacts[0]));
1879
1880        ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device,
1881                                              pdev->revision);
1882
1883        switch (pdev->device)
1884        {
1885        case MPI_MANUFACTPAGE_DEVICEID_FC939X:
1886        case MPI_MANUFACTPAGE_DEVICEID_FC949X:
1887                ioc->errata_flag_1064 = 1;
1888        case MPI_MANUFACTPAGE_DEVICEID_FC909:
1889        case MPI_MANUFACTPAGE_DEVICEID_FC929:
1890        case MPI_MANUFACTPAGE_DEVICEID_FC919:
1891        case MPI_MANUFACTPAGE_DEVICEID_FC949E:
1892                ioc->bus_type = FC;
1893                break;
1894
1895        case MPI_MANUFACTPAGE_DEVICEID_FC929X:
1896                if (pdev->revision < XL_929) {
1897                        /* 929X Chip Fix. Set Split transactions level
1898                        * for PCIX. Set MOST bits to zero.
1899                        */
1900                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1901                        pcixcmd &= 0x8F;
1902                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1903                } else {
1904                        /* 929XL Chip Fix. Set MMRBC to 0x08.
1905                        */
1906                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1907                        pcixcmd |= 0x08;
1908                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1909                }
1910                ioc->bus_type = FC;
1911                break;
1912
1913        case MPI_MANUFACTPAGE_DEVICEID_FC919X:
1914                /* 919X Chip Fix. Set Split transactions level
1915                 * for PCIX. Set MOST bits to zero.
1916                 */
1917                pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1918                pcixcmd &= 0x8F;
1919                pci_write_config_byte(pdev, 0x6a, pcixcmd);
1920                ioc->bus_type = FC;
1921                break;
1922
1923        case MPI_MANUFACTPAGE_DEVID_53C1030:
1924                /* 1030 Chip Fix. Disable Split transactions
1925                 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
1926                 */
1927                if (pdev->revision < C0_1030) {
1928                        pci_read_config_byte(pdev, 0x6a, &pcixcmd);
1929                        pcixcmd &= 0x8F;
1930                        pci_write_config_byte(pdev, 0x6a, pcixcmd);
1931                }
1932
1933        case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
1934                ioc->bus_type = SPI;
1935                break;
1936
1937        case MPI_MANUFACTPAGE_DEVID_SAS1064:
1938        case MPI_MANUFACTPAGE_DEVID_SAS1068:
1939                ioc->errata_flag_1064 = 1;
1940                ioc->bus_type = SAS;
1941                break;
1942
1943        case MPI_MANUFACTPAGE_DEVID_SAS1064E:
1944        case MPI_MANUFACTPAGE_DEVID_SAS1068E:
1945        case MPI_MANUFACTPAGE_DEVID_SAS1078:
1946                ioc->bus_type = SAS;
1947                break;
1948        }
1949
1950
1951        switch (ioc->bus_type) {
1952
1953        case SAS:
1954                ioc->msi_enable = mpt_msi_enable_sas;
1955                break;
1956
1957        case SPI:
1958                ioc->msi_enable = mpt_msi_enable_spi;
1959                break;
1960
1961        case FC:
1962                ioc->msi_enable = mpt_msi_enable_fc;
1963                break;
1964
1965        default:
1966                ioc->msi_enable = 0;
1967                break;
1968        }
1969
1970        ioc->fw_events_off = 1;
1971
1972        if (ioc->errata_flag_1064)
1973                pci_disable_io_access(pdev);
1974
1975        spin_lock_init(&ioc->FreeQlock);
1976
1977        /* Disable all! */
1978        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
1979        ioc->active = 0;
1980        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
1981
1982        /* Set IOC ptr in the pcidev's driver data. */
1983        pci_set_drvdata(ioc->pcidev, ioc);
1984
1985        /* Set lookup ptr. */
1986        list_add_tail(&ioc->list, &ioc_list);
1987
1988        /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
1989         */
1990        mpt_detect_bound_ports(ioc, pdev);
1991
1992        INIT_LIST_HEAD(&ioc->fw_event_list);
1993        spin_lock_init(&ioc->fw_event_lock);
1994        snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
1995        ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
1996        if (!ioc->fw_event_q) {
1997                printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
1998                    ioc->name);
1999                r = -ENOMEM;
2000                goto out_remove_ioc;
2001        }
2002
2003        if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2004            CAN_SLEEP)) != 0){
2005                printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
2006                    ioc->name, r);
2007
2008                destroy_workqueue(ioc->fw_event_q);
2009                ioc->fw_event_q = NULL;
2010
2011                list_del(&ioc->list);
2012                if (ioc->alt_ioc)
2013                        ioc->alt_ioc->alt_ioc = NULL;
2014                iounmap(ioc->memmap);
2015                if (pci_is_enabled(pdev))
2016                        pci_disable_device(pdev);
2017                if (r != -5)
2018                        pci_release_selected_regions(pdev, ioc->bars);
2019
2020                destroy_workqueue(ioc->reset_work_q);
2021                ioc->reset_work_q = NULL;
2022
2023                kfree(ioc);
2024                return r;
2025        }
2026
2027        /* call per device driver probe entry point */
2028        for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2029                if(MptDeviceDriverHandlers[cb_idx] &&
2030                  MptDeviceDriverHandlers[cb_idx]->probe) {
2031                        MptDeviceDriverHandlers[cb_idx]->probe(pdev,id);
2032                }
2033        }
2034
2035#ifdef CONFIG_PROC_FS
2036        /*
2037         *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
2038         */
2039        dent = proc_mkdir(ioc->name, mpt_proc_root_dir);
2040        if (dent) {
2041                proc_create_data("info", S_IRUGO, dent, &mpt_iocinfo_proc_fops, ioc);
2042                proc_create_data("summary", S_IRUGO, dent, &mpt_summary_proc_fops, ioc);
2043        }
2044#endif
2045
2046        if (!ioc->alt_ioc)
2047                queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work,
2048                        msecs_to_jiffies(MPT_POLLING_INTERVAL));
2049
2050        return 0;
2051
2052out_remove_ioc:
2053        list_del(&ioc->list);
2054        if (ioc->alt_ioc)
2055                ioc->alt_ioc->alt_ioc = NULL;
2056
2057        destroy_workqueue(ioc->reset_work_q);
2058        ioc->reset_work_q = NULL;
2059
2060out_unmap_resources:
2061        iounmap(ioc->memmap);
2062        pci_disable_device(pdev);
2063        pci_release_selected_regions(pdev, ioc->bars);
2064
2065out_free_ioc:
2066        kfree(ioc);
2067
2068        return r;
2069}
2070
2071/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2072/**
2073 *      mpt_detach - Remove a PCI intelligent MPT adapter.
2074 *      @pdev: Pointer to pci_dev structure
2075 */
2076
2077void
2078mpt_detach(struct pci_dev *pdev)
2079{
2080        MPT_ADAPTER     *ioc = pci_get_drvdata(pdev);
2081        char pname[32];
2082        u8 cb_idx;
2083        unsigned long flags;
2084        struct workqueue_struct *wq;
2085
2086        /*
2087         * Stop polling ioc for fault condition
2088         */
2089        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2090        wq = ioc->reset_work_q;
2091        ioc->reset_work_q = NULL;
2092        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2093        cancel_delayed_work(&ioc->fault_reset_work);
2094        destroy_workqueue(wq);
2095
2096        spin_lock_irqsave(&ioc->fw_event_lock, flags);
2097        wq = ioc->fw_event_q;
2098        ioc->fw_event_q = NULL;
2099        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2100        destroy_workqueue(wq);
2101
2102        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name);
2103        remove_proc_entry(pname, NULL);
2104        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name);
2105        remove_proc_entry(pname, NULL);
2106        sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s", ioc->name);
2107        remove_proc_entry(pname, NULL);
2108
2109        /* call per device driver remove entry point */
2110        for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
2111                if(MptDeviceDriverHandlers[cb_idx] &&
2112                  MptDeviceDriverHandlers[cb_idx]->remove) {
2113                        MptDeviceDriverHandlers[cb_idx]->remove(pdev);
2114                }
2115        }
2116
2117        /* Disable interrupts! */
2118        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2119
2120        ioc->active = 0;
2121        synchronize_irq(pdev->irq);
2122
2123        /* Clear any lingering interrupt */
2124        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2125
2126        CHIPREG_READ32(&ioc->chip->IntStatus);
2127
2128        mpt_adapter_dispose(ioc);
2129
2130}
2131
2132/**************************************************************************
2133 * Power Management
2134 */
2135#ifdef CONFIG_PM
2136/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2137/**
2138 *      mpt_suspend - Fusion MPT base driver suspend routine.
2139 *      @pdev: Pointer to pci_dev structure
2140 *      @state: new state to enter
2141 */
2142int
2143mpt_suspend(struct pci_dev *pdev, pm_message_t state)
2144{
2145        u32 device_state;
2146        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2147
2148        device_state = pci_choose_state(pdev, state);
2149        printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering "
2150            "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2151            device_state);
2152
2153        /* put ioc into READY_STATE */
2154        if(SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) {
2155                printk(MYIOC_s_ERR_FMT
2156                "pci-suspend:  IOC msg unit reset failed!\n", ioc->name);
2157        }
2158
2159        /* disable interrupts */
2160        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2161        ioc->active = 0;
2162
2163        /* Clear any lingering interrupt */
2164        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2165
2166        free_irq(ioc->pci_irq, ioc);
2167        if (ioc->msi_enable)
2168                pci_disable_msi(ioc->pcidev);
2169        ioc->pci_irq = -1;
2170        pci_save_state(pdev);
2171        pci_disable_device(pdev);
2172        pci_release_selected_regions(pdev, ioc->bars);
2173        pci_set_power_state(pdev, device_state);
2174        return 0;
2175}
2176
2177/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2178/**
2179 *      mpt_resume - Fusion MPT base driver resume routine.
2180 *      @pdev: Pointer to pci_dev structure
2181 */
2182int
2183mpt_resume(struct pci_dev *pdev)
2184{
2185        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2186        u32 device_state = pdev->current_state;
2187        int recovery_state;
2188        int err;
2189
2190        printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous "
2191            "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev),
2192            device_state);
2193
2194        pci_set_power_state(pdev, PCI_D0);
2195        pci_enable_wake(pdev, PCI_D0, 0);
2196        pci_restore_state(pdev);
2197        ioc->pcidev = pdev;
2198        err = mpt_mapresources(ioc);
2199        if (err)
2200                return err;
2201
2202        if (ioc->dma_mask == DMA_BIT_MASK(64)) {
2203                if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078)
2204                        ioc->add_sge = &mpt_add_sge_64bit_1078;
2205                else
2206                        ioc->add_sge = &mpt_add_sge_64bit;
2207                ioc->add_chain = &mpt_add_chain_64bit;
2208                ioc->sg_addr_size = 8;
2209        } else {
2210
2211                ioc->add_sge = &mpt_add_sge;
2212                ioc->add_chain = &mpt_add_chain;
2213                ioc->sg_addr_size = 4;
2214        }
2215        ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size;
2216
2217        printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
2218            ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
2219            CHIPREG_READ32(&ioc->chip->Doorbell));
2220
2221        /*
2222         * Errata workaround for SAS pci express:
2223         * Upon returning to the D0 state, the contents of the doorbell will be
2224         * stale data, and this will incorrectly signal to the host driver that
2225         * the firmware is ready to process mpt commands.   The workaround is
2226         * to issue a diagnostic reset.
2227         */
2228        if (ioc->bus_type == SAS && (pdev->device ==
2229            MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device ==
2230            MPI_MANUFACTPAGE_DEVID_SAS1064E)) {
2231                if (KickStart(ioc, 1, CAN_SLEEP) < 0) {
2232                        printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n",
2233                            ioc->name);
2234                        goto out;
2235                }
2236        }
2237
2238        /* bring ioc to operational state */
2239        printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name);
2240        recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
2241                                                 CAN_SLEEP);
2242        if (recovery_state != 0)
2243                printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, "
2244                    "error:[%x]\n", ioc->name, recovery_state);
2245        else
2246                printk(MYIOC_s_INFO_FMT
2247                    "pci-resume: success\n", ioc->name);
2248 out:
2249        return 0;
2250
2251}
2252#endif
2253
2254static int
2255mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase)
2256{
2257        if ((MptDriverClass[index] == MPTSPI_DRIVER &&
2258             ioc->bus_type != SPI) ||
2259            (MptDriverClass[index] == MPTFC_DRIVER &&
2260             ioc->bus_type != FC) ||
2261            (MptDriverClass[index] == MPTSAS_DRIVER &&
2262             ioc->bus_type != SAS))
2263                /* make sure we only call the relevant reset handler
2264                 * for the bus */
2265                return 0;
2266        return (MptResetHandlers[index])(ioc, reset_phase);
2267}
2268
2269/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2270/**
2271 *      mpt_do_ioc_recovery - Initialize or recover MPT adapter.
2272 *      @ioc: Pointer to MPT adapter structure
2273 *      @reason: Event word / reason
2274 *      @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
2275 *
2276 *      This routine performs all the steps necessary to bring the IOC
2277 *      to a OPERATIONAL state.
2278 *
2279 *      This routine also pre-fetches the LAN MAC address of a Fibre Channel
2280 *      MPT adapter.
2281 *
2282 *      Returns:
2283 *               0 for success
2284 *              -1 if failed to get board READY
2285 *              -2 if READY but IOCFacts Failed
2286 *              -3 if READY but PrimeIOCFifos Failed
2287 *              -4 if READY but IOCInit Failed
2288 *              -5 if failed to enable_device and/or request_selected_regions
2289 *              -6 if failed to upload firmware
2290 */
2291static int
2292mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
2293{
2294        int      hard_reset_done = 0;
2295        int      alt_ioc_ready = 0;
2296        int      hard;
2297        int      rc=0;
2298        int      ii;
2299        int      ret = 0;
2300        int      reset_alt_ioc_active = 0;
2301        int      irq_allocated = 0;
2302        u8      *a;
2303
2304        printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name,
2305            reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
2306
2307        /* Disable reply interrupts (also blocks FreeQ) */
2308        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2309        ioc->active = 0;
2310
2311        if (ioc->alt_ioc) {
2312                if (ioc->alt_ioc->active ||
2313                    reason == MPT_HOSTEVENT_IOC_RECOVER) {
2314                        reset_alt_ioc_active = 1;
2315                        /* Disable alt-IOC's reply interrupts
2316                         *  (and FreeQ) for a bit
2317                         **/
2318                        CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2319                                0xFFFFFFFF);
2320                        ioc->alt_ioc->active = 0;
2321                }
2322        }
2323
2324        hard = 1;
2325        if (reason == MPT_HOSTEVENT_IOC_BRINGUP)
2326                hard = 0;
2327
2328        if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) {
2329                if (hard_reset_done == -4) {
2330                        printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n",
2331                            ioc->name);
2332
2333                        if (reset_alt_ioc_active && ioc->alt_ioc) {
2334                                /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
2335                                dprintk(ioc, printk(MYIOC_s_INFO_FMT
2336                                    "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name));
2337                                CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
2338                                ioc->alt_ioc->active = 1;
2339                        }
2340
2341                } else {
2342                        printk(MYIOC_s_WARN_FMT
2343                            "NOT READY WARNING!\n", ioc->name);
2344                }
2345                ret = -1;
2346                goto out;
2347        }
2348
2349        /* hard_reset_done = 0 if a soft reset was performed
2350         * and 1 if a hard reset was performed.
2351         */
2352        if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
2353                if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
2354                        alt_ioc_ready = 1;
2355                else
2356                        printk(MYIOC_s_WARN_FMT
2357                            ": alt-ioc Not ready WARNING!\n",
2358                            ioc->alt_ioc->name);
2359        }
2360
2361        for (ii=0; ii<5; ii++) {
2362                /* Get IOC facts! Allow 5 retries */
2363                if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
2364                        break;
2365        }
2366
2367
2368        if (ii == 5) {
2369                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2370                    "Retry IocFacts failed rc=%x\n", ioc->name, rc));
2371                ret = -2;
2372        } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2373                MptDisplayIocCapabilities(ioc);
2374        }
2375
2376        if (alt_ioc_ready) {
2377                if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
2378                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2379                            "Initial Alt IocFacts failed rc=%x\n",
2380                            ioc->name, rc));
2381                        /* Retry - alt IOC was initialized once
2382                         */
2383                        rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
2384                }
2385                if (rc) {
2386                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2387                            "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
2388                        alt_ioc_ready = 0;
2389                        reset_alt_ioc_active = 0;
2390                } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
2391                        MptDisplayIocCapabilities(ioc->alt_ioc);
2392                }
2393        }
2394
2395        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) &&
2396            (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) {
2397                pci_release_selected_regions(ioc->pcidev, ioc->bars);
2398                ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM |
2399                    IORESOURCE_IO);
2400                if (pci_enable_device(ioc->pcidev))
2401                        return -5;
2402                if (pci_request_selected_regions(ioc->pcidev, ioc->bars,
2403                        "mpt"))
2404                        return -5;
2405        }
2406
2407        /*
2408         * Device is reset now. It must have de-asserted the interrupt line
2409         * (if it was asserted) and it should be safe to register for the
2410         * interrupt now.
2411         */
2412        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2413                ioc->pci_irq = -1;
2414                if (ioc->pcidev->irq) {
2415                        if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev))
2416                                printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
2417                                    ioc->name);
2418                        else
2419                                ioc->msi_enable = 0;
2420                        rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
2421                            IRQF_SHARED, ioc->name, ioc);
2422                        if (rc < 0) {
2423                                printk(MYIOC_s_ERR_FMT "Unable to allocate "
2424                                    "interrupt %d!\n",
2425                                    ioc->name, ioc->pcidev->irq);
2426                                if (ioc->msi_enable)
2427                                        pci_disable_msi(ioc->pcidev);
2428                                ret = -EBUSY;
2429                                goto out;
2430                        }
2431                        irq_allocated = 1;
2432                        ioc->pci_irq = ioc->pcidev->irq;
2433                        pci_set_master(ioc->pcidev);            /* ?? */
2434                        pci_set_drvdata(ioc->pcidev, ioc);
2435                        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2436                            "installed at interrupt %d\n", ioc->name,
2437                            ioc->pcidev->irq));
2438                }
2439        }
2440
2441        /* Prime reply & request queues!
2442         * (mucho alloc's) Must be done prior to
2443         * init as upper addresses are needed for init.
2444         * If fails, continue with alt-ioc processing
2445         */
2446        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n",
2447            ioc->name));
2448        if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
2449                ret = -3;
2450
2451        /* May need to check/upload firmware & data here!
2452         * If fails, continue with alt-ioc processing
2453         */
2454        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n",
2455            ioc->name));
2456        if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
2457                ret = -4;
2458// NEW!
2459        if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
2460                printk(MYIOC_s_WARN_FMT
2461                    ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n",
2462                    ioc->alt_ioc->name, rc);
2463                alt_ioc_ready = 0;
2464                reset_alt_ioc_active = 0;
2465        }
2466
2467        if (alt_ioc_ready) {
2468                if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
2469                        alt_ioc_ready = 0;
2470                        reset_alt_ioc_active = 0;
2471                        printk(MYIOC_s_WARN_FMT
2472                                ": alt-ioc: (%d) init failure WARNING!\n",
2473                                        ioc->alt_ioc->name, rc);
2474                }
2475        }
2476
2477        if (reason == MPT_HOSTEVENT_IOC_BRINGUP){
2478                if (ioc->upload_fw) {
2479                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2480                            "firmware upload required!\n", ioc->name));
2481
2482                        /* Controller is not operational, cannot do upload
2483                         */
2484                        if (ret == 0) {
2485                                rc = mpt_do_upload(ioc, sleepFlag);
2486                                if (rc == 0) {
2487                                        if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
2488                                                /*
2489                                                 * Maintain only one pointer to FW memory
2490                                                 * so there will not be two attempt to
2491                                                 * downloadboot onboard dual function
2492                                                 * chips (mpt_adapter_disable,
2493                                                 * mpt_diag_reset)
2494                                                 */
2495                                                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2496                                                    "mpt_upload:  alt_%s has cached_fw=%p \n",
2497                                                    ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw));
2498                                                ioc->cached_fw = NULL;
2499                                        }
2500                                } else {
2501                                        printk(MYIOC_s_WARN_FMT
2502                                            "firmware upload failure!\n", ioc->name);
2503                                        ret = -6;
2504                                }
2505                        }
2506                }
2507        }
2508
2509        /*  Enable MPT base driver management of EventNotification
2510         *  and EventAck handling.
2511         */
2512        if ((ret == 0) && (!ioc->facts.EventState)) {
2513                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2514                        "SendEventNotification\n",
2515                    ioc->name));
2516                ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */
2517        }
2518
2519        if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
2520                rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag);
2521
2522        if (ret == 0) {
2523                /* Enable! (reply interrupt) */
2524                CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
2525                ioc->active = 1;
2526        }
2527        if (rc == 0) {  /* alt ioc */
2528                if (reset_alt_ioc_active && ioc->alt_ioc) {
2529                        /* (re)Enable alt-IOC! (reply interrupt) */
2530                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc"
2531                                "reply irq re-enabled\n",
2532                                ioc->alt_ioc->name));
2533                        CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask,
2534                                MPI_HIM_DIM);
2535                        ioc->alt_ioc->active = 1;
2536                }
2537        }
2538
2539
2540        /*      Add additional "reason" check before call to GetLanConfigPages
2541         *      (combined with GetIoUnitPage2 call).  This prevents a somewhat
2542         *      recursive scenario; GetLanConfigPages times out, timer expired
2543         *      routine calls HardResetHandler, which calls into here again,
2544         *      and we try GetLanConfigPages again...
2545         */
2546        if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
2547
2548                /*
2549                 * Initialize link list for inactive raid volumes.
2550                 */
2551                mutex_init(&ioc->raid_data.inactive_list_mutex);
2552                INIT_LIST_HEAD(&ioc->raid_data.inactive_list);
2553
2554                switch (ioc->bus_type) {
2555
2556                case SAS:
2557                        /* clear persistency table */
2558                        if(ioc->facts.IOCExceptions &
2559                            MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) {
2560                                ret = mptbase_sas_persist_operation(ioc,
2561                                    MPI_SAS_OP_CLEAR_NOT_PRESENT);
2562                                if(ret != 0)
2563                                        goto out;
2564                        }
2565
2566                        /* Find IM volumes
2567                         */
2568                        mpt_findImVolumes(ioc);
2569
2570                        /* Check, and possibly reset, the coalescing value
2571                         */
2572                        mpt_read_ioc_pg_1(ioc);
2573
2574                        break;
2575
2576                case FC:
2577                        if ((ioc->pfacts[0].ProtocolFlags &
2578                                MPI_PORTFACTS_PROTOCOL_LAN) &&
2579                            (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
2580                                /*
2581                                 *  Pre-fetch the ports LAN MAC address!
2582                                 *  (LANPage1_t stuff)
2583                                 */
2584                                (void) GetLanConfigPages(ioc);
2585                                a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
2586                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2587                                        "LanAddr = %02X:%02X:%02X"
2588                                        ":%02X:%02X:%02X\n",
2589                                        ioc->name, a[5], a[4],
2590                                        a[3], a[2], a[1], a[0]));
2591                        }
2592                        break;
2593
2594                case SPI:
2595                        /* Get NVRAM and adapter maximums from SPP 0 and 2
2596                         */
2597                        mpt_GetScsiPortSettings(ioc, 0);
2598
2599                        /* Get version and length of SDP 1
2600                         */
2601                        mpt_readScsiDevicePageHeaders(ioc, 0);
2602
2603                        /* Find IM volumes
2604                         */
2605                        if (ioc->facts.MsgVersion >= MPI_VERSION_01_02)
2606                                mpt_findImVolumes(ioc);
2607
2608                        /* Check, and possibly reset, the coalescing value
2609                         */
2610                        mpt_read_ioc_pg_1(ioc);
2611
2612                        mpt_read_ioc_pg_4(ioc);
2613
2614                        break;
2615                }
2616
2617                GetIoUnitPage2(ioc);
2618                mpt_get_manufacturing_pg_0(ioc);
2619        }
2620
2621 out:
2622        if ((ret != 0) && irq_allocated) {
2623                free_irq(ioc->pci_irq, ioc);
2624                if (ioc->msi_enable)
2625                        pci_disable_msi(ioc->pcidev);
2626        }
2627        return ret;
2628}
2629
2630/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2631/**
2632 *      mpt_detect_bound_ports - Search for matching PCI bus/dev_function
2633 *      @ioc: Pointer to MPT adapter structure
2634 *      @pdev: Pointer to (struct pci_dev) structure
2635 *
2636 *      Search for PCI bus/dev_function which matches
2637 *      PCI bus/dev_function (+/-1) for newly discovered 929,
2638 *      929X, 1030 or 1035.
2639 *
2640 *      If match on PCI dev_function +/-1 is found, bind the two MPT adapters
2641 *      using alt_ioc pointer fields in their %MPT_ADAPTER structures.
2642 */
2643static void
2644mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
2645{
2646        struct pci_dev *peer=NULL;
2647        unsigned int slot = PCI_SLOT(pdev->devfn);
2648        unsigned int func = PCI_FUNC(pdev->devfn);
2649        MPT_ADAPTER *ioc_srch;
2650
2651        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x,"
2652            " searching for devfn match on %x or %x\n",
2653            ioc->name, pci_name(pdev), pdev->bus->number,
2654            pdev->devfn, func-1, func+1));
2655
2656        peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
2657        if (!peer) {
2658                peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
2659                if (!peer)
2660                        return;
2661        }
2662
2663        list_for_each_entry(ioc_srch, &ioc_list, list) {
2664                struct pci_dev *_pcidev = ioc_srch->pcidev;
2665                if (_pcidev == peer) {
2666                        /* Paranoia checks */
2667                        if (ioc->alt_ioc != NULL) {
2668                                printk(MYIOC_s_WARN_FMT
2669                                    "Oops, already bound (%s <==> %s)!\n",
2670                                    ioc->name, ioc->name, ioc->alt_ioc->name);
2671                                break;
2672                        } else if (ioc_srch->alt_ioc != NULL) {
2673                                printk(MYIOC_s_WARN_FMT
2674                                    "Oops, already bound (%s <==> %s)!\n",
2675                                    ioc_srch->name, ioc_srch->name,
2676                                    ioc_srch->alt_ioc->name);
2677                                break;
2678                        }
2679                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2680                                "FOUND! binding %s <==> %s\n",
2681                                ioc->name, ioc->name, ioc_srch->name));
2682                        ioc_srch->alt_ioc = ioc;
2683                        ioc->alt_ioc = ioc_srch;
2684                }
2685        }
2686        pci_dev_put(peer);
2687}
2688
2689/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2690/**
2691 *      mpt_adapter_disable - Disable misbehaving MPT adapter.
2692 *      @ioc: Pointer to MPT adapter structure
2693 */
2694static void
2695mpt_adapter_disable(MPT_ADAPTER *ioc)
2696{
2697        int sz;
2698        int ret;
2699
2700        if (ioc->cached_fw != NULL) {
2701                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2702                        "%s: Pushing FW onto adapter\n", __func__, ioc->name));
2703                if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)
2704                    ioc->cached_fw, CAN_SLEEP)) < 0) {
2705                        printk(MYIOC_s_WARN_FMT
2706                            ": firmware downloadboot failure (%d)!\n",
2707                            ioc->name, ret);
2708                }
2709        }
2710
2711        /*
2712         * Put the controller into ready state (if its not already)
2713         */
2714        if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) {
2715                if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET,
2716                    CAN_SLEEP)) {
2717                        if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY)
2718                                printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit "
2719                                    "reset failed to put ioc in ready state!\n",
2720                                    ioc->name, __func__);
2721                } else
2722                        printk(MYIOC_s_ERR_FMT "%s:  IOC msg unit reset "
2723                            "failed!\n", ioc->name, __func__);
2724        }
2725
2726
2727        /* Disable adapter interrupts! */
2728        synchronize_irq(ioc->pcidev->irq);
2729        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
2730        ioc->active = 0;
2731
2732        /* Clear any lingering interrupt */
2733        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
2734        CHIPREG_READ32(&ioc->chip->IntStatus);
2735
2736        if (ioc->alloc != NULL) {
2737                sz = ioc->alloc_sz;
2738                dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free  @ %p, sz=%d bytes\n",
2739                    ioc->name, ioc->alloc, ioc->alloc_sz));
2740                pci_free_consistent(ioc->pcidev, sz,
2741                                ioc->alloc, ioc->alloc_dma);
2742                ioc->reply_frames = NULL;
2743                ioc->req_frames = NULL;
2744                ioc->alloc = NULL;
2745                ioc->alloc_total -= sz;
2746        }
2747
2748        if (ioc->sense_buf_pool != NULL) {
2749                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
2750                pci_free_consistent(ioc->pcidev, sz,
2751                                ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
2752                ioc->sense_buf_pool = NULL;
2753                ioc->alloc_total -= sz;
2754        }
2755
2756        if (ioc->events != NULL){
2757                sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
2758                kfree(ioc->events);
2759                ioc->events = NULL;
2760                ioc->alloc_total -= sz;
2761        }
2762
2763        mpt_free_fw_memory(ioc);
2764
2765        kfree(ioc->spi_data.nvram);
2766        mpt_inactive_raid_list_free(ioc);
2767        kfree(ioc->raid_data.pIocPg2);
2768        kfree(ioc->raid_data.pIocPg3);
2769        ioc->spi_data.nvram = NULL;
2770        ioc->raid_data.pIocPg3 = NULL;
2771
2772        if (ioc->spi_data.pIocPg4 != NULL) {
2773                sz = ioc->spi_data.IocPg4Sz;
2774                pci_free_consistent(ioc->pcidev, sz,
2775                        ioc->spi_data.pIocPg4,
2776                        ioc->spi_data.IocPg4_dma);
2777                ioc->spi_data.pIocPg4 = NULL;
2778                ioc->alloc_total -= sz;
2779        }
2780
2781        if (ioc->ReqToChain != NULL) {
2782                kfree(ioc->ReqToChain);
2783                kfree(ioc->RequestNB);
2784                ioc->ReqToChain = NULL;
2785        }
2786
2787        kfree(ioc->ChainToChain);
2788        ioc->ChainToChain = NULL;
2789
2790        if (ioc->HostPageBuffer != NULL) {
2791                if((ret = mpt_host_page_access_control(ioc,
2792                    MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) {
2793                        printk(MYIOC_s_ERR_FMT
2794                           ": %s: host page buffers free failed (%d)!\n",
2795                            ioc->name, __func__, ret);
2796                }
2797                dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
2798                        "HostPageBuffer free  @ %p, sz=%d bytes\n",
2799                        ioc->name, ioc->HostPageBuffer,
2800                        ioc->HostPageBuffer_sz));
2801                pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz,
2802                    ioc->HostPageBuffer, ioc->HostPageBuffer_dma);
2803                ioc->HostPageBuffer = NULL;
2804                ioc->HostPageBuffer_sz = 0;
2805                ioc->alloc_total -= ioc->HostPageBuffer_sz;
2806        }
2807
2808        pci_set_drvdata(ioc->pcidev, NULL);
2809}
2810/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2811/**
2812 *      mpt_adapter_dispose - Free all resources associated with an MPT adapter
2813 *      @ioc: Pointer to MPT adapter structure
2814 *
2815 *      This routine unregisters h/w resources and frees all alloc'd memory
2816 *      associated with a MPT adapter structure.
2817 */
2818static void
2819mpt_adapter_dispose(MPT_ADAPTER *ioc)
2820{
2821        int sz_first, sz_last;
2822
2823        if (ioc == NULL)
2824                return;
2825
2826        sz_first = ioc->alloc_total;
2827
2828        mpt_adapter_disable(ioc);
2829
2830        if (ioc->pci_irq != -1) {
2831                free_irq(ioc->pci_irq, ioc);
2832                if (ioc->msi_enable)
2833                        pci_disable_msi(ioc->pcidev);
2834                ioc->pci_irq = -1;
2835        }
2836
2837        if (ioc->memmap != NULL) {
2838                iounmap(ioc->memmap);
2839                ioc->memmap = NULL;
2840        }
2841
2842        pci_disable_device(ioc->pcidev);
2843        pci_release_selected_regions(ioc->pcidev, ioc->bars);
2844
2845        /*  Zap the adapter lookup ptr!  */
2846        list_del(&ioc->list);
2847
2848        sz_last = ioc->alloc_total;
2849        dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n",
2850            ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
2851
2852        if (ioc->alt_ioc)
2853                ioc->alt_ioc->alt_ioc = NULL;
2854
2855        kfree(ioc);
2856}
2857
2858/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2859/**
2860 *      MptDisplayIocCapabilities - Disply IOC's capabilities.
2861 *      @ioc: Pointer to MPT adapter structure
2862 */
2863static void
2864MptDisplayIocCapabilities(MPT_ADAPTER *ioc)
2865{
2866        int i = 0;
2867
2868        printk(KERN_INFO "%s: ", ioc->name);
2869        if (ioc->prod_name)
2870                printk("%s: ", ioc->prod_name);
2871        printk("Capabilities={");
2872
2873        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
2874                printk("Initiator");
2875                i++;
2876        }
2877
2878        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2879                printk("%sTarget", i ? "," : "");
2880                i++;
2881        }
2882
2883        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
2884                printk("%sLAN", i ? "," : "");
2885                i++;
2886        }
2887
2888#if 0
2889        /*
2890         *  This would probably evoke more questions than it's worth
2891         */
2892        if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
2893                printk("%sLogBusAddr", i ? "," : "");
2894                i++;
2895        }
2896#endif
2897
2898        printk("}\n");
2899}
2900
2901/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2902/**
2903 *      MakeIocReady - Get IOC to a READY state, using KickStart if needed.
2904 *      @ioc: Pointer to MPT_ADAPTER structure
2905 *      @force: Force hard KickStart of IOC
2906 *      @sleepFlag: Specifies whether the process can sleep
2907 *
2908 *      Returns:
2909 *               1 - DIAG reset and READY
2910 *               0 - READY initially OR soft reset and READY
2911 *              -1 - Any failure on KickStart
2912 *              -2 - Msg Unit Reset Failed
2913 *              -3 - IO Unit Reset Failed
2914 *              -4 - IOC owned by a PEER
2915 */
2916static int
2917MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
2918{
2919        u32      ioc_state;
2920        int      statefault = 0;
2921        int      cntdn;
2922        int      hard_reset_done = 0;
2923        int      r;
2924        int      ii;
2925        int      whoinit;
2926
2927        /* Get current [raw] IOC state  */
2928        ioc_state = mpt_GetIocState(ioc, 0);
2929        dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state));
2930
2931        /*
2932         *      Check to see if IOC got left/stuck in doorbell handshake
2933         *      grip of death.  If so, hard reset the IOC.
2934         */
2935        if (ioc_state & MPI_DOORBELL_ACTIVE) {
2936                statefault = 1;
2937                printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n",
2938                                ioc->name);
2939        }
2940
2941        /* Is it already READY? */
2942        if (!statefault &&
2943            ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) {
2944                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2945                    "IOC is in READY state\n", ioc->name));
2946                return 0;
2947        }
2948
2949        /*
2950         *      Check to see if IOC is in FAULT state.
2951         */
2952        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
2953                statefault = 2;
2954                printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n",
2955                    ioc->name);
2956                printk(MYIOC_s_WARN_FMT "           FAULT code = %04xh\n",
2957                    ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK);
2958        }
2959
2960        /*
2961         *      Hmmm...  Did it get left operational?
2962         */
2963        if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
2964                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n",
2965                                ioc->name));
2966
2967                /* Check WhoInit.
2968                 * If PCI Peer, exit.
2969                 * Else, if no fault conditions are present, issue a MessageUnitReset
2970                 * Else, fall through to KickStart case
2971                 */
2972                whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT;
2973                dinitprintk(ioc, printk(MYIOC_s_INFO_FMT
2974                        "whoinit 0x%x statefault %d force %d\n",
2975                        ioc->name, whoinit, statefault, force));
2976                if (whoinit == MPI_WHOINIT_PCI_PEER)
2977                        return -4;
2978                else {
2979                        if ((statefault == 0 ) && (force == 0)) {
2980                                if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
2981                                        return 0;
2982                        }
2983                        statefault = 3;
2984                }
2985        }
2986
2987        hard_reset_done = KickStart(ioc, statefault||force, sleepFlag);
2988        if (hard_reset_done < 0)
2989                return -1;
2990
2991        /*
2992         *  Loop here waiting for IOC to come READY.
2993         */
2994        ii = 0;
2995        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5;     /* 5 seconds */
2996
2997        while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
2998                if (ioc_state == MPI_IOC_STATE_OPERATIONAL) {
2999                        /*
3000                         *  BIOS or previous driver load left IOC in OP state.
3001                         *  Reset messaging FIFOs.
3002                         */
3003                        if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) {
3004                                printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name);
3005                                return -2;
3006                        }
3007                } else if (ioc_state == MPI_IOC_STATE_RESET) {
3008                        /*
3009                         *  Something is wrong.  Try to get IOC back
3010                         *  to a known state.
3011                         */
3012                        if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) {
3013                                printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name);
3014                                return -3;
3015                        }
3016                }
3017
3018                ii++; cntdn--;
3019                if (!cntdn) {
3020                        printk(MYIOC_s_ERR_FMT
3021                                "Wait IOC_READY state (0x%x) timeout(%d)!\n",
3022                                ioc->name, ioc_state, (int)((ii+5)/HZ));
3023                        return -ETIME;
3024                }
3025
3026                if (sleepFlag == CAN_SLEEP) {
3027                        msleep(1);
3028                } else {
3029                        mdelay (1);     /* 1 msec delay */
3030                }
3031
3032        }
3033
3034        if (statefault < 3) {
3035                printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name,
3036                        statefault == 1 ? "stuck handshake" : "IOC FAULT");
3037        }
3038
3039        return hard_reset_done;
3040}
3041
3042/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3043/**
3044 *      mpt_GetIocState - Get the current state of a MPT adapter.
3045 *      @ioc: Pointer to MPT_ADAPTER structure
3046 *      @cooked: Request raw or cooked IOC state
3047 *
3048 *      Returns all IOC Doorbell register bits if cooked==0, else just the
3049 *      Doorbell bits in MPI_IOC_STATE_MASK.
3050 */
3051u32
3052mpt_GetIocState(MPT_ADAPTER *ioc, int cooked)
3053{
3054        u32 s, sc;
3055
3056        /*  Get!  */
3057        s = CHIPREG_READ32(&ioc->chip->Doorbell);
3058        sc = s & MPI_IOC_STATE_MASK;
3059
3060        /*  Save!  */
3061        ioc->last_state = sc;
3062
3063        return cooked ? sc : s;
3064}
3065
3066/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3067/**
3068 *      GetIocFacts - Send IOCFacts request to MPT adapter.
3069 *      @ioc: Pointer to MPT_ADAPTER structure
3070 *      @sleepFlag: Specifies whether the process can sleep
3071 *      @reason: If recovery, only update facts.
3072 *
3073 *      Returns 0 for success, non-zero for failure.
3074 */
3075static int
3076GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
3077{
3078        IOCFacts_t               get_facts;
3079        IOCFactsReply_t         *facts;
3080        int                      r;
3081        int                      req_sz;
3082        int                      reply_sz;
3083        int                      sz;
3084        u32                      status, vv;
3085        u8                       shiftFactor=1;
3086
3087        /* IOC *must* NOT be in RESET state! */
3088        if (ioc->last_state == MPI_IOC_STATE_RESET) {
3089                printk(KERN_ERR MYNAM
3090                    ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n",
3091                    ioc->name, ioc->last_state);
3092                return -44;
3093        }
3094
3095        facts = &ioc->facts;
3096
3097        /* Destination (reply area)... */
3098        reply_sz = sizeof(*facts);
3099        memset(facts, 0, reply_sz);
3100
3101        /* Request area (get_facts on the stack right now!) */
3102        req_sz = sizeof(get_facts);
3103        memset(&get_facts, 0, req_sz);
3104
3105        get_facts.Function = MPI_FUNCTION_IOC_FACTS;
3106        /* Assert: All other get_facts fields are zero! */
3107
3108        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3109            "Sending get IocFacts request req_sz=%d reply_sz=%d\n",
3110            ioc->name, req_sz, reply_sz));
3111
3112        /* No non-zero fields in the get_facts request are greater than
3113         * 1 byte in size, so we can just fire it off as is.
3114         */
3115        r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
3116                        reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
3117        if (r != 0)
3118                return r;
3119
3120        /*
3121         * Now byte swap (GRRR) the necessary fields before any further
3122         * inspection of reply contents.
3123         *
3124         * But need to do some sanity checks on MsgLength (byte) field
3125         * to make sure we don't zero IOC's req_sz!
3126         */
3127        /* Did we get a valid reply? */
3128        if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) {
3129                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3130                        /*
3131                         * If not been here, done that, save off first WhoInit value
3132                         */
3133                        if (ioc->FirstWhoInit == WHOINIT_UNKNOWN)
3134                                ioc->FirstWhoInit = facts->WhoInit;
3135                }
3136
3137                facts->MsgVersion = le16_to_cpu(facts->MsgVersion);
3138                facts->MsgContext = le32_to_cpu(facts->MsgContext);
3139                facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions);
3140                facts->IOCStatus = le16_to_cpu(facts->IOCStatus);
3141                facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo);
3142                status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK;
3143                /* CHECKME! IOCStatus, IOCLogInfo */
3144
3145                facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth);
3146                facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize);
3147
3148                /*
3149                 * FC f/w version changed between 1.1 and 1.2
3150                 *      Old: u16{Major(4),Minor(4),SubMinor(8)}
3151                 *      New: u32{Major(8),Minor(8),Unit(8),Dev(8)}
3152                 */
3153                if (facts->MsgVersion < MPI_VERSION_01_02) {
3154                        /*
3155                         *      Handle old FC f/w style, convert to new...
3156                         */
3157                        u16      oldv = le16_to_cpu(facts->Reserved_0101_FWVersion);
3158                        facts->FWVersion.Word =
3159                                        ((oldv<<12) & 0xFF000000) |
3160                                        ((oldv<<8)  & 0x000FFF00);
3161                } else
3162                        facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word);
3163
3164                facts->ProductID = le16_to_cpu(facts->ProductID);
3165
3166                if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK)
3167                    > MPI_FW_HEADER_PID_PROD_TARGET_SCSI)
3168                        ioc->ir_firmware = 1;
3169
3170                facts->CurrentHostMfaHighAddr =
3171                                le32_to_cpu(facts->CurrentHostMfaHighAddr);
3172                facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits);
3173                facts->CurrentSenseBufferHighAddr =
3174                                le32_to_cpu(facts->CurrentSenseBufferHighAddr);
3175                facts->CurReplyFrameSize =
3176                                le16_to_cpu(facts->CurReplyFrameSize);
3177                facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities);
3178
3179                /*
3180                 * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx
3181                 * Older MPI-1.00.xx struct had 13 dwords, and enlarged
3182                 * to 14 in MPI-1.01.0x.
3183                 */
3184                if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 &&
3185                    facts->MsgVersion > MPI_VERSION_01_00) {
3186                        facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
3187                }
3188
3189                facts->FWImageSize = ALIGN(facts->FWImageSize, 4);
3190
3191                if (!facts->RequestFrameSize) {
3192                        /*  Something is wrong!  */
3193                        printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
3194                                        ioc->name);
3195                        return -55;
3196                }
3197
3198                r = sz = facts->BlockSize;
3199                vv = ((63 / (sz * 4)) + 1) & 0x03;
3200                ioc->NB_for_64_byte_frame = vv;
3201                while ( sz )
3202                {
3203                        shiftFactor++;
3204                        sz = sz >> 1;
3205                }
3206                ioc->NBShiftFactor  = shiftFactor;
3207                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3208                    "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
3209                    ioc->name, vv, shiftFactor, r));
3210
3211                if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
3212                        /*
3213                         * Set values for this IOC's request & reply frame sizes,
3214                         * and request & reply queue depths...
3215                         */
3216                        ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4);
3217                        ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits);
3218                        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
3219                        ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
3220
3221                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n",
3222                                ioc->name, ioc->reply_sz, ioc->reply_depth));
3223                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz  =%3d, req_depth  =%4d\n",
3224                                ioc->name, ioc->req_sz, ioc->req_depth));
3225
3226                        /* Get port facts! */
3227                        if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 )
3228                                return r;
3229                }
3230        } else {
3231                printk(MYIOC_s_ERR_FMT
3232                     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
3233                     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
3234                     RequestFrameSize)/sizeof(u32)));
3235                return -66;
3236        }
3237
3238        return 0;
3239}
3240
3241/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3242/**
3243 *      GetPortFacts - Send PortFacts request to MPT adapter.
3244 *      @ioc: Pointer to MPT_ADAPTER structure
3245 *      @portnum: Port number
3246 *      @sleepFlag: Specifies whether the process can sleep
3247 *
3248 *      Returns 0 for success, non-zero for failure.
3249 */
3250static int
3251GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3252{
3253        PortFacts_t              get_pfacts;
3254        PortFactsReply_t        *pfacts;
3255        int                      ii;
3256        int                      req_sz;
3257        int                      reply_sz;
3258        int                      max_id;
3259
3260        /* IOC *must* NOT be in RESET state! */
3261        if (ioc->last_state == MPI_IOC_STATE_RESET) {
3262                printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n",
3263                    ioc->name, ioc->last_state );
3264                return -4;
3265        }
3266
3267        pfacts = &ioc->pfacts[portnum];
3268
3269        /* Destination (reply area)...  */
3270        reply_sz = sizeof(*pfacts);
3271        memset(pfacts, 0, reply_sz);
3272
3273        /* Request area (get_pfacts on the stack right now!) */
3274        req_sz = sizeof(get_pfacts);
3275        memset(&get_pfacts, 0, req_sz);
3276
3277        get_pfacts.Function = MPI_FUNCTION_PORT_FACTS;
3278        get_pfacts.PortNumber = portnum;
3279        /* Assert: All other get_pfacts fields are zero! */
3280
3281        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n",
3282                        ioc->name, portnum));
3283
3284        /* No non-zero fields in the get_pfacts request are greater than
3285         * 1 byte in size, so we can just fire it off as is.
3286         */
3287        ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
3288                                reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
3289        if (ii != 0)
3290                return ii;
3291
3292        /* Did we get a valid reply? */
3293
3294        /* Now byte swap the necessary fields in the response. */
3295        pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext);
3296        pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus);
3297        pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo);
3298        pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices);
3299        pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID);
3300        pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags);
3301        pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers);
3302        pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs);
3303        pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets);
3304
3305        max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID :
3306            pfacts->MaxDevices;
3307        ioc->devices_per_bus = (max_id > 255) ? 256 : max_id;
3308        ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256;
3309
3310        /*
3311         * Place all the devices on channels
3312         *
3313         * (for debuging)
3314         */
3315        if (mpt_channel_mapping) {
3316                ioc->devices_per_bus = 1;
3317                ioc->number_of_buses = (max_id > 255) ? 255 : max_id;
3318        }
3319
3320        return 0;
3321}
3322
3323/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3324/**
3325 *      SendIocInit - Send IOCInit request to MPT adapter.
3326 *      @ioc: Pointer to MPT_ADAPTER structure
3327 *      @sleepFlag: Specifies whether the process can sleep
3328 *
3329 *      Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state.
3330 *
3331 *      Returns 0 for success, non-zero for failure.
3332 */
3333static int
3334SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
3335{
3336        IOCInit_t                ioc_init;
3337        MPIDefaultReply_t        init_reply;
3338        u32                      state;
3339        int                      r;
3340        int                      count;
3341        int                      cntdn;
3342
3343        memset(&ioc_init, 0, sizeof(ioc_init));
3344        memset(&init_reply, 0, sizeof(init_reply));
3345
3346        ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
3347        ioc_init.Function = MPI_FUNCTION_IOC_INIT;
3348
3349        /* If we are in a recovery mode and we uploaded the FW image,
3350         * then this pointer is not NULL. Skip the upload a second time.
3351         * Set this flag if cached_fw set for either IOC.
3352         */
3353        if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
3354                ioc->upload_fw = 1;
3355        else
3356                ioc->upload_fw = 0;
3357        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n",
3358                   ioc->name, ioc->upload_fw, ioc->facts.Flags));
3359
3360        ioc_init.MaxDevices = (U8)ioc->devices_per_bus;
3361        ioc_init.MaxBuses = (U8)ioc->number_of_buses;
3362
3363        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n",
3364                   ioc->name, ioc->facts.MsgVersion));
3365        if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) {
3366                // set MsgVersion and HeaderVersion host driver was built with
3367                ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION);
3368                ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION);
3369
3370                if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) {
3371                        ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE;
3372                } else if(mpt_host_page_alloc(ioc, &ioc_init))
3373                        return -99;
3374        }
3375        ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);   /* in BYTES */
3376
3377        if (ioc->sg_addr_size == sizeof(u64)) {
3378                /* Save the upper 32-bits of the request
3379                 * (reply) and sense buffers.
3380                 */
3381                ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
3382                ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
3383        } else {
3384                /* Force 32-bit addressing */
3385                ioc_init.HostMfaHighAddr = cpu_to_le32(0);
3386                ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
3387        }
3388
3389        ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr;
3390        ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr;
3391        ioc->facts.MaxDevices = ioc_init.MaxDevices;
3392        ioc->facts.MaxBuses = ioc_init.MaxBuses;
3393
3394        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n",
3395                        ioc->name, &ioc_init));
3396
3397        r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
3398                                sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag);
3399        if (r != 0) {
3400                printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r);
3401                return r;
3402        }
3403
3404        /* No need to byte swap the multibyte fields in the reply
3405         * since we don't even look at its contents.
3406         */
3407
3408        dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n",
3409                        ioc->name, &ioc_init));
3410
3411        if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) {
3412                printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r);
3413                return r;
3414        }
3415
3416        /* YIKES!  SUPER IMPORTANT!!!
3417         *  Poll IocState until _OPERATIONAL while IOC is doing
3418         *  LoopInit and TargetDiscovery!
3419         */
3420        count = 0;
3421        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60;    /* 60 seconds */
3422        state = mpt_GetIocState(ioc, 1);
3423        while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
3424                if (sleepFlag == CAN_SLEEP) {
3425                        msleep(1);
3426                } else {
3427                        mdelay(1);
3428                }
3429
3430                if (!cntdn) {
3431                        printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
3432                                        ioc->name, (int)((count+5)/HZ));
3433                        return -9;
3434                }
3435
3436                state = mpt_GetIocState(ioc, 1);
3437                count++;
3438        }
3439        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n",
3440                        ioc->name, count));
3441
3442        ioc->aen_event_read_flag=0;
3443        return r;
3444}
3445
3446/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3447/**
3448 *      SendPortEnable - Send PortEnable request to MPT adapter port.
3449 *      @ioc: Pointer to MPT_ADAPTER structure
3450 *      @portnum: Port number to enable
3451 *      @sleepFlag: Specifies whether the process can sleep
3452 *
3453 *      Send PortEnable to bring IOC to OPERATIONAL state.
3454 *
3455 *      Returns 0 for success, non-zero for failure.
3456 */
3457static int
3458SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
3459{
3460        PortEnable_t             port_enable;
3461        MPIDefaultReply_t        reply_buf;
3462        int      rc;
3463        int      req_sz;
3464        int      reply_sz;
3465
3466        /*  Destination...  */
3467        reply_sz = sizeof(MPIDefaultReply_t);
3468        memset(&reply_buf, 0, reply_sz);
3469
3470        req_sz = sizeof(PortEnable_t);
3471        memset(&port_enable, 0, req_sz);
3472
3473        port_enable.Function = MPI_FUNCTION_PORT_ENABLE;
3474        port_enable.PortNumber = portnum;
3475/*      port_enable.ChainOffset = 0;            */
3476/*      port_enable.MsgFlags = 0;               */
3477/*      port_enable.MsgContext = 0;             */
3478
3479        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n",
3480                        ioc->name, portnum, &port_enable));
3481
3482        /* RAID FW may take a long time to enable
3483         */
3484        if (ioc->ir_firmware || ioc->bus_type == SAS) {
3485                rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3486                (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3487                300 /*seconds*/, sleepFlag);
3488        } else {
3489                rc = mpt_handshake_req_reply_wait(ioc, req_sz,
3490                (u32*)&port_enable, reply_sz, (u16*)&reply_buf,
3491                30 /*seconds*/, sleepFlag);
3492        }
3493        return rc;
3494}
3495
3496/**
3497 *      mpt_alloc_fw_memory - allocate firmware memory
3498 *      @ioc: Pointer to MPT_ADAPTER structure
3499 *      @size: total FW bytes
3500 *
3501 *      If memory has already been allocated, the same (cached) value
3502 *      is returned.
3503 *
3504 *      Return 0 if successful, or non-zero for failure
3505 **/
3506int
3507mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
3508{
3509        int rc;
3510
3511        if (ioc->cached_fw) {
3512                rc = 0;  /* use already allocated memory */
3513                goto out;
3514        }
3515        else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
3516                ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
3517                ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
3518                rc = 0;
3519                goto out;
3520        }
3521        ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma);
3522        if (!ioc->cached_fw) {
3523                printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n",
3524                    ioc->name);
3525                rc = -1;
3526        } else {
3527                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3528                    ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size));
3529                ioc->alloc_total += size;
3530                rc = 0;
3531        }
3532 out:
3533        return rc;
3534}
3535
3536/**
3537 *      mpt_free_fw_memory - free firmware memory
3538 *      @ioc: Pointer to MPT_ADAPTER structure
3539 *
3540 *      If alt_img is NULL, delete from ioc structure.
3541 *      Else, delete a secondary image in same format.
3542 **/
3543void
3544mpt_free_fw_memory(MPT_ADAPTER *ioc)
3545{
3546        int sz;
3547
3548        if (!ioc->cached_fw)
3549                return;
3550
3551        sz = ioc->facts.FWImageSize;
3552        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3553                 ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3554        pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma);
3555        ioc->alloc_total -= sz;
3556        ioc->cached_fw = NULL;
3557}
3558
3559/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3560/**
3561 *      mpt_do_upload - Construct and Send FWUpload request to MPT adapter port.
3562 *      @ioc: Pointer to MPT_ADAPTER structure
3563 *      @sleepFlag: Specifies whether the process can sleep
3564 *
3565 *      Returns 0 for success, >0 for handshake failure
3566 *              <0 for fw upload failure.
3567 *
3568 *      Remark: If bound IOC and a successful FWUpload was performed
3569 *      on the bound IOC, the second image is discarded
3570 *      and memory is free'd. Both channels must upload to prevent
3571 *      IOC from running in degraded mode.
3572 */
3573static int
3574mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
3575{
3576        u8                       reply[sizeof(FWUploadReply_t)];
3577        FWUpload_t              *prequest;
3578        FWUploadReply_t         *preply;
3579        FWUploadTCSGE_t         *ptcsge;
3580        u32                      flagsLength;
3581        int                      ii, sz, reply_sz;
3582        int                      cmdStatus;
3583        int                     request_size;
3584        /* If the image size is 0, we are done.
3585         */
3586        if ((sz = ioc->facts.FWImageSize) == 0)
3587                return 0;
3588
3589        if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0)
3590                return -ENOMEM;
3591
3592        dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
3593            ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
3594
3595        prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) :
3596            kzalloc(ioc->req_sz, GFP_KERNEL);
3597        if (!prequest) {
3598                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed "
3599                    "while allocating memory \n", ioc->name));
3600                mpt_free_fw_memory(ioc);
3601                return -ENOMEM;
3602        }
3603
3604        preply = (FWUploadReply_t *)&reply;
3605
3606        reply_sz = sizeof(reply);
3607        memset(preply, 0, reply_sz);
3608
3609        prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
3610        prequest->Function = MPI_FUNCTION_FW_UPLOAD;
3611
3612        ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
3613        ptcsge->DetailsLength = 12;
3614        ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
3615        ptcsge->ImageSize = cpu_to_le32(sz);
3616        ptcsge++;
3617
3618        flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
3619        ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma);
3620        request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) +
3621            ioc->SGE_size;
3622        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload "
3623            " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest,
3624            ioc->facts.FWImageSize, request_size));
3625        DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest);
3626
3627        ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest,
3628            reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag);
3629
3630        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed "
3631            "rc=%x \n", ioc->name, ii));
3632
3633        cmdStatus = -EFAULT;
3634        if (ii == 0) {
3635                /* Handshake transfer was complete and successful.
3636                 * Check the Reply Frame.
3637                 */
3638                int status;
3639                status = le16_to_cpu(preply->IOCStatus) &
3640                                MPI_IOCSTATUS_MASK;
3641                if (status == MPI_IOCSTATUS_SUCCESS &&
3642                    ioc->facts.FWImageSize ==
3643                    le32_to_cpu(preply->ActualImageSize))
3644                                cmdStatus = 0;
3645        }
3646        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n",
3647                        ioc->name, cmdStatus));
3648
3649
3650        if (cmdStatus) {
3651                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, "
3652                    "freeing image \n", ioc->name));
3653                mpt_free_fw_memory(ioc);
3654        }
3655        kfree(prequest);
3656
3657        return cmdStatus;
3658}
3659
3660/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3661/**
3662 *      mpt_downloadboot - DownloadBoot code
3663 *      @ioc: Pointer to MPT_ADAPTER structure
3664 *      @pFwHeader: Pointer to firmware header info
3665 *      @sleepFlag: Specifies whether the process can sleep
3666 *
3667 *      FwDownloadBoot requires Programmed IO access.
3668 *
3669 *      Returns 0 for success
3670 *              -1 FW Image size is 0
3671 *              -2 No valid cached_fw Pointer
3672 *              <0 for fw upload failure.
3673 */
3674static int
3675mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
3676{
3677        MpiExtImageHeader_t     *pExtImage;
3678        u32                      fwSize;
3679        u32                      diag0val;
3680        int                      count;
3681        u32                     *ptrFw;
3682        u32                      diagRwData;
3683        u32                      nextImage;
3684        u32                      load_addr;
3685        u32                      ioc_state=0;
3686
3687        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
3688                                ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
3689
3690        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3691        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3692        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3693        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3694        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3695        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3696
3697        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
3698
3699        /* wait 1 msec */
3700        if (sleepFlag == CAN_SLEEP) {
3701                msleep(1);
3702        } else {
3703                mdelay (1);
3704        }
3705
3706        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3707        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
3708
3709        for (count = 0; count < 30; count ++) {
3710                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3711                if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
3712                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n",
3713                                ioc->name, count));
3714                        break;
3715                }
3716                /* wait .1 sec */
3717                if (sleepFlag == CAN_SLEEP) {
3718                        msleep (100);
3719                } else {
3720                        mdelay (100);
3721                }
3722        }
3723
3724        if ( count == 30 ) {
3725                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! "
3726                "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n",
3727                ioc->name, diag0val));
3728                return -3;
3729        }
3730
3731        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3732        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
3733        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
3734        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
3735        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
3736        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
3737
3738        /* Set the DiagRwEn and Disable ARM bits */
3739        CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
3740
3741        fwSize = (pFwHeader->ImageSize + 3)/4;
3742        ptrFw = (u32 *) pFwHeader;
3743
3744        /* Write the LoadStartAddress to the DiagRw Address Register
3745         * using Programmed IO
3746         */
3747        if (ioc->errata_flag_1064)
3748                pci_enable_io_access(ioc->pcidev);
3749
3750        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
3751        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n",
3752                ioc->name, pFwHeader->LoadStartAddress));
3753
3754        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n",
3755                                ioc->name, fwSize*4, ptrFw));
3756        while (fwSize--) {
3757                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3758        }
3759
3760        nextImage = pFwHeader->NextImageHeaderOffset;
3761        while (nextImage) {
3762                pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
3763
3764                load_addr = pExtImage->LoadStartAddress;
3765
3766                fwSize = (pExtImage->ImageSize + 3) >> 2;
3767                ptrFw = (u32 *)pExtImage;
3768
3769                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n",
3770                                                ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr));
3771                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
3772
3773                while (fwSize--) {
3774                        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
3775                }
3776                nextImage = pExtImage->NextImageHeaderOffset;
3777        }
3778
3779        /* Write the IopResetVectorRegAddr */
3780        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name,  pFwHeader->IopResetRegAddr));
3781        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
3782
3783        /* Write the IopResetVectorValue */
3784        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
3785        CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
3786
3787        /* Clear the internal flash bad bit - autoincrementing register,
3788         * so must do two writes.
3789         */
3790        if (ioc->bus_type == SPI) {
3791                /*
3792                 * 1030 and 1035 H/W errata, workaround to access
3793                 * the ClearFlashBadSignatureBit
3794                 */
3795                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3796                diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData);
3797                diagRwData |= 0x40000000;
3798                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
3799                CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
3800
3801        } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
3802                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3803                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
3804                    MPI_DIAG_CLEAR_FLASH_BAD_SIG);
3805
3806                /* wait 1 msec */
3807                if (sleepFlag == CAN_SLEEP) {
3808                        msleep (1);
3809                } else {
3810                        mdelay (1);
3811                }
3812        }
3813
3814        if (ioc->errata_flag_1064)
3815                pci_disable_io_access(ioc->pcidev);
3816
3817        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
3818        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, "
3819                "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
3820                ioc->name, diag0val));
3821        diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
3822        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n",
3823                ioc->name, diag0val));
3824        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
3825
3826        /* Write 0xFF to reset the sequencer */
3827        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
3828
3829        if (ioc->bus_type == SAS) {
3830                ioc_state = mpt_GetIocState(ioc, 0);
3831                if ( (GetIocFacts(ioc, sleepFlag,
3832                                MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) {
3833                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n",
3834                                        ioc->name, ioc_state));
3835                        return -EFAULT;
3836                }
3837        }
3838
3839        for (count=0; count<HZ*20; count++) {
3840                if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
3841                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3842                                "downloadboot successful! (count=%d) IocState=%x\n",
3843                                ioc->name, count, ioc_state));
3844                        if (ioc->bus_type == SAS) {
3845                                return 0;
3846                        }
3847                        if ((SendIocInit(ioc, sleepFlag)) != 0) {
3848                                ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3849                                        "downloadboot: SendIocInit failed\n",
3850                                        ioc->name));
3851                                return -EFAULT;
3852                        }
3853                        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3854                                        "downloadboot: SendIocInit successful\n",
3855                                        ioc->name));
3856                        return 0;
3857                }
3858                if (sleepFlag == CAN_SLEEP) {
3859                        msleep (10);
3860                } else {
3861                        mdelay (10);
3862                }
3863        }
3864        ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3865                "downloadboot failed! IocState=%x\n",ioc->name, ioc_state));
3866        return -EFAULT;
3867}
3868
3869/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3870/**
3871 *      KickStart - Perform hard reset of MPT adapter.
3872 *      @ioc: Pointer to MPT_ADAPTER structure
3873 *      @force: Force hard reset
3874 *      @sleepFlag: Specifies whether the process can sleep
3875 *
3876 *      This routine places MPT adapter in diagnostic mode via the
3877 *      WriteSequence register, and then performs a hard reset of adapter
3878 *      via the Diagnostic register.
3879 *
3880 *      Inputs:   sleepflag - CAN_SLEEP (non-interrupt thread)
3881 *                      or NO_SLEEP (interrupt thread, use mdelay)
3882 *                force - 1 if doorbell active, board fault state
3883 *                              board operational, IOC_RECOVERY or
3884 *                              IOC_BRINGUP and there is an alt_ioc.
3885 *                        0 else
3886 *
3887 *      Returns:
3888 *               1 - hard reset, READY
3889 *               0 - no reset due to History bit, READY
3890 *              -1 - no reset due to History bit but not READY
3891 *                   OR reset but failed to come READY
3892 *              -2 - no reset, could not enter DIAG mode
3893 *              -3 - reset but bad FW bit
3894 */
3895static int
3896KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
3897{
3898        int hard_reset_done = 0;
3899        u32 ioc_state=0;
3900        int cnt,cntdn;
3901
3902        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name));
3903        if (ioc->bus_type == SPI) {
3904                /* Always issue a Msg Unit Reset first. This will clear some
3905                 * SCSI bus hang conditions.
3906                 */
3907                SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
3908
3909                if (sleepFlag == CAN_SLEEP) {
3910                        msleep (1000);
3911                } else {
3912                        mdelay (1000);
3913                }
3914        }
3915
3916        hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag);
3917        if (hard_reset_done < 0)
3918                return hard_reset_done;
3919
3920        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n",
3921                ioc->name));
3922
3923        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;     /* 2 seconds */
3924        for (cnt=0; cnt<cntdn; cnt++) {
3925                ioc_state = mpt_GetIocState(ioc, 1);
3926                if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
3927                        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n",
3928                                        ioc->name, cnt));
3929                        return hard_reset_done;
3930                }
3931                if (sleepFlag == CAN_SLEEP) {
3932                        msleep (10);
3933                } else {
3934                        mdelay (10);
3935                }
3936        }
3937
3938        dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
3939                ioc->name, mpt_GetIocState(ioc, 0)));
3940        return -1;
3941}
3942
3943/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3944/**
3945 *      mpt_diag_reset - Perform hard reset of the adapter.
3946 *      @ioc: Pointer to MPT_ADAPTER structure
3947 *      @ignore: Set if to honor and clear to ignore
3948 *              the reset history bit
3949 *      @sleepFlag: CAN_SLEEP if called in a non-interrupt thread,
3950 *              else set to NO_SLEEP (use mdelay instead)
3951 *
3952 *      This routine places the adapter in diagnostic mode via the
3953 *      WriteSequence register and then performs a hard reset of adapter
3954 *      via the Diagnostic register. Adapter should be in ready state
3955 *      upon successful completion.
3956 *
3957 *      Returns:  1  hard reset successful
3958 *                0  no reset performed because reset history bit set
3959 *               -2  enabling diagnostic mode failed
3960 *               -3  diagnostic reset failed
3961 */
3962static int
3963mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
3964{
3965        u32 diag0val;
3966        u32 doorbell;
3967        int hard_reset_done = 0;
3968        int count = 0;
3969        u32 diag1val = 0;
3970        MpiFwHeader_t *cached_fw;       /* Pointer to FW */
3971        u8       cb_idx;
3972
3973        /* Clear any existing interrupts */
3974        CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
3975
3976        if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
3977
3978                if (!ignore)
3979                        return 0;
3980
3981                drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
3982                        "address=%p\n",  ioc->name, __func__,
3983                        &ioc->chip->Doorbell, &ioc->chip->Reset_1078));
3984                CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07);
3985                if (sleepFlag == CAN_SLEEP)
3986                        msleep(1);
3987                else
3988                        mdelay(1);
3989
3990                /*
3991                 * Call each currently registered protocol IOC reset handler
3992                 * with pre-reset indication.
3993                 * NOTE: If we're doing _IOC_BRINGUP, there can be no
3994                 * MptResetHandlers[] registered yet.
3995                 */
3996                for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
3997                        if (MptResetHandlers[cb_idx])
3998                                (*(MptResetHandlers[cb_idx]))(ioc,
3999                                                MPT_IOC_PRE_RESET);
4000                }
4001
4002                for (count = 0; count < 60; count ++) {
4003                        doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
4004                        doorbell &= MPI_IOC_STATE_MASK;
4005
4006                        drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4007                                "looking for READY STATE: doorbell=%x"
4008                                " count=%d\n",
4009                                ioc->name, doorbell, count));
4010
4011                        if (doorbell == MPI_IOC_STATE_READY) {
4012                                return 1;
4013                        }
4014
4015                        /* wait 1 sec */
4016                        if (sleepFlag == CAN_SLEEP)
4017                                msleep(1000);
4018                        else
4019                                mdelay(1000);
4020                }
4021                return -1;
4022        }
4023
4024        /* Use "Diagnostic reset" method! (only thing available!) */
4025        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4026
4027        if (ioc->debug_level & MPT_DEBUG) {
4028                if (ioc->alt_ioc)
4029                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4030                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n",
4031                        ioc->name, diag0val, diag1val));
4032        }
4033
4034        /* Do the reset if we are told to ignore the reset history
4035         * or if the reset history is 0
4036         */
4037        if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) {
4038                while ((diag0val & MPI_DIAG_DRWE) == 0) {
4039                        /* Write magic sequence to WriteSequence register
4040                         * Loop until in diagnostic mode
4041                         */
4042                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4043                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4044                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4045                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4046                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4047                        CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4048
4049                        /* wait 100 msec */
4050                        if (sleepFlag == CAN_SLEEP) {
4051                                msleep (100);
4052                        } else {
4053                                mdelay (100);
4054                        }
4055
4056                        count++;
4057                        if (count > 20) {
4058                                printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4059                                                ioc->name, diag0val);
4060                                return -2;
4061
4062                        }
4063
4064                        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4065
4066                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
4067                                        ioc->name, diag0val));
4068                }
4069
4070                if (ioc->debug_level & MPT_DEBUG) {
4071                        if (ioc->alt_ioc)
4072                                diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4073                        dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n",
4074                                ioc->name, diag0val, diag1val));
4075                }
4076                /*
4077                 * Disable the ARM (Bug fix)
4078                 *
4079                 */
4080                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
4081                mdelay(1);
4082
4083                /*
4084                 * Now hit the reset bit in the Diagnostic register
4085                 * (THE BIG HAMMER!) (Clears DRWE bit).
4086                 */
4087                CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
4088                hard_reset_done = 1;
4089                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n",
4090                                ioc->name));
4091
4092                /*
4093                 * Call each currently registered protocol IOC reset handler
4094                 * with pre-reset indication.
4095                 * NOTE: If we're doing _IOC_BRINGUP, there can be no
4096                 * MptResetHandlers[] registered yet.
4097                 */
4098                for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
4099                        if (MptResetHandlers[cb_idx]) {
4100                                mpt_signal_reset(cb_idx,
4101                                        ioc, MPT_IOC_PRE_RESET);
4102                                if (ioc->alt_ioc) {
4103                                        mpt_signal_reset(cb_idx,
4104                                        ioc->alt_ioc, MPT_IOC_PRE_RESET);
4105                                }
4106                        }
4107                }
4108
4109                if (ioc->cached_fw)
4110                        cached_fw = (MpiFwHeader_t *)ioc->cached_fw;
4111                else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
4112                        cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw;
4113                else
4114                        cached_fw = NULL;
4115                if (cached_fw) {
4116                        /* If the DownloadBoot operation fails, the
4117                         * IOC will be left unusable. This is a fatal error
4118                         * case.  _diag_reset will return < 0
4119                         */
4120                        for (count = 0; count < 30; count ++) {
4121                                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4122                                if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
4123                                        break;
4124                                }
4125
4126                                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n",
4127                                        ioc->name, diag0val, count));
4128                                /* wait 1 sec */
4129                                if (sleepFlag == CAN_SLEEP) {
4130                                        msleep (1000);
4131                                } else {
4132                                        mdelay (1000);
4133                                }
4134                        }
4135                        if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) {
4136                                printk(MYIOC_s_WARN_FMT
4137                                        "firmware downloadboot failure (%d)!\n", ioc->name, count);
4138                        }
4139
4140                } else {
4141                        /* Wait for FW to reload and for board
4142                         * to go to the READY state.
4143                         * Maximum wait is 60 seconds.
4144                         * If fail, no error will check again
4145                         * with calling program.
4146                         */
4147                        for (count = 0; count < 60; count ++) {
4148                                doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
4149                                doorbell &= MPI_IOC_STATE_MASK;
4150
4151                                drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4152                                    "looking for READY STATE: doorbell=%x"
4153                                    " count=%d\n", ioc->name, doorbell, count));
4154
4155                                if (doorbell == MPI_IOC_STATE_READY) {
4156                                        break;
4157                                }
4158
4159                                /* wait 1 sec */
4160                                if (sleepFlag == CAN_SLEEP) {
4161                                        msleep (1000);
4162                                } else {
4163                                        mdelay (1000);
4164                                }
4165                        }
4166
4167                        if (doorbell != MPI_IOC_STATE_READY)
4168                                printk(MYIOC_s_ERR_FMT "Failed to come READY "
4169                                    "after reset! IocState=%x", ioc->name,
4170                                    doorbell);
4171                }
4172        }
4173
4174        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4175        if (ioc->debug_level & MPT_DEBUG) {
4176                if (ioc->alt_ioc)
4177                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4178                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n",
4179                        ioc->name, diag0val, diag1val));
4180        }
4181
4182        /* Clear RESET_HISTORY bit!  Place board in the
4183         * diagnostic mode to update the diag register.
4184         */
4185        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4186        count = 0;
4187        while ((diag0val & MPI_DIAG_DRWE) == 0) {
4188                /* Write magic sequence to WriteSequence register
4189                 * Loop until in diagnostic mode
4190                 */
4191                CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
4192                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
4193                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
4194                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
4195                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
4196                CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
4197
4198                /* wait 100 msec */
4199                if (sleepFlag == CAN_SLEEP) {
4200                        msleep (100);
4201                } else {
4202                        mdelay (100);
4203                }
4204
4205                count++;
4206                if (count > 20) {
4207                        printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
4208                                        ioc->name, diag0val);
4209                        break;
4210                }
4211                diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4212        }
4213        diag0val &= ~MPI_DIAG_RESET_HISTORY;
4214        CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
4215        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4216        if (diag0val & MPI_DIAG_RESET_HISTORY) {
4217                printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
4218                                ioc->name);
4219        }
4220
4221        /* Disable Diagnostic Mode
4222         */
4223        CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
4224
4225        /* Check FW reload status flags.
4226         */
4227        diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
4228        if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
4229                printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
4230                                ioc->name, diag0val);
4231                return -3;
4232        }
4233
4234        if (ioc->debug_level & MPT_DEBUG) {
4235                if (ioc->alt_ioc)
4236                        diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
4237                dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n",
4238                        ioc->name, diag0val, diag1val));
4239        }
4240
4241        /*
4242         * Reset flag that says we've enabled event notification
4243         */
4244        ioc->facts.EventState = 0;
4245
4246        if (ioc->alt_ioc)
4247                ioc->alt_ioc->facts.EventState = 0;
4248
4249        return hard_reset_done;
4250}
4251
4252/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4253/**
4254 *      SendIocReset - Send IOCReset request to MPT adapter.
4255 *      @ioc: Pointer to MPT_ADAPTER structure
4256 *      @reset_type: reset type, expected values are
4257 *      %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET
4258 *      @sleepFlag: Specifies whether the process can sleep
4259 *
4260 *      Send IOCReset request to the MPT adapter.
4261 *
4262 *      Returns 0 for success, non-zero for failure.
4263 */
4264static int
4265SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
4266{
4267        int r;
4268        u32 state;
4269        int cntdn, count;
4270
4271        drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n",
4272                        ioc->name, reset_type));
4273        CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
4274        if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
4275                return r;
4276
4277        /* FW ACK'd request, wait for READY state
4278         */
4279        count = 0;
4280        cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15;    /* 15 seconds */
4281
4282        while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) {
4283                cntdn--;
4284                count++;
4285                if (!cntdn) {
4286                        if (sleepFlag != CAN_SLEEP)
4287                                count *= 10;
4288
4289                        printk(MYIOC_s_ERR_FMT
4290                            "Wait IOC_READY state (0x%x) timeout(%d)!\n",
4291                            ioc->name, state, (int)((count+5)/HZ));
4292                        return -ETIME;
4293                }
4294
4295                if (sleepFlag == CAN_SLEEP) {
4296                        msleep(1);
4297                } else {
4298                        mdelay (1);     /* 1 msec delay */
4299                }
4300        }
4301
4302        /* TODO!
4303         *  Cleanup all event stuff for this IOC; re-issue EventNotification
4304         *  request if needed.
4305         */
4306        if (ioc->facts.Function)
4307                ioc->facts.EventState = 0;
4308
4309        return 0;
4310}
4311
4312/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4313/**
4314 *      initChainBuffers - Allocate memory for and initialize chain buffers
4315 *      @ioc: Pointer to MPT_ADAPTER structure
4316 *
4317 *      Allocates memory for and initializes chain buffers,
4318 *      chain buffer control arrays and spinlock.
4319 */
4320static int
4321initChainBuffers(MPT_ADAPTER *ioc)
4322{
4323        u8              *mem;
4324        int             sz, ii, num_chain;
4325        int             scale, num_sge, numSGE;
4326
4327        /* ReqToChain size must equal the req_depth
4328         * index = req_idx
4329         */
4330        if (ioc->ReqToChain == NULL) {
4331                sz = ioc->req_depth * sizeof(int);
4332                mem = kmalloc(sz, GFP_ATOMIC);
4333                if (mem == NULL)
4334                        return -1;
4335
4336                ioc->ReqToChain = (int *) mem;
4337                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc  @ %p, sz=%d bytes\n",
4338                                ioc->name, mem, sz));
4339                mem = kmalloc(sz, GFP_ATOMIC);
4340                if (mem == NULL)
4341                        return -1;
4342
4343                ioc->RequestNB = (int *) mem;
4344                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc  @ %p, sz=%d bytes\n",
4345                                ioc->name, mem, sz));
4346        }
4347        for (ii = 0; ii < ioc->req_depth; ii++) {
4348                ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
4349        }
4350
4351        /* ChainToChain size must equal the total number
4352         * of chain buffers to be allocated.
4353         * index = chain_idx
4354         *
4355         * Calculate the number of chain buffers needed(plus 1) per I/O
4356         * then multiply the maximum number of simultaneous cmds
4357         *
4358         * num_sge = num sge in request frame + last chain buffer
4359         * scale = num sge per chain buffer if no chain element
4360         */
4361        scale = ioc->req_sz / ioc->SGE_size;
4362        if (ioc->sg_addr_size == sizeof(u64))
4363                num_sge =  scale + (ioc->req_sz - 60) / ioc->SGE_size;
4364        else
4365                num_sge =  1 + scale + (ioc->req_sz - 64) / ioc->SGE_size;
4366
4367        if (ioc->sg_addr_size == sizeof(u64)) {
4368                numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
4369                        (ioc->req_sz - 60) / ioc->SGE_size;
4370        } else {
4371                numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) +
4372                    scale + (ioc->req_sz - 64) / ioc->SGE_size;
4373        }
4374        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n",
4375                ioc->name, num_sge, numSGE));
4376
4377        if (ioc->bus_type == FC) {
4378                if (numSGE > MPT_SCSI_FC_SG_DEPTH)
4379                        numSGE = MPT_SCSI_FC_SG_DEPTH;
4380        } else {
4381                if (numSGE > MPT_SCSI_SG_DEPTH)
4382                        numSGE = MPT_SCSI_SG_DEPTH;
4383        }
4384
4385        num_chain = 1;
4386        while (numSGE - num_sge > 0) {
4387                num_chain++;
4388                num_sge += (scale - 1);
4389        }
4390        num_chain++;
4391
4392        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n",
4393                ioc->name, numSGE, num_sge, num_chain));
4394
4395        if (ioc->bus_type == SPI)
4396                num_chain *= MPT_SCSI_CAN_QUEUE;
4397        else if (ioc->bus_type == SAS)
4398                num_chain *= MPT_SAS_CAN_QUEUE;
4399        else
4400                num_chain *= MPT_FC_CAN_QUEUE;
4401
4402        ioc->num_chain = num_chain;
4403
4404        sz = num_chain * sizeof(int);
4405        if (ioc->ChainToChain == NULL) {
4406                mem = kmalloc(sz, GFP_ATOMIC);
4407                if (mem == NULL)
4408                        return -1;
4409
4410                ioc->ChainToChain = (int *) mem;
4411                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n",
4412                                ioc->name, mem, sz));
4413        } else {
4414                mem = (u8 *) ioc->ChainToChain;
4415        }
4416        memset(mem, 0xFF, sz);
4417        return num_chain;
4418}
4419
4420/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4421/**
4422 *      PrimeIocFifos - Initialize IOC request and reply FIFOs.
4423 *      @ioc: Pointer to MPT_ADAPTER structure
4424 *
4425 *      This routine allocates memory for the MPT reply and request frame
4426 *      pools (if necessary), and primes the IOC reply FIFO with
4427 *      reply frames.
4428 *
4429 *      Returns 0 for success, non-zero for failure.
4430 */
4431static int
4432PrimeIocFifos(MPT_ADAPTER *ioc)
4433{
4434        MPT_FRAME_HDR *mf;
4435        unsigned long flags;
4436        dma_addr_t alloc_dma;
4437        u8 *mem;
4438        int i, reply_sz, sz, total_size, num_chain;
4439        u64     dma_mask;
4440
4441        dma_mask = 0;
4442
4443        /*  Prime reply FIFO...  */
4444
4445        if (ioc->reply_frames == NULL) {
4446                if ( (num_chain = initChainBuffers(ioc)) < 0)
4447                        return -1;
4448                /*
4449                 * 1078 errata workaround for the 36GB limitation
4450                 */
4451                if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 &&
4452                    ioc->dma_mask > DMA_BIT_MASK(35)) {
4453                        if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32))
4454                            && !pci_set_consistent_dma_mask(ioc->pcidev,
4455                            DMA_BIT_MASK(32))) {
4456                                dma_mask = DMA_BIT_MASK(35);
4457                                d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4458                                    "setting 35 bit addressing for "
4459                                    "Request/Reply/Chain and Sense Buffers\n",
4460                                    ioc->name));
4461                        } else {
4462                                /*Reseting DMA mask to 64 bit*/
4463                                pci_set_dma_mask(ioc->pcidev,
4464                                        DMA_BIT_MASK(64));
4465                                pci_set_consistent_dma_mask(ioc->pcidev,
4466                                        DMA_BIT_MASK(64));
4467
4468                                printk(MYIOC_s_ERR_FMT
4469                                    "failed setting 35 bit addressing for "
4470                                    "Request/Reply/Chain and Sense Buffers\n",
4471                                    ioc->name);
4472                                return -1;
4473                        }
4474                }
4475
4476                total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
4477                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
4478                                ioc->name, ioc->reply_sz, ioc->reply_depth));
4479                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n",
4480                                ioc->name, reply_sz, reply_sz));
4481
4482                sz = (ioc->req_sz * ioc->req_depth);
4483                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n",
4484                                ioc->name, ioc->req_sz, ioc->req_depth));
4485                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n",
4486                                ioc->name, sz, sz));
4487                total_size += sz;
4488
4489                sz = num_chain * ioc->req_sz; /* chain buffer pool size */
4490                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n",
4491                                ioc->name, ioc->req_sz, num_chain));
4492                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
4493                                ioc->name, sz, sz, num_chain));
4494
4495                total_size += sz;
4496                mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
4497                if (mem == NULL) {
4498                        printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
4499                                ioc->name);
4500                        goto out_fail;
4501                }
4502
4503                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n",
4504                                ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
4505
4506                memset(mem, 0, total_size);
4507                ioc->alloc_total += total_size;
4508                ioc->alloc = mem;
4509                ioc->alloc_dma = alloc_dma;
4510                ioc->alloc_sz = total_size;
4511                ioc->reply_frames = (MPT_FRAME_HDR *) mem;
4512                ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4513
4514                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4515                        ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4516
4517                alloc_dma += reply_sz;
4518                mem += reply_sz;
4519
4520                /*  Request FIFO - WE manage this!  */
4521
4522                ioc->req_frames = (MPT_FRAME_HDR *) mem;
4523                ioc->req_frames_dma = alloc_dma;
4524
4525                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n",
4526                                ioc->name, mem, (void *)(ulong)alloc_dma));
4527
4528                ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
4529
4530                for (i = 0; i < ioc->req_depth; i++) {
4531                        alloc_dma += ioc->req_sz;
4532                        mem += ioc->req_sz;
4533                }
4534
4535                ioc->ChainBuffer = mem;
4536                ioc->ChainBufferDMA = alloc_dma;
4537
4538                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n",
4539                        ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
4540
4541                /* Initialize the free chain Q.
4542                */
4543
4544                INIT_LIST_HEAD(&ioc->FreeChainQ);
4545
4546                /* Post the chain buffers to the FreeChainQ.
4547                */
4548                mem = (u8 *)ioc->ChainBuffer;
4549                for (i=0; i < num_chain; i++) {
4550                        mf = (MPT_FRAME_HDR *) mem;
4551                        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ);
4552                        mem += ioc->req_sz;
4553                }
4554
4555                /* Initialize Request frames linked list
4556                 */
4557                alloc_dma = ioc->req_frames_dma;
4558                mem = (u8 *) ioc->req_frames;
4559
4560                spin_lock_irqsave(&ioc->FreeQlock, flags);
4561                INIT_LIST_HEAD(&ioc->FreeQ);
4562                for (i = 0; i < ioc->req_depth; i++) {
4563                        mf = (MPT_FRAME_HDR *) mem;
4564
4565                        /*  Queue REQUESTs *internally*!  */
4566                        list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
4567
4568                        mem += ioc->req_sz;
4569                }
4570                spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4571
4572                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4573                ioc->sense_buf_pool =
4574                        pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
4575                if (ioc->sense_buf_pool == NULL) {
4576                        printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
4577                                ioc->name);
4578                        goto out_fail;
4579                }
4580
4581                ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
4582                ioc->alloc_total += sz;
4583                dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n",
4584                        ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
4585
4586        }
4587
4588        /* Post Reply frames to FIFO
4589         */
4590        alloc_dma = ioc->alloc_dma;
4591        dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n",
4592                ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
4593
4594        for (i = 0; i < ioc->reply_depth; i++) {
4595                /*  Write each address to the IOC!  */
4596                CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
4597                alloc_dma += ioc->reply_sz;
4598        }
4599
4600        if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev,
4601            ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev,
4602            ioc->dma_mask))
4603                d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4604                    "restoring 64 bit addressing\n", ioc->name));
4605
4606        return 0;
4607
4608out_fail:
4609
4610        if (ioc->alloc != NULL) {
4611                sz = ioc->alloc_sz;
4612                pci_free_consistent(ioc->pcidev,
4613                                sz,
4614                                ioc->alloc, ioc->alloc_dma);
4615                ioc->reply_frames = NULL;
4616                ioc->req_frames = NULL;
4617                ioc->alloc_total -= sz;
4618        }
4619        if (ioc->sense_buf_pool != NULL) {
4620                sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
4621                pci_free_consistent(ioc->pcidev,
4622                                sz,
4623                                ioc->sense_buf_pool, 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("summary", S_IRUGO, mpt_proc_root_dir, &mpt_summary_proc_fops);
6611        proc_create("version", S_IRUGO, mpt_proc_root_dir, &mpt_version_proc_fops);
6612        return 0;
6613}
6614
6615/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6616/**
6617 *      procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries.
6618 *
6619 *      Returns 0 for success, non-zero for failure.
6620 */
6621static void
6622procmpt_destroy(void)
6623{
6624        remove_proc_entry("version", mpt_proc_root_dir);
6625        remove_proc_entry("summary", mpt_proc_root_dir);
6626        remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL);
6627}
6628
6629/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6630/*
6631 *      Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary.
6632 */
6633static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan);
6634
6635static int mpt_summary_proc_show(struct seq_file *m, void *v)
6636{
6637        MPT_ADAPTER *ioc = m->private;
6638
6639        if (ioc) {
6640                seq_mpt_print_ioc_summary(ioc, m, 1);
6641        } else {
6642                list_for_each_entry(ioc, &ioc_list, list) {
6643                        seq_mpt_print_ioc_summary(ioc, m, 1);
6644                }
6645        }
6646
6647        return 0;
6648}
6649
6650static int mpt_summary_proc_open(struct inode *inode, struct file *file)
6651{
6652        return single_open(file, mpt_summary_proc_show, PDE_DATA(inode));
6653}
6654
6655static const struct file_operations mpt_summary_proc_fops = {
6656        .owner          = THIS_MODULE,
6657        .open           = mpt_summary_proc_open,
6658        .read           = seq_read,
6659        .llseek         = seq_lseek,
6660        .release        = single_release,
6661};
6662
6663static int mpt_version_proc_show(struct seq_file *m, void *v)
6664{
6665        u8       cb_idx;
6666        int      scsi, fc, sas, lan, ctl, targ, dmp;
6667        char    *drvname;
6668
6669        seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
6670        seq_printf(m, "  Fusion MPT base driver\n");
6671
6672        scsi = fc = sas = lan = ctl = targ = dmp = 0;
6673        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
6674                drvname = NULL;
6675                if (MptCallbacks[cb_idx]) {
6676                        switch (MptDriverClass[cb_idx]) {
6677                        case MPTSPI_DRIVER:
6678                                if (!scsi++) drvname = "SPI host";
6679                                break;
6680                        case MPTFC_DRIVER:
6681                                if (!fc++) drvname = "FC host";
6682                                break;
6683                        case MPTSAS_DRIVER:
6684                                if (!sas++) drvname = "SAS host";
6685                                break;
6686                        case MPTLAN_DRIVER:
6687                                if (!lan++) drvname = "LAN";
6688                                break;
6689                        case MPTSTM_DRIVER:
6690                                if (!targ++) drvname = "SCSI target";
6691                                break;
6692                        case MPTCTL_DRIVER:
6693                                if (!ctl++) drvname = "ioctl";
6694                                break;
6695                        }
6696
6697                        if (drvname)
6698                                seq_printf(m, "  Fusion MPT %s driver\n", drvname);
6699                }
6700        }
6701
6702        return 0;
6703}
6704
6705static int mpt_version_proc_open(struct inode *inode, struct file *file)
6706{
6707        return single_open(file, mpt_version_proc_show, NULL);
6708}
6709
6710static const struct file_operations mpt_version_proc_fops = {
6711        .owner          = THIS_MODULE,
6712        .open           = mpt_version_proc_open,
6713        .read           = seq_read,
6714        .llseek         = seq_lseek,
6715        .release        = single_release,
6716};
6717
6718static int mpt_iocinfo_proc_show(struct seq_file *m, void *v)
6719{
6720        MPT_ADAPTER     *ioc = m->private;
6721        char             expVer[32];
6722        int              sz;
6723        int              p;
6724
6725        mpt_get_fw_exp_ver(expVer, ioc);
6726
6727        seq_printf(m, "%s:", ioc->name);
6728        if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
6729                seq_printf(m, "  (f/w download boot flag set)");
6730//      if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL)
6731//              seq_printf(m, "  CONFIG_CHECKSUM_FAIL!");
6732
6733        seq_printf(m, "\n  ProductID = 0x%04x (%s)\n",
6734                        ioc->facts.ProductID,
6735                        ioc->prod_name);
6736        seq_printf(m, "  FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer);
6737        if (ioc->facts.FWImageSize)
6738                seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize);
6739        seq_printf(m, "\n  MsgVersion = 0x%04x\n", ioc->facts.MsgVersion);
6740        seq_printf(m, "  FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit);
6741        seq_printf(m, "  EventState = 0x%02x\n", ioc->facts.EventState);
6742
6743        seq_printf(m, "  CurrentHostMfaHighAddr = 0x%08x\n",
6744                        ioc->facts.CurrentHostMfaHighAddr);
6745        seq_printf(m, "  CurrentSenseBufferHighAddr = 0x%08x\n",
6746                        ioc->facts.CurrentSenseBufferHighAddr);
6747
6748        seq_printf(m, "  MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth);
6749        seq_printf(m, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
6750
6751        seq_printf(m, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
6752                                        (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
6753        /*
6754         *  Rounding UP to nearest 4-kB boundary here...
6755         */
6756        sz = (ioc->req_sz * ioc->req_depth) + 128;
6757        sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
6758        seq_printf(m, "    {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n",
6759                                        ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz);
6760        seq_printf(m, "    {MaxReqSz=%d}   {MaxReqDepth=%d}\n",
6761                                        4*ioc->facts.RequestFrameSize,
6762                                        ioc->facts.GlobalCredits);
6763
6764        seq_printf(m, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
6765                                        (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
6766        sz = (ioc->reply_sz * ioc->reply_depth) + 128;
6767        seq_printf(m, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
6768                                        ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
6769        seq_printf(m, "    {MaxRepSz=%d}   {MaxRepDepth=%d}\n",
6770                                        ioc->facts.CurReplyFrameSize,
6771                                        ioc->facts.ReplyQueueDepth);
6772
6773        seq_printf(m, "  MaxDevices = %d\n",
6774                        (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices);
6775        seq_printf(m, "  MaxBuses = %d\n", ioc->facts.MaxBuses);
6776
6777        /* per-port info */
6778        for (p=0; p < ioc->facts.NumberOfPorts; p++) {
6779                seq_printf(m, "  PortNumber = %d (of %d)\n",
6780                                p+1,
6781                                ioc->facts.NumberOfPorts);
6782                if (ioc->bus_type == FC) {
6783                        if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
6784                                u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6785                                seq_printf(m, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
6786                                                a[5], a[4], a[3], a[2], a[1], a[0]);
6787                        }
6788                        seq_printf(m, "    WWN = %08X%08X:%08X%08X\n",
6789                                        ioc->fc_port_page0[p].WWNN.High,
6790                                        ioc->fc_port_page0[p].WWNN.Low,
6791                                        ioc->fc_port_page0[p].WWPN.High,
6792                                        ioc->fc_port_page0[p].WWPN.Low);
6793                }
6794        }
6795
6796        return 0;
6797}
6798
6799static int mpt_iocinfo_proc_open(struct inode *inode, struct file *file)
6800{
6801        return single_open(file, mpt_iocinfo_proc_show, PDE_DATA(inode));
6802}
6803
6804static const struct file_operations mpt_iocinfo_proc_fops = {
6805        .owner          = THIS_MODULE,
6806        .open           = mpt_iocinfo_proc_open,
6807        .read           = seq_read,
6808        .llseek         = seq_lseek,
6809        .release        = single_release,
6810};
6811#endif          /* CONFIG_PROC_FS } */
6812
6813/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6814static void
6815mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc)
6816{
6817        buf[0] ='\0';
6818        if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) {
6819                sprintf(buf, " (Exp %02d%02d)",
6820                        (ioc->facts.FWVersion.Word >> 16) & 0x00FF,     /* Month */
6821                        (ioc->facts.FWVersion.Word >> 8) & 0x1F);       /* Day */
6822
6823                /* insider hack! */
6824                if ((ioc->facts.FWVersion.Word >> 8) & 0x80)
6825                        strcat(buf, " [MDBG]");
6826        }
6827}
6828
6829/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6830/**
6831 *      mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer.
6832 *      @ioc: Pointer to MPT_ADAPTER structure
6833 *      @buffer: Pointer to buffer where IOC summary info should be written
6834 *      @size: Pointer to number of bytes we wrote (set by this routine)
6835 *      @len: Offset at which to start writing in buffer
6836 *      @showlan: Display LAN stuff?
6837 *
6838 *      This routine writes (english readable) ASCII text, which represents
6839 *      a summary of IOC information, to a buffer.
6840 */
6841void
6842mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan)
6843{
6844        char expVer[32];
6845        int y;
6846
6847        mpt_get_fw_exp_ver(expVer, ioc);
6848
6849        /*
6850         *  Shorter summary of attached ioc's...
6851         */
6852        y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6853                        ioc->name,
6854                        ioc->prod_name,
6855                        MPT_FW_REV_MAGIC_ID_STRING,     /* "FwRev=" or somesuch */
6856                        ioc->facts.FWVersion.Word,
6857                        expVer,
6858                        ioc->facts.NumberOfPorts,
6859                        ioc->req_depth);
6860
6861        if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6862                u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6863                y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6864                        a[5], a[4], a[3], a[2], a[1], a[0]);
6865        }
6866
6867        y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
6868
6869        if (!ioc->active)
6870                y += sprintf(buffer+len+y, " (disabled)");
6871
6872        y += sprintf(buffer+len+y, "\n");
6873
6874        *size = y;
6875}
6876
6877#ifdef CONFIG_PROC_FS
6878static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan)
6879{
6880        char expVer[32];
6881
6882        mpt_get_fw_exp_ver(expVer, ioc);
6883
6884        /*
6885         *  Shorter summary of attached ioc's...
6886         */
6887        seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d",
6888                        ioc->name,
6889                        ioc->prod_name,
6890                        MPT_FW_REV_MAGIC_ID_STRING,     /* "FwRev=" or somesuch */
6891                        ioc->facts.FWVersion.Word,
6892                        expVer,
6893                        ioc->facts.NumberOfPorts,
6894                        ioc->req_depth);
6895
6896        if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
6897                u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
6898                seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
6899                        a[5], a[4], a[3], a[2], a[1], a[0]);
6900        }
6901
6902        seq_printf(m, ", IRQ=%d", ioc->pci_irq);
6903
6904        if (!ioc->active)
6905                seq_printf(m, " (disabled)");
6906
6907        seq_putc(m, '\n');
6908}
6909#endif
6910
6911/**
6912 *      mpt_set_taskmgmt_in_progress_flag - set flags associated with task management
6913 *      @ioc: Pointer to MPT_ADAPTER structure
6914 *
6915 *      Returns 0 for SUCCESS or -1 if FAILED.
6916 *
6917 *      If -1 is return, then it was not possible to set the flags
6918 **/
6919int
6920mpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6921{
6922        unsigned long    flags;
6923        int              retval;
6924
6925        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6926        if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress ||
6927            (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) {
6928                retval = -1;
6929                goto out;
6930        }
6931        retval = 0;
6932        ioc->taskmgmt_in_progress = 1;
6933        ioc->taskmgmt_quiesce_io = 1;
6934        if (ioc->alt_ioc) {
6935                ioc->alt_ioc->taskmgmt_in_progress = 1;
6936                ioc->alt_ioc->taskmgmt_quiesce_io = 1;
6937        }
6938 out:
6939        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6940        return retval;
6941}
6942EXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag);
6943
6944/**
6945 *      mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management
6946 *      @ioc: Pointer to MPT_ADAPTER structure
6947 *
6948 **/
6949void
6950mpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc)
6951{
6952        unsigned long    flags;
6953
6954        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
6955        ioc->taskmgmt_in_progress = 0;
6956        ioc->taskmgmt_quiesce_io = 0;
6957        if (ioc->alt_ioc) {
6958                ioc->alt_ioc->taskmgmt_in_progress = 0;
6959                ioc->alt_ioc->taskmgmt_quiesce_io = 0;
6960        }
6961        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
6962}
6963EXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag);
6964
6965
6966/**
6967 *      mpt_halt_firmware - Halts the firmware if it is operational and panic
6968 *      the kernel
6969 *      @ioc: Pointer to MPT_ADAPTER structure
6970 *
6971 **/
6972void
6973mpt_halt_firmware(MPT_ADAPTER *ioc)
6974{
6975        u32      ioc_raw_state;
6976
6977        ioc_raw_state = mpt_GetIocState(ioc, 0);
6978
6979        if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
6980                printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
6981                        ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6982                panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
6983                        ioc_raw_state & MPI_DOORBELL_DATA_MASK);
6984        } else {
6985                CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
6986                panic("%s: Firmware is halted due to command timeout\n",
6987                        ioc->name);
6988        }
6989}
6990EXPORT_SYMBOL(mpt_halt_firmware);
6991
6992/**
6993 *      mpt_SoftResetHandler - Issues a less expensive reset
6994 *      @ioc: Pointer to MPT_ADAPTER structure
6995 *      @sleepFlag: Indicates if sleep or schedule must be called.
6996 *
6997 *      Returns 0 for SUCCESS or -1 if FAILED.
6998 *
6999 *      Message Unit Reset - instructs the IOC to reset the Reply Post and
7000 *      Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
7001 *      All posted buffers are freed, and event notification is turned off.
7002 *      IOC doesn't reply to any outstanding request. This will transfer IOC
7003 *      to READY state.
7004 **/
7005static int
7006mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7007{
7008        int              rc;
7009        int              ii;
7010        u8               cb_idx;
7011        unsigned long    flags;
7012        u32              ioc_state;
7013        unsigned long    time_count;
7014
7015        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n",
7016                ioc->name));
7017
7018        ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
7019
7020        if (mpt_fwfault_debug)
7021                mpt_halt_firmware(ioc);
7022
7023        if (ioc_state == MPI_IOC_STATE_FAULT ||
7024            ioc_state == MPI_IOC_STATE_RESET) {
7025                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7026                    "skipping, either in FAULT or RESET state!\n", ioc->name));
7027                return -1;
7028        }
7029
7030        if (ioc->bus_type == FC) {
7031                dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7032                    "skipping, because the bus type is FC!\n", ioc->name));
7033                return -1;
7034        }
7035
7036        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7037        if (ioc->ioc_reset_in_progress) {
7038                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7039                return -1;
7040        }
7041        ioc->ioc_reset_in_progress = 1;
7042        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7043
7044        rc = -1;
7045
7046        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7047                if (MptResetHandlers[cb_idx])
7048                        mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
7049        }
7050
7051        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7052        if (ioc->taskmgmt_in_progress) {
7053                ioc->ioc_reset_in_progress = 0;
7054                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7055                return -1;
7056        }
7057        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7058        /* Disable reply interrupts (also blocks FreeQ) */
7059        CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
7060        ioc->active = 0;
7061        time_count = jiffies;
7062
7063        rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
7064
7065        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7066                if (MptResetHandlers[cb_idx])
7067                        mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET);
7068        }
7069
7070        if (rc)
7071                goto out;
7072
7073        ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK;
7074        if (ioc_state != MPI_IOC_STATE_READY)
7075                goto out;
7076
7077        for (ii = 0; ii < 5; ii++) {
7078                /* Get IOC facts! Allow 5 retries */
7079                rc = GetIocFacts(ioc, sleepFlag,
7080                        MPT_HOSTEVENT_IOC_RECOVER);
7081                if (rc == 0)
7082                        break;
7083                if (sleepFlag == CAN_SLEEP)
7084                        msleep(100);
7085                else
7086                        mdelay(100);
7087        }
7088        if (ii == 5)
7089                goto out;
7090
7091        rc = PrimeIocFifos(ioc);
7092        if (rc != 0)
7093                goto out;
7094
7095        rc = SendIocInit(ioc, sleepFlag);
7096        if (rc != 0)
7097                goto out;
7098
7099        rc = SendEventNotification(ioc, 1, sleepFlag);
7100        if (rc != 0)
7101                goto out;
7102
7103        if (ioc->hard_resets < -1)
7104                ioc->hard_resets++;
7105
7106        /*
7107         * At this point, we know soft reset succeeded.
7108         */
7109
7110        ioc->active = 1;
7111        CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
7112
7113 out:
7114        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7115        ioc->ioc_reset_in_progress = 0;
7116        ioc->taskmgmt_quiesce_io = 0;
7117        ioc->taskmgmt_in_progress = 0;
7118        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7119
7120        if (ioc->active) {      /* otherwise, hard reset coming */
7121                for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7122                        if (MptResetHandlers[cb_idx])
7123                                mpt_signal_reset(cb_idx, ioc,
7124                                        MPT_IOC_POST_RESET);
7125                }
7126        }
7127
7128        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7129                "SoftResetHandler: completed (%d seconds): %s\n",
7130                ioc->name, jiffies_to_msecs(jiffies - time_count)/1000,
7131                ((rc == 0) ? "SUCCESS" : "FAILED")));
7132
7133        return rc;
7134}
7135
7136/**
7137 *      mpt_Soft_Hard_ResetHandler - Try less expensive reset
7138 *      @ioc: Pointer to MPT_ADAPTER structure
7139 *      @sleepFlag: Indicates if sleep or schedule must be called.
7140 *
7141 *      Returns 0 for SUCCESS or -1 if FAILED.
7142 *      Try for softreset first, only if it fails go for expensive
7143 *      HardReset.
7144 **/
7145int
7146mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) {
7147        int ret = -1;
7148
7149        ret = mpt_SoftResetHandler(ioc, sleepFlag);
7150        if (ret == 0)
7151                return ret;
7152        ret = mpt_HardResetHandler(ioc, sleepFlag);
7153        return ret;
7154}
7155EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler);
7156
7157/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7158/*
7159 *      Reset Handling
7160 */
7161/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7162/**
7163 *      mpt_HardResetHandler - Generic reset handler
7164 *      @ioc: Pointer to MPT_ADAPTER structure
7165 *      @sleepFlag: Indicates if sleep or schedule must be called.
7166 *
7167 *      Issues SCSI Task Management call based on input arg values.
7168 *      If TaskMgmt fails, returns associated SCSI request.
7169 *
7170 *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
7171 *      or a non-interrupt thread.  In the former, must not call schedule().
7172 *
7173 *      Note: A return of -1 is a FATAL error case, as it means a
7174 *      FW reload/initialization failed.
7175 *
7176 *      Returns 0 for SUCCESS or -1 if FAILED.
7177 */
7178int
7179mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
7180{
7181        int      rc;
7182        u8       cb_idx;
7183        unsigned long    flags;
7184        unsigned long    time_count;
7185
7186        dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name));
7187#ifdef MFCNT
7188        printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
7189        printk("MF count 0x%x !\n", ioc->mfcnt);
7190#endif
7191        if (mpt_fwfault_debug)
7192                mpt_halt_firmware(ioc);
7193
7194        /* Reset the adapter. Prevent more than 1 call to
7195         * mpt_do_ioc_recovery at any instant in time.
7196         */
7197        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7198        if (ioc->ioc_reset_in_progress) {
7199                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7200                ioc->wait_on_reset_completion = 1;
7201                do {
7202                        ssleep(1);
7203                } while (ioc->ioc_reset_in_progress == 1);
7204                ioc->wait_on_reset_completion = 0;
7205                return ioc->reset_status;
7206        }
7207        if (ioc->wait_on_reset_completion) {
7208                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7209                rc = 0;
7210                time_count = jiffies;
7211                goto exit;
7212        }
7213        ioc->ioc_reset_in_progress = 1;
7214        if (ioc->alt_ioc)
7215                ioc->alt_ioc->ioc_reset_in_progress = 1;
7216        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7217
7218
7219        /* The SCSI driver needs to adjust timeouts on all current
7220         * commands prior to the diagnostic reset being issued.
7221         * Prevents timeouts occurring during a diagnostic reset...very bad.
7222         * For all other protocol drivers, this is a no-op.
7223         */
7224        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7225                if (MptResetHandlers[cb_idx]) {
7226                        mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET);
7227                        if (ioc->alt_ioc)
7228                                mpt_signal_reset(cb_idx, ioc->alt_ioc,
7229                                        MPT_IOC_SETUP_RESET);
7230                }
7231        }
7232
7233        time_count = jiffies;
7234        rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag);
7235        if (rc != 0) {
7236                printk(KERN_WARNING MYNAM
7237                       ": WARNING - (%d) Cannot recover %s, doorbell=0x%08x\n",
7238                       rc, ioc->name, mpt_GetIocState(ioc, 0));
7239        } else {
7240                if (ioc->hard_resets < -1)
7241                        ioc->hard_resets++;
7242        }
7243
7244        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
7245        ioc->ioc_reset_in_progress = 0;
7246        ioc->taskmgmt_quiesce_io = 0;
7247        ioc->taskmgmt_in_progress = 0;
7248        ioc->reset_status = rc;
7249        if (ioc->alt_ioc) {
7250                ioc->alt_ioc->ioc_reset_in_progress = 0;
7251                ioc->alt_ioc->taskmgmt_quiesce_io = 0;
7252                ioc->alt_ioc->taskmgmt_in_progress = 0;
7253        }
7254        spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
7255
7256        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7257                if (MptResetHandlers[cb_idx]) {
7258                        mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET);
7259                        if (ioc->alt_ioc)
7260                                mpt_signal_reset(cb_idx,
7261                                        ioc->alt_ioc, MPT_IOC_POST_RESET);
7262                }
7263        }
7264exit:
7265        dtmprintk(ioc,
7266            printk(MYIOC_s_DEBUG_FMT
7267                "HardResetHandler: completed (%d seconds): %s\n", ioc->name,
7268                jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ?
7269                "SUCCESS" : "FAILED")));
7270
7271        return rc;
7272}
7273
7274#ifdef CONFIG_FUSION_LOGGING
7275static void
7276mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
7277{
7278        char *ds = NULL;
7279        u32 evData0;
7280        int ii;
7281        u8 event;
7282        char *evStr = ioc->evStr;
7283
7284        event = le32_to_cpu(pEventReply->Event) & 0xFF;
7285        evData0 = le32_to_cpu(pEventReply->Data[0]);
7286
7287        switch(event) {
7288        case MPI_EVENT_NONE:
7289                ds = "None";
7290                break;
7291        case MPI_EVENT_LOG_DATA:
7292                ds = "Log Data";
7293                break;
7294        case MPI_EVENT_STATE_CHANGE:
7295                ds = "State Change";
7296                break;
7297        case MPI_EVENT_UNIT_ATTENTION:
7298                ds = "Unit Attention";
7299                break;
7300        case MPI_EVENT_IOC_BUS_RESET:
7301                ds = "IOC Bus Reset";
7302                break;
7303        case MPI_EVENT_EXT_BUS_RESET:
7304                ds = "External Bus Reset";
7305                break;
7306        case MPI_EVENT_RESCAN:
7307                ds = "Bus Rescan Event";
7308                break;
7309        case MPI_EVENT_LINK_STATUS_CHANGE:
7310                if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE)
7311                        ds = "Link Status(FAILURE) Change";
7312                else
7313                        ds = "Link Status(ACTIVE) Change";
7314                break;
7315        case MPI_EVENT_LOOP_STATE_CHANGE:
7316                if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP)
7317                        ds = "Loop State(LIP) Change";
7318                else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE)
7319                        ds = "Loop State(LPE) Change";
7320                else
7321                        ds = "Loop State(LPB) Change";
7322                break;
7323        case MPI_EVENT_LOGOUT:
7324                ds = "Logout";
7325                break;
7326        case MPI_EVENT_EVENT_CHANGE:
7327                if (evData0)
7328                        ds = "Events ON";
7329                else
7330                        ds = "Events OFF";
7331                break;
7332        case MPI_EVENT_INTEGRATED_RAID:
7333        {
7334                u8 ReasonCode = (u8)(evData0 >> 16);
7335                switch (ReasonCode) {
7336                case MPI_EVENT_RAID_RC_VOLUME_CREATED :
7337                        ds = "Integrated Raid: Volume Created";
7338                        break;
7339                case MPI_EVENT_RAID_RC_VOLUME_DELETED :
7340                        ds = "Integrated Raid: Volume Deleted";
7341                        break;
7342                case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED :
7343                        ds = "Integrated Raid: Volume Settings Changed";
7344                        break;
7345                case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED :
7346                        ds = "Integrated Raid: Volume Status Changed";
7347                        break;
7348                case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED :
7349                        ds = "Integrated Raid: Volume Physdisk Changed";
7350                        break;
7351                case MPI_EVENT_RAID_RC_PHYSDISK_CREATED :
7352                        ds = "Integrated Raid: Physdisk Created";
7353                        break;
7354                case MPI_EVENT_RAID_RC_PHYSDISK_DELETED :
7355                        ds = "Integrated Raid: Physdisk Deleted";
7356                        break;
7357                case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED :
7358                        ds = "Integrated Raid: Physdisk Settings Changed";
7359                        break;
7360                case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED :
7361                        ds = "Integrated Raid: Physdisk Status Changed";
7362                        break;
7363                case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED :
7364                        ds = "Integrated Raid: Domain Validation Needed";
7365                        break;
7366                case MPI_EVENT_RAID_RC_SMART_DATA :
7367                        ds = "Integrated Raid; Smart Data";
7368                        break;
7369                case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED :
7370                        ds = "Integrated Raid: Replace Action Started";
7371                        break;
7372                default:
7373                        ds = "Integrated Raid";
7374                break;
7375                }
7376                break;
7377        }
7378        case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE:
7379                ds = "SCSI Device Status Change";
7380                break;
7381        case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
7382        {
7383                u8 id = (u8)(evData0);
7384                u8 channel = (u8)(evData0 >> 8);
7385                u8 ReasonCode = (u8)(evData0 >> 16);
7386                switch (ReasonCode) {
7387                case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
7388                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7389                            "SAS Device Status Change: Added: "
7390                            "id=%d channel=%d", id, channel);
7391                        break;
7392                case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
7393                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7394                            "SAS Device Status Change: Deleted: "
7395                            "id=%d channel=%d", id, channel);
7396                        break;
7397                case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7398                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7399                            "SAS Device Status Change: SMART Data: "
7400                            "id=%d channel=%d", id, channel);
7401                        break;
7402                case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
7403                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7404                            "SAS Device Status Change: No Persistancy: "
7405                            "id=%d channel=%d", id, channel);
7406                        break;
7407                case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7408                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7409                            "SAS Device Status Change: Unsupported Device "
7410                            "Discovered : id=%d channel=%d", id, channel);
7411                        break;
7412                case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7413                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7414                            "SAS Device Status Change: Internal Device "
7415                            "Reset : id=%d channel=%d", id, channel);
7416                        break;
7417                case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7418                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7419                            "SAS Device Status Change: Internal Task "
7420                            "Abort : id=%d channel=%d", id, channel);
7421                        break;
7422                case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7423                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7424                            "SAS Device Status Change: Internal Abort "
7425                            "Task Set : id=%d channel=%d", id, channel);
7426                        break;
7427                case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7428                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7429                            "SAS Device Status Change: Internal Clear "
7430                            "Task Set : id=%d channel=%d", id, channel);
7431                        break;
7432                case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7433                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7434                            "SAS Device Status Change: Internal Query "
7435                            "Task : id=%d channel=%d", id, channel);
7436                        break;
7437                default:
7438                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7439                            "SAS Device Status Change: Unknown: "
7440                            "id=%d channel=%d", id, channel);
7441                        break;
7442                }
7443                break;
7444        }
7445        case MPI_EVENT_ON_BUS_TIMER_EXPIRED:
7446                ds = "Bus Timer Expired";
7447                break;
7448        case MPI_EVENT_QUEUE_FULL:
7449        {
7450                u16 curr_depth = (u16)(evData0 >> 16);
7451                u8 channel = (u8)(evData0 >> 8);
7452                u8 id = (u8)(evData0);
7453
7454                snprintf(evStr, EVENT_DESCR_STR_SZ,
7455                   "Queue Full: channel=%d id=%d depth=%d",
7456                   channel, id, curr_depth);
7457                break;
7458        }
7459        case MPI_EVENT_SAS_SES:
7460                ds = "SAS SES Event";
7461                break;
7462        case MPI_EVENT_PERSISTENT_TABLE_FULL:
7463                ds = "Persistent Table Full";
7464                break;
7465        case MPI_EVENT_SAS_PHY_LINK_STATUS:
7466        {
7467                u8 LinkRates = (u8)(evData0 >> 8);
7468                u8 PhyNumber = (u8)(evData0);
7469                LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >>
7470                        MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT;
7471                switch (LinkRates) {
7472                case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN:
7473                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7474                           "SAS PHY Link Status: Phy=%d:"
7475                           " Rate Unknown",PhyNumber);
7476                        break;
7477                case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED:
7478                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7479                           "SAS PHY Link Status: Phy=%d:"
7480                           " Phy Disabled",PhyNumber);
7481                        break;
7482                case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION:
7483                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7484                           "SAS PHY Link Status: Phy=%d:"
7485                           " Failed Speed Nego",PhyNumber);
7486                        break;
7487                case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE:
7488                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7489                           "SAS PHY Link Status: Phy=%d:"
7490                           " Sata OOB Completed",PhyNumber);
7491                        break;
7492                case MPI_EVENT_SAS_PLS_LR_RATE_1_5:
7493                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7494                           "SAS PHY Link Status: Phy=%d:"
7495                           " Rate 1.5 Gbps",PhyNumber);
7496                        break;
7497                case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
7498                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7499                           "SAS PHY Link Status: Phy=%d:"
7500                           " Rate 3.0 Gbps", PhyNumber);
7501                        break;
7502                case MPI_EVENT_SAS_PLS_LR_RATE_6_0:
7503                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7504                           "SAS PHY Link Status: Phy=%d:"
7505                           " Rate 6.0 Gbps", PhyNumber);
7506                        break;
7507                default:
7508                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7509                           "SAS PHY Link Status: Phy=%d", PhyNumber);
7510                        break;
7511                }
7512                break;
7513        }
7514        case MPI_EVENT_SAS_DISCOVERY_ERROR:
7515                ds = "SAS Discovery Error";
7516                break;
7517        case MPI_EVENT_IR_RESYNC_UPDATE:
7518        {
7519                u8 resync_complete = (u8)(evData0 >> 16);
7520                snprintf(evStr, EVENT_DESCR_STR_SZ,
7521                    "IR Resync Update: Complete = %d:",resync_complete);
7522                break;
7523        }
7524        case MPI_EVENT_IR2:
7525        {
7526                u8 id = (u8)(evData0);
7527                u8 channel = (u8)(evData0 >> 8);
7528                u8 phys_num = (u8)(evData0 >> 24);
7529                u8 ReasonCode = (u8)(evData0 >> 16);
7530
7531                switch (ReasonCode) {
7532                case MPI_EVENT_IR2_RC_LD_STATE_CHANGED:
7533                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7534                            "IR2: LD State Changed: "
7535                            "id=%d channel=%d phys_num=%d",
7536                            id, channel, phys_num);
7537                        break;
7538                case MPI_EVENT_IR2_RC_PD_STATE_CHANGED:
7539                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7540                            "IR2: PD State Changed "
7541                            "id=%d channel=%d phys_num=%d",
7542                            id, channel, phys_num);
7543                        break;
7544                case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL:
7545                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7546                            "IR2: Bad Block Table Full: "
7547                            "id=%d channel=%d phys_num=%d",
7548                            id, channel, phys_num);
7549                        break;
7550                case MPI_EVENT_IR2_RC_PD_INSERTED:
7551                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7552                            "IR2: PD Inserted: "
7553                            "id=%d channel=%d phys_num=%d",
7554                            id, channel, phys_num);
7555                        break;
7556                case MPI_EVENT_IR2_RC_PD_REMOVED:
7557                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7558                            "IR2: PD Removed: "
7559                            "id=%d channel=%d phys_num=%d",
7560                            id, channel, phys_num);
7561                        break;
7562                case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
7563                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7564                            "IR2: Foreign CFG Detected: "
7565                            "id=%d channel=%d phys_num=%d",
7566                            id, channel, phys_num);
7567                        break;
7568                case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR:
7569                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7570                            "IR2: Rebuild Medium Error: "
7571                            "id=%d channel=%d phys_num=%d",
7572                            id, channel, phys_num);
7573                        break;
7574                case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
7575                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7576                            "IR2: Dual Port Added: "
7577                            "id=%d channel=%d phys_num=%d",
7578                            id, channel, phys_num);
7579                        break;
7580                case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
7581                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7582                            "IR2: Dual Port Removed: "
7583                            "id=%d channel=%d phys_num=%d",
7584                            id, channel, phys_num);
7585                        break;
7586                default:
7587                        ds = "IR2";
7588                break;
7589                }
7590                break;
7591        }
7592        case MPI_EVENT_SAS_DISCOVERY:
7593        {
7594                if (evData0)
7595                        ds = "SAS Discovery: Start";
7596                else
7597                        ds = "SAS Discovery: Stop";
7598                break;
7599        }
7600        case MPI_EVENT_LOG_ENTRY_ADDED:
7601                ds = "SAS Log Entry Added";
7602                break;
7603
7604        case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
7605        {
7606                u8 phy_num = (u8)(evData0);
7607                u8 port_num = (u8)(evData0 >> 8);
7608                u8 port_width = (u8)(evData0 >> 16);
7609                u8 primative = (u8)(evData0 >> 24);
7610                snprintf(evStr, EVENT_DESCR_STR_SZ,
7611                    "SAS Broadcase Primative: phy=%d port=%d "
7612                    "width=%d primative=0x%02x",
7613                    phy_num, port_num, port_width, primative);
7614                break;
7615        }
7616
7617        case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
7618        {
7619                u8 reason = (u8)(evData0);
7620
7621                switch (reason) {
7622                case MPI_EVENT_SAS_INIT_RC_ADDED:
7623                        ds = "SAS Initiator Status Change: Added";
7624                        break;
7625                case MPI_EVENT_SAS_INIT_RC_REMOVED:
7626                        ds = "SAS Initiator Status Change: Deleted";
7627                        break;
7628                default:
7629                        ds = "SAS Initiator Status Change";
7630                        break;
7631                }
7632                break;
7633        }
7634
7635        case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW:
7636        {
7637                u8 max_init = (u8)(evData0);
7638                u8 current_init = (u8)(evData0 >> 8);
7639
7640                snprintf(evStr, EVENT_DESCR_STR_SZ,
7641                    "SAS Initiator Device Table Overflow: max initiators=%02d "
7642                    "current initators=%02d",
7643                    max_init, current_init);
7644                break;
7645        }
7646        case MPI_EVENT_SAS_SMP_ERROR:
7647        {
7648                u8 status = (u8)(evData0);
7649                u8 port_num = (u8)(evData0 >> 8);
7650                u8 result = (u8)(evData0 >> 16);
7651
7652                if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID)
7653                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7654                            "SAS SMP Error: port=%d result=0x%02x",
7655                            port_num, result);
7656                else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR)
7657                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7658                            "SAS SMP Error: port=%d : CRC Error",
7659                            port_num);
7660                else if (status == MPI_EVENT_SAS_SMP_TIMEOUT)
7661                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7662                            "SAS SMP Error: port=%d : Timeout",
7663                            port_num);
7664                else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION)
7665                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7666                            "SAS SMP Error: port=%d : No Destination",
7667                            port_num);
7668                else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION)
7669                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7670                            "SAS SMP Error: port=%d : Bad Destination",
7671                            port_num);
7672                else
7673                        snprintf(evStr, EVENT_DESCR_STR_SZ,
7674                            "SAS SMP Error: port=%d : status=0x%02x",
7675                            port_num, status);
7676                break;
7677        }
7678
7679        case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
7680        {
7681                u8 reason = (u8)(evData0);
7682
7683                switch (reason) {
7684                case MPI_EVENT_SAS_EXP_RC_ADDED:
7685                        ds = "Expander Status Change: Added";
7686                        break;
7687                case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING:
7688                        ds = "Expander Status Change: Deleted";
7689                        break;
7690                default:
7691                        ds = "Expander Status Change";
7692                        break;
7693                }
7694                break;
7695        }
7696
7697        /*
7698         *  MPT base "custom" events may be added here...
7699         */
7700        default:
7701                ds = "Unknown";
7702                break;
7703        }
7704        if (ds)
7705                strncpy(evStr, ds, EVENT_DESCR_STR_SZ);
7706
7707
7708        devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7709            "MPT event:(%02Xh) : %s\n",
7710            ioc->name, event, evStr));
7711
7712        devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM
7713            ": Event data:\n"));
7714        for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++)
7715                devtverboseprintk(ioc, printk(" %08x",
7716                    le32_to_cpu(pEventReply->Data[ii])));
7717        devtverboseprintk(ioc, printk(KERN_DEBUG "\n"));
7718}
7719#endif
7720/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7721/**
7722 *      ProcessEventNotification - Route EventNotificationReply to all event handlers
7723 *      @ioc: Pointer to MPT_ADAPTER structure
7724 *      @pEventReply: Pointer to EventNotification reply frame
7725 *      @evHandlers: Pointer to integer, number of event handlers
7726 *
7727 *      Routes a received EventNotificationReply to all currently registered
7728 *      event handlers.
7729 *      Returns sum of event handlers return values.
7730 */
7731static int
7732ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers)
7733{
7734        u16 evDataLen;
7735        u32 evData0 = 0;
7736        int ii;
7737        u8 cb_idx;
7738        int r = 0;
7739        int handlers = 0;
7740        u8 event;
7741
7742        /*
7743         *  Do platform normalization of values
7744         */
7745        event = le32_to_cpu(pEventReply->Event) & 0xFF;
7746        evDataLen = le16_to_cpu(pEventReply->EventDataLength);
7747        if (evDataLen) {
7748                evData0 = le32_to_cpu(pEventReply->Data[0]);
7749        }
7750
7751#ifdef CONFIG_FUSION_LOGGING
7752        if (evDataLen)
7753                mpt_display_event_info(ioc, pEventReply);
7754#endif
7755
7756        /*
7757         *  Do general / base driver event processing
7758         */
7759        switch(event) {
7760        case MPI_EVENT_EVENT_CHANGE:            /* 0A */
7761                if (evDataLen) {
7762                        u8 evState = evData0 & 0xFF;
7763
7764                        /* CHECKME! What if evState unexpectedly says OFF (0)? */
7765
7766                        /* Update EventState field in cached IocFacts */
7767                        if (ioc->facts.Function) {
7768                                ioc->facts.EventState = evState;
7769                        }
7770                }
7771                break;
7772        case MPI_EVENT_INTEGRATED_RAID:
7773                mptbase_raid_process_event_data(ioc,
7774                    (MpiEventDataRaid_t *)pEventReply->Data);
7775                break;
7776        default:
7777                break;
7778        }
7779
7780        /*
7781         * Should this event be logged? Events are written sequentially.
7782         * When buffer is full, start again at the top.
7783         */
7784        if (ioc->events && (ioc->eventTypes & ( 1 << event))) {
7785                int idx;
7786
7787                idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE;
7788
7789                ioc->events[idx].event = event;
7790                ioc->events[idx].eventContext = ioc->eventContext;
7791
7792                for (ii = 0; ii < 2; ii++) {
7793                        if (ii < evDataLen)
7794                                ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]);
7795                        else
7796                                ioc->events[idx].data[ii] =  0;
7797                }
7798
7799                ioc->eventContext++;
7800        }
7801
7802
7803        /*
7804         *  Call each currently registered protocol event handler.
7805         */
7806        for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) {
7807                if (MptEvHandlers[cb_idx]) {
7808                        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7809                            "Routing Event to event handler #%d\n",
7810                            ioc->name, cb_idx));
7811                        r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply);
7812                        handlers++;
7813                }
7814        }
7815        /* FIXME?  Examine results here? */
7816
7817        /*
7818         *  If needed, send (a single) EventAck.
7819         */
7820        if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
7821                devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT
7822                        "EventAck required\n",ioc->name));
7823                if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
7824                        devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n",
7825                                        ioc->name, ii));
7826                }
7827        }
7828
7829        *evHandlers = handlers;
7830        return r;
7831}
7832
7833/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7834/**
7835 *      mpt_fc_log_info - Log information returned from Fibre Channel IOC.
7836 *      @ioc: Pointer to MPT_ADAPTER structure
7837 *      @log_info: U32 LogInfo reply word from the IOC
7838 *
7839 *      Refer to lsi/mpi_log_fc.h.
7840 */
7841static void
7842mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
7843{
7844        char *desc = "unknown";
7845
7846        switch (log_info & 0xFF000000) {
7847        case MPI_IOCLOGINFO_FC_INIT_BASE:
7848                desc = "FCP Initiator";
7849                break;
7850        case MPI_IOCLOGINFO_FC_TARGET_BASE:
7851                desc = "FCP Target";
7852                break;
7853        case MPI_IOCLOGINFO_FC_LAN_BASE:
7854                desc = "LAN";
7855                break;
7856        case MPI_IOCLOGINFO_FC_MSG_BASE:
7857                desc = "MPI Message Layer";
7858                break;
7859        case MPI_IOCLOGINFO_FC_LINK_BASE:
7860                desc = "FC Link";
7861                break;
7862        case MPI_IOCLOGINFO_FC_CTX_BASE:
7863                desc = "Context Manager";
7864                break;
7865        case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET:
7866                desc = "Invalid Field Offset";
7867                break;
7868        case MPI_IOCLOGINFO_FC_STATE_CHANGE:
7869                desc = "State Change Info";
7870                break;
7871        }
7872
7873        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n",
7874                        ioc->name, log_info, desc, (log_info & 0xFFFFFF));
7875}
7876
7877/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7878/**
7879 *      mpt_spi_log_info - Log information returned from SCSI Parallel IOC.
7880 *      @ioc: Pointer to MPT_ADAPTER structure
7881 *      @log_info: U32 LogInfo word from the IOC
7882 *
7883 *      Refer to lsi/sp_log.h.
7884 */
7885static void
7886mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info)
7887{
7888        u32 info = log_info & 0x00FF0000;
7889        char *desc = "unknown";
7890
7891        switch (info) {
7892        case 0x00010000:
7893                desc = "bug! MID not found";
7894                break;
7895
7896        case 0x00020000:
7897                desc = "Parity Error";
7898                break;
7899
7900        case 0x00030000:
7901                desc = "ASYNC Outbound Overrun";
7902                break;
7903
7904        case 0x00040000:
7905                desc = "SYNC Offset Error";
7906                break;
7907
7908        case 0x00050000:
7909                desc = "BM Change";
7910                break;
7911
7912        case 0x00060000:
7913                desc = "Msg In Overflow";
7914                break;
7915
7916        case 0x00070000:
7917                desc = "DMA Error";
7918                break;
7919
7920        case 0x00080000:
7921                desc = "Outbound DMA Overrun";
7922                break;
7923
7924        case 0x00090000:
7925                desc = "Task Management";
7926                break;
7927
7928        case 0x000A0000:
7929                desc = "Device Problem";
7930                break;
7931
7932        case 0x000B0000:
7933                desc = "Invalid Phase Change";
7934                break;
7935
7936        case 0x000C0000:
7937                desc = "Untagged Table Size";
7938                break;
7939
7940        }
7941
7942        printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc);
7943}
7944
7945/* strings for sas loginfo */
7946        static char *originator_str[] = {
7947                "IOP",                                          /* 00h */
7948                "PL",                                           /* 01h */
7949                "IR"                                            /* 02h */
7950        };
7951        static char *iop_code_str[] = {
7952                NULL,                                           /* 00h */
7953                "Invalid SAS Address",                          /* 01h */
7954                NULL,                                           /* 02h */
7955                "Invalid Page",                                 /* 03h */
7956                "Diag Message Error",                           /* 04h */
7957                "Task Terminated",                              /* 05h */
7958                "Enclosure Management",                         /* 06h */
7959                "Target Mode"                                   /* 07h */
7960        };
7961        static char *pl_code_str[] = {
7962                NULL,                                           /* 00h */
7963                "Open Failure",                                 /* 01h */
7964                "Invalid Scatter Gather List",                  /* 02h */
7965                "Wrong Relative Offset or Frame Length",        /* 03h */
7966                "Frame Transfer Error",                         /* 04h */
7967                "Transmit Frame Connected Low",                 /* 05h */
7968                "SATA Non-NCQ RW Error Bit Set",                /* 06h */
7969                "SATA Read Log Receive Data Error",             /* 07h */
7970                "SATA NCQ Fail All Commands After Error",       /* 08h */
7971                "SATA Error in Receive Set Device Bit FIS",     /* 09h */
7972                "Receive Frame Invalid Message",                /* 0Ah */
7973                "Receive Context Message Valid Error",          /* 0Bh */
7974                "Receive Frame Current Frame Error",            /* 0Ch */
7975                "SATA Link Down",                               /* 0Dh */
7976                "Discovery SATA Init W IOS",                    /* 0Eh */
7977                "Config Invalid Page",                          /* 0Fh */
7978                "Discovery SATA Init Timeout",                  /* 10h */
7979                "Reset",                                        /* 11h */
7980                "Abort",                                        /* 12h */
7981                "IO Not Yet Executed",                          /* 13h */
7982                "IO Executed",                                  /* 14h */
7983                "Persistent Reservation Out Not Affiliation "
7984                    "Owner",                                    /* 15h */
7985                "Open Transmit DMA Abort",                      /* 16h */
7986                "IO Device Missing Delay Retry",                /* 17h */
7987                "IO Cancelled Due to Receive Error",            /* 18h */
7988                NULL,                                           /* 19h */
7989                NULL,                                           /* 1Ah */
7990                NULL,                                           /* 1Bh */
7991                NULL,                                           /* 1Ch */
7992                NULL,                                           /* 1Dh */
7993                NULL,                                           /* 1Eh */
7994                NULL,                                           /* 1Fh */
7995                "Enclosure Management"                          /* 20h */
7996        };
7997        static char *ir_code_str[] = {
7998                "Raid Action Error",                            /* 00h */
7999                NULL,                                           /* 00h */
8000                NULL,                                           /* 01h */
8001                NULL,                                           /* 02h */
8002                NULL,                                           /* 03h */
8003                NULL,                                           /* 04h */
8004                NULL,                                           /* 05h */
8005                NULL,                                           /* 06h */
8006                NULL                                            /* 07h */
8007        };
8008        static char *raid_sub_code_str[] = {
8009                NULL,                                           /* 00h */
8010                "Volume Creation Failed: Data Passed too "
8011                    "Large",                                    /* 01h */
8012                "Volume Creation Failed: Duplicate Volumes "
8013                    "Attempted",                                /* 02h */
8014                "Volume Creation Failed: Max Number "
8015                    "Supported Volumes Exceeded",               /* 03h */
8016                "Volume Creation Failed: DMA Error",            /* 04h */
8017                "Volume Creation Failed: Invalid Volume Type",  /* 05h */
8018                "Volume Creation Failed: Error Reading "
8019                    "MFG Page 4",                               /* 06h */
8020                "Volume Creation Failed: Creating Internal "
8021                    "Structures",                               /* 07h */
8022                NULL,                                           /* 08h */
8023                NULL,                                           /* 09h */
8024                NULL,                                           /* 0Ah */
8025                NULL,                                           /* 0Bh */
8026                NULL,                                           /* 0Ch */
8027                NULL,                                           /* 0Dh */
8028                NULL,                                           /* 0Eh */
8029                NULL,                                           /* 0Fh */
8030                "Activation failed: Already Active Volume",     /* 10h */
8031                "Activation failed: Unsupported Volume Type",   /* 11h */
8032                "Activation failed: Too Many Active Volumes",   /* 12h */
8033                "Activation failed: Volume ID in Use",          /* 13h */
8034                "Activation failed: Reported Failure",          /* 14h */
8035                "Activation failed: Importing a Volume",        /* 15h */
8036                NULL,                                           /* 16h */
8037                NULL,                                           /* 17h */
8038                NULL,                                           /* 18h */
8039                NULL,                                           /* 19h */
8040                NULL,                                           /* 1Ah */
8041                NULL,                                           /* 1Bh */
8042                NULL,                                           /* 1Ch */
8043                NULL,                                           /* 1Dh */
8044                NULL,                                           /* 1Eh */
8045                NULL,                                           /* 1Fh */
8046                "Phys Disk failed: Too Many Phys Disks",        /* 20h */
8047                "Phys Disk failed: Data Passed too Large",      /* 21h */
8048                "Phys Disk failed: DMA Error",                  /* 22h */
8049                "Phys Disk failed: Invalid <channel:id>",       /* 23h */
8050                "Phys Disk failed: Creating Phys Disk Config "
8051                    "Page",                                     /* 24h */
8052                NULL,                                           /* 25h */
8053                NULL,                                           /* 26h */
8054                NULL,                                           /* 27h */
8055                NULL,                                           /* 28h */
8056                NULL,                                           /* 29h */
8057                NULL,                                           /* 2Ah */
8058                NULL,                                           /* 2Bh */
8059                NULL,                                           /* 2Ch */
8060                NULL,                                           /* 2Dh */
8061                NULL,                                           /* 2Eh */
8062                NULL,                                           /* 2Fh */
8063                "Compatibility Error: IR Disabled",             /* 30h */
8064                "Compatibility Error: Inquiry Command Failed",  /* 31h */
8065                "Compatibility Error: Device not Direct Access "
8066                    "Device ",                                  /* 32h */
8067                "Compatibility Error: Removable Device Found",  /* 33h */
8068                "Compatibility Error: Device SCSI Version not "
8069                    "2 or Higher",                              /* 34h */
8070                "Compatibility Error: SATA Device, 48 BIT LBA "
8071                    "not Supported",                            /* 35h */
8072                "Compatibility Error: Device doesn't have "
8073                    "512 Byte Block Sizes",                     /* 36h */
8074                "Compatibility Error: Volume Type Check Failed", /* 37h */
8075                "Compatibility Error: Volume Type is "
8076                    "Unsupported by FW",                        /* 38h */
8077                "Compatibility Error: Disk Drive too Small for "
8078                    "use in Volume",                            /* 39h */
8079                "Compatibility Error: Phys Disk for Create "
8080                    "Volume not Found",                         /* 3Ah */
8081                "Compatibility Error: Too Many or too Few "
8082                    "Disks for Volume Type",                    /* 3Bh */
8083                "Compatibility Error: Disk stripe Sizes "
8084                    "Must be 64KB",                             /* 3Ch */
8085                "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */
8086        };
8087
8088/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8089/**
8090 *      mpt_sas_log_info - Log information returned from SAS IOC.
8091 *      @ioc: Pointer to MPT_ADAPTER structure
8092 *      @log_info: U32 LogInfo reply word from the IOC
8093 *      @cb_idx: callback function's handle
8094 *
8095 *      Refer to lsi/mpi_log_sas.h.
8096 **/
8097static void
8098mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx)
8099{
8100union loginfo_type {
8101        u32     loginfo;
8102        struct {
8103                u32     subcode:16;
8104                u32     code:8;
8105                u32     originator:4;
8106                u32     bus_type:4;
8107        }dw;
8108};
8109        union loginfo_type sas_loginfo;
8110        char *originator_desc = NULL;
8111        char *code_desc = NULL;
8112        char *sub_code_desc = NULL;
8113
8114        sas_loginfo.loginfo = log_info;
8115        if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) &&
8116            (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str)))
8117                return;
8118
8119        originator_desc = originator_str[sas_loginfo.dw.originator];
8120
8121        switch (sas_loginfo.dw.originator) {
8122
8123                case 0:  /* IOP */
8124                        if (sas_loginfo.dw.code <
8125                            ARRAY_SIZE(iop_code_str))
8126                                code_desc = iop_code_str[sas_loginfo.dw.code];
8127                        break;
8128                case 1:  /* PL */
8129                        if (sas_loginfo.dw.code <
8130                            ARRAY_SIZE(pl_code_str))
8131                                code_desc = pl_code_str[sas_loginfo.dw.code];
8132                        break;
8133                case 2:  /* IR */
8134                        if (sas_loginfo.dw.code >=
8135                            ARRAY_SIZE(ir_code_str))
8136                                break;
8137                        code_desc = ir_code_str[sas_loginfo.dw.code];
8138                        if (sas_loginfo.dw.subcode >=
8139                            ARRAY_SIZE(raid_sub_code_str))
8140                                break;
8141                        if (sas_loginfo.dw.code == 0)
8142                                sub_code_desc =
8143                                    raid_sub_code_str[sas_loginfo.dw.subcode];
8144                        break;
8145                default:
8146                        return;
8147        }
8148
8149        if (sub_code_desc != NULL)
8150                printk(MYIOC_s_INFO_FMT
8151                        "LogInfo(0x%08x): Originator={%s}, Code={%s},"
8152                        " SubCode={%s} cb_idx %s\n",
8153                        ioc->name, log_info, originator_desc, code_desc,
8154                        sub_code_desc, MptCallbacksName[cb_idx]);
8155        else if (code_desc != NULL)
8156                printk(MYIOC_s_INFO_FMT
8157                        "LogInfo(0x%08x): Originator={%s}, Code={%s},"
8158                        " SubCode(0x%04x) cb_idx %s\n",
8159                        ioc->name, log_info, originator_desc, code_desc,
8160                        sas_loginfo.dw.subcode, MptCallbacksName[cb_idx]);
8161        else
8162                printk(MYIOC_s_INFO_FMT
8163                        "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x),"
8164                        " SubCode(0x%04x) cb_idx %s\n",
8165                        ioc->name, log_info, originator_desc,
8166                        sas_loginfo.dw.code, sas_loginfo.dw.subcode,
8167                        MptCallbacksName[cb_idx]);
8168}
8169
8170/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8171/**
8172 *      mpt_iocstatus_info_config - IOCSTATUS information for config pages
8173 *      @ioc: Pointer to MPT_ADAPTER structure
8174 *      @ioc_status: U32 IOCStatus word from IOC
8175 *      @mf: Pointer to MPT request frame
8176 *
8177 *      Refer to lsi/mpi.h.
8178 **/
8179static void
8180mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8181{
8182        Config_t *pReq = (Config_t *)mf;
8183        char extend_desc[EVENT_DESCR_STR_SZ];
8184        char *desc = NULL;
8185        u32 form;
8186        u8 page_type;
8187
8188        if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED)
8189                page_type = pReq->ExtPageType;
8190        else
8191                page_type = pReq->Header.PageType;
8192
8193        /*
8194         * ignore invalid page messages for GET_NEXT_HANDLE
8195         */
8196        form = le32_to_cpu(pReq->PageAddress);
8197        if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
8198                if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE ||
8199                    page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER ||
8200                    page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) {
8201                        if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) ==
8202                                MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE)
8203                                return;
8204                }
8205                if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE)
8206                        if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) ==
8207                                MPI_FC_DEVICE_PGAD_FORM_NEXT_DID)
8208                                return;
8209        }
8210
8211        snprintf(extend_desc, EVENT_DESCR_STR_SZ,
8212            "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh",
8213            page_type, pReq->Header.PageNumber, pReq->Action, form);
8214
8215        switch (ioc_status) {
8216
8217        case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8218                desc = "Config Page Invalid Action";
8219                break;
8220
8221        case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
8222                desc = "Config Page Invalid Type";
8223                break;
8224
8225        case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
8226                desc = "Config Page Invalid Page";
8227                break;
8228
8229        case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
8230                desc = "Config Page Invalid Data";
8231                break;
8232
8233        case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
8234                desc = "Config Page No Defaults";
8235                break;
8236
8237        case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
8238                desc = "Config Page Can't Commit";
8239                break;
8240        }
8241
8242        if (!desc)
8243                return;
8244
8245        dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n",
8246            ioc->name, ioc_status, desc, extend_desc));
8247}
8248
8249/**
8250 *      mpt_iocstatus_info - IOCSTATUS information returned from IOC.
8251 *      @ioc: Pointer to MPT_ADAPTER structure
8252 *      @ioc_status: U32 IOCStatus word from IOC
8253 *      @mf: Pointer to MPT request frame
8254 *
8255 *      Refer to lsi/mpi.h.
8256 **/
8257static void
8258mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
8259{
8260        u32 status = ioc_status & MPI_IOCSTATUS_MASK;
8261        char *desc = NULL;
8262
8263        switch (status) {
8264
8265/****************************************************************************/
8266/*  Common IOCStatus values for all replies                                 */
8267/****************************************************************************/
8268
8269        case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
8270                desc = "Invalid Function";
8271                break;
8272
8273        case MPI_IOCSTATUS_BUSY: /* 0x0002 */
8274                desc = "Busy";
8275                break;
8276
8277        case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
8278                desc = "Invalid SGL";
8279                break;
8280
8281        case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
8282                desc = "Internal Error";
8283                break;
8284
8285        case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
8286                desc = "Reserved";
8287                break;
8288
8289        case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
8290                desc = "Insufficient Resources";
8291                break;
8292
8293        case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
8294                desc = "Invalid Field";
8295                break;
8296
8297        case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
8298                desc = "Invalid State";
8299                break;
8300
8301/****************************************************************************/
8302/*  Config IOCStatus values                                                 */
8303/****************************************************************************/
8304
8305        case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */
8306        case MPI_IOCSTATUS_CONFIG_INVALID_TYPE:   /* 0x0021 */
8307        case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:   /* 0x0022 */
8308        case MPI_IOCSTATUS_CONFIG_INVALID_DATA:   /* 0x0023 */
8309        case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS:    /* 0x0024 */
8310        case MPI_IOCSTATUS_CONFIG_CANT_COMMIT:    /* 0x0025 */
8311                mpt_iocstatus_info_config(ioc, status, mf);
8312                break;
8313
8314/****************************************************************************/
8315/*  SCSIIO Reply (SPI, FCP, SAS) initiator values                           */
8316/*                                                                          */
8317/*  Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */
8318/*                                                                          */
8319/****************************************************************************/
8320
8321        case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
8322        case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
8323        case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
8324        case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
8325        case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
8326        case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
8327        case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
8328        case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
8329        case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
8330        case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
8331        case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
8332        case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
8333        case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
8334                break;
8335
8336/****************************************************************************/
8337/*  SCSI Target values                                                      */
8338/****************************************************************************/
8339
8340        case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */
8341                desc = "Target: Priority IO";
8342                break;
8343
8344        case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */
8345                desc = "Target: Invalid Port";
8346                break;
8347
8348        case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */
8349                desc = "Target Invalid IO Index:";
8350                break;
8351
8352        case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */
8353                desc = "Target: Aborted";
8354                break;
8355
8356        case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */
8357                desc = "Target: No Conn Retryable";
8358                break;
8359
8360        case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */
8361                desc = "Target: No Connection";
8362                break;
8363
8364        case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */
8365                desc = "Target: Transfer Count Mismatch";
8366                break;
8367
8368        case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */
8369                desc = "Target: STS Data not Sent";
8370                break;
8371
8372        case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */
8373                desc = "Target: Data Offset Error";
8374                break;
8375
8376        case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */
8377                desc = "Target: Too Much Write Data";
8378                break;
8379
8380        case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */
8381                desc = "Target: IU Too Short";
8382                break;
8383
8384        case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */
8385                desc = "Target: ACK NAK Timeout";
8386                break;
8387
8388        case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */
8389                desc = "Target: Nak Received";
8390                break;
8391
8392/****************************************************************************/
8393/*  Fibre Channel Direct Access values                                      */
8394/****************************************************************************/
8395
8396        case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */
8397                desc = "FC: Aborted";
8398                break;
8399
8400        case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */
8401                desc = "FC: RX ID Invalid";
8402                break;
8403
8404        case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */
8405                desc = "FC: DID Invalid";
8406                break;
8407
8408        case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */
8409                desc = "FC: Node Logged Out";
8410                break;
8411
8412        case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */
8413                desc = "FC: Exchange Canceled";
8414                break;
8415
8416/****************************************************************************/
8417/*  LAN values                                                              */
8418/****************************************************************************/
8419
8420        case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */
8421                desc = "LAN: Device not Found";
8422                break;
8423
8424        case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */
8425                desc = "LAN: Device Failure";
8426                break;
8427
8428        case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */
8429                desc = "LAN: Transmit Error";
8430                break;
8431
8432        case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */
8433                desc = "LAN: Transmit Aborted";
8434                break;
8435
8436        case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */
8437                desc = "LAN: Receive Error";
8438                break;
8439
8440        case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */
8441                desc = "LAN: Receive Aborted";
8442                break;
8443
8444        case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */
8445                desc = "LAN: Partial Packet";
8446                break;
8447
8448        case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */
8449                desc = "LAN: Canceled";
8450                break;
8451
8452/****************************************************************************/
8453/*  Serial Attached SCSI values                                             */
8454/****************************************************************************/
8455
8456        case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */
8457                desc = "SAS: SMP Request Failed";
8458                break;
8459
8460        case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */
8461                desc = "SAS: SMP Data Overrun";
8462                break;
8463
8464        default:
8465                desc = "Others";
8466                break;
8467        }
8468
8469        if (!desc)
8470                return;
8471
8472        dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n",
8473            ioc->name, status, desc));
8474}
8475
8476/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8477EXPORT_SYMBOL(mpt_attach);
8478EXPORT_SYMBOL(mpt_detach);
8479#ifdef CONFIG_PM
8480EXPORT_SYMBOL(mpt_resume);
8481EXPORT_SYMBOL(mpt_suspend);
8482#endif
8483EXPORT_SYMBOL(ioc_list);
8484EXPORT_SYMBOL(mpt_register);
8485EXPORT_SYMBOL(mpt_deregister);
8486EXPORT_SYMBOL(mpt_event_register);
8487EXPORT_SYMBOL(mpt_event_deregister);
8488EXPORT_SYMBOL(mpt_reset_register);
8489EXPORT_SYMBOL(mpt_reset_deregister);
8490EXPORT_SYMBOL(mpt_device_driver_register);
8491EXPORT_SYMBOL(mpt_device_driver_deregister);
8492EXPORT_SYMBOL(mpt_get_msg_frame);
8493EXPORT_SYMBOL(mpt_put_msg_frame);
8494EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri);
8495EXPORT_SYMBOL(mpt_free_msg_frame);
8496EXPORT_SYMBOL(mpt_send_handshake_request);
8497EXPORT_SYMBOL(mpt_verify_adapter);
8498EXPORT_SYMBOL(mpt_GetIocState);
8499EXPORT_SYMBOL(mpt_print_ioc_summary);
8500EXPORT_SYMBOL(mpt_HardResetHandler);
8501EXPORT_SYMBOL(mpt_config);
8502EXPORT_SYMBOL(mpt_findImVolumes);
8503EXPORT_SYMBOL(mpt_alloc_fw_memory);
8504EXPORT_SYMBOL(mpt_free_fw_memory);
8505EXPORT_SYMBOL(mptbase_sas_persist_operation);
8506EXPORT_SYMBOL(mpt_raid_phys_disk_pg0);
8507
8508/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8509/**
8510 *      fusion_init - Fusion MPT base driver initialization routine.
8511 *
8512 *      Returns 0 for success, non-zero for failure.
8513 */
8514static int __init
8515fusion_init(void)
8516{
8517        u8 cb_idx;
8518
8519        show_mptmod_ver(my_NAME, my_VERSION);
8520        printk(KERN_INFO COPYRIGHT "\n");
8521
8522        for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) {
8523                MptCallbacks[cb_idx] = NULL;
8524                MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER;
8525                MptEvHandlers[cb_idx] = NULL;
8526                MptResetHandlers[cb_idx] = NULL;
8527        }
8528
8529        /*  Register ourselves (mptbase) in order to facilitate
8530         *  EventNotification handling.
8531         */
8532        mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER,
8533            "mptbase_reply");
8534
8535        /* Register for hard reset handling callbacks.
8536         */
8537        mpt_reset_register(mpt_base_index, mpt_ioc_reset);
8538
8539#ifdef CONFIG_PROC_FS
8540        (void) procmpt_create();
8541#endif
8542        return 0;
8543}
8544
8545/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
8546/**
8547 *      fusion_exit - Perform driver unload cleanup.
8548 *
8549 *      This routine frees all resources associated with each MPT adapter
8550 *      and removes all %MPT_PROCFS_MPTBASEDIR entries.
8551 */
8552static void __exit
8553fusion_exit(void)
8554{
8555
8556        mpt_reset_deregister(mpt_base_index);
8557
8558#ifdef CONFIG_PROC_FS
8559        procmpt_destroy();
8560#endif
8561}
8562
8563module_init(fusion_init);
8564module_exit(fusion_exit);
8565