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