linux/drivers/scsi/qla2xxx/qla_nx2.c
<<
>>
Prefs
   1/*
   2 * QLogic Fibre Channel HBA Driver
   3 * Copyright (c)  2003-2014 QLogic Corporation
   4 *
   5 * See LICENSE.qla2xxx for copyright and licensing details.
   6 */
   7
   8#include <linux/vmalloc.h>
   9#include <linux/delay.h>
  10
  11#include "qla_def.h"
  12#include "qla_gbl.h"
  13
  14#define TIMEOUT_100_MS 100
  15
  16static const uint32_t qla8044_reg_tbl[] = {
  17        QLA8044_PEG_HALT_STATUS1,
  18        QLA8044_PEG_HALT_STATUS2,
  19        QLA8044_PEG_ALIVE_COUNTER,
  20        QLA8044_CRB_DRV_ACTIVE,
  21        QLA8044_CRB_DEV_STATE,
  22        QLA8044_CRB_DRV_STATE,
  23        QLA8044_CRB_DRV_SCRATCH,
  24        QLA8044_CRB_DEV_PART_INFO1,
  25        QLA8044_CRB_IDC_VER_MAJOR,
  26        QLA8044_FW_VER_MAJOR,
  27        QLA8044_FW_VER_MINOR,
  28        QLA8044_FW_VER_SUB,
  29        QLA8044_CMDPEG_STATE,
  30        QLA8044_ASIC_TEMP,
  31};
  32
  33/* 8044 Flash Read/Write functions */
  34uint32_t
  35qla8044_rd_reg(struct qla_hw_data *ha, ulong addr)
  36{
  37        return readl((void __iomem *) (ha->nx_pcibase + addr));
  38}
  39
  40void
  41qla8044_wr_reg(struct qla_hw_data *ha, ulong addr, uint32_t val)
  42{
  43        writel(val, (void __iomem *)((ha)->nx_pcibase + addr));
  44}
  45
  46int
  47qla8044_rd_direct(struct scsi_qla_host *vha,
  48        const uint32_t crb_reg)
  49{
  50        struct qla_hw_data *ha = vha->hw;
  51
  52        if (crb_reg < CRB_REG_INDEX_MAX)
  53                return qla8044_rd_reg(ha, qla8044_reg_tbl[crb_reg]);
  54        else
  55                return QLA_FUNCTION_FAILED;
  56}
  57
  58void
  59qla8044_wr_direct(struct scsi_qla_host *vha,
  60        const uint32_t crb_reg,
  61        const uint32_t value)
  62{
  63        struct qla_hw_data *ha = vha->hw;
  64
  65        if (crb_reg < CRB_REG_INDEX_MAX)
  66                qla8044_wr_reg(ha, qla8044_reg_tbl[crb_reg], value);
  67}
  68
  69static int
  70qla8044_set_win_base(scsi_qla_host_t *vha, uint32_t addr)
  71{
  72        uint32_t val;
  73        int ret_val = QLA_SUCCESS;
  74        struct qla_hw_data *ha = vha->hw;
  75
  76        qla8044_wr_reg(ha, QLA8044_CRB_WIN_FUNC(ha->portnum), addr);
  77        val = qla8044_rd_reg(ha, QLA8044_CRB_WIN_FUNC(ha->portnum));
  78
  79        if (val != addr) {
  80                ql_log(ql_log_warn, vha, 0xb087,
  81                    "%s: Failed to set register window : "
  82                    "addr written 0x%x, read 0x%x!\n",
  83                    __func__, addr, val);
  84                ret_val = QLA_FUNCTION_FAILED;
  85        }
  86        return ret_val;
  87}
  88
  89static int
  90qla8044_rd_reg_indirect(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data)
  91{
  92        int ret_val = QLA_SUCCESS;
  93        struct qla_hw_data *ha = vha->hw;
  94
  95        ret_val = qla8044_set_win_base(vha, addr);
  96        if (!ret_val)
  97                *data = qla8044_rd_reg(ha, QLA8044_WILDCARD);
  98        else
  99                ql_log(ql_log_warn, vha, 0xb088,
 100                    "%s: failed read of addr 0x%x!\n", __func__, addr);
 101        return ret_val;
 102}
 103
 104static int
 105qla8044_wr_reg_indirect(scsi_qla_host_t *vha, uint32_t addr, uint32_t data)
 106{
 107        int ret_val = QLA_SUCCESS;
 108        struct qla_hw_data *ha = vha->hw;
 109
 110        ret_val = qla8044_set_win_base(vha, addr);
 111        if (!ret_val)
 112                qla8044_wr_reg(ha, QLA8044_WILDCARD, data);
 113        else
 114                ql_log(ql_log_warn, vha, 0xb089,
 115                    "%s: failed wrt to addr 0x%x, data 0x%x\n",
 116                    __func__, addr, data);
 117        return ret_val;
 118}
 119
 120/*
 121 * qla8044_read_write_crb_reg - Read from raddr and write value to waddr.
 122 *
 123 * @ha : Pointer to adapter structure
 124 * @raddr : CRB address to read from
 125 * @waddr : CRB address to write to
 126 *
 127 */
 128static void
 129qla8044_read_write_crb_reg(struct scsi_qla_host *vha,
 130        uint32_t raddr, uint32_t waddr)
 131{
 132        uint32_t value;
 133
 134        qla8044_rd_reg_indirect(vha, raddr, &value);
 135        qla8044_wr_reg_indirect(vha, waddr, value);
 136}
 137
 138static int
 139qla8044_poll_wait_for_ready(struct scsi_qla_host *vha, uint32_t addr1,
 140        uint32_t mask)
 141{
 142        unsigned long timeout;
 143        uint32_t temp = 0;
 144
 145        /* jiffies after 100ms */
 146        timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
 147        do {
 148                qla8044_rd_reg_indirect(vha, addr1, &temp);
 149                if ((temp & mask) != 0)
 150                        break;
 151                if (time_after_eq(jiffies, timeout)) {
 152                        ql_log(ql_log_warn, vha, 0xb151,
 153                                "Error in processing rdmdio entry\n");
 154                        return -1;
 155                }
 156        } while (1);
 157
 158        return 0;
 159}
 160
 161static uint32_t
 162qla8044_ipmdio_rd_reg(struct scsi_qla_host *vha,
 163        uint32_t addr1, uint32_t addr3, uint32_t mask, uint32_t addr)
 164{
 165        uint32_t temp;
 166        int ret = 0;
 167
 168        ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
 169        if (ret == -1)
 170                return -1;
 171
 172        temp = (0x40000000 | addr);
 173        qla8044_wr_reg_indirect(vha, addr1, temp);
 174
 175        ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
 176        if (ret == -1)
 177                return 0;
 178
 179        qla8044_rd_reg_indirect(vha, addr3, &ret);
 180
 181        return ret;
 182}
 183
 184
 185static int
 186qla8044_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *vha,
 187        uint32_t addr1, uint32_t addr2, uint32_t addr3, uint32_t mask)
 188{
 189        unsigned long timeout;
 190        uint32_t temp;
 191
 192        /* jiffies after 100 msecs */
 193        timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
 194        do {
 195                temp = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr2);
 196                if ((temp & 0x1) != 1)
 197                        break;
 198                if (time_after_eq(jiffies, timeout)) {
 199                        ql_log(ql_log_warn, vha, 0xb152,
 200                            "Error in processing mdiobus idle\n");
 201                        return -1;
 202                }
 203        } while (1);
 204
 205        return 0;
 206}
 207
 208static int
 209qla8044_ipmdio_wr_reg(struct scsi_qla_host *vha, uint32_t addr1,
 210        uint32_t addr3, uint32_t mask, uint32_t addr, uint32_t value)
 211{
 212        int ret = 0;
 213
 214        ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
 215        if (ret == -1)
 216                return -1;
 217
 218        qla8044_wr_reg_indirect(vha, addr3, value);
 219        qla8044_wr_reg_indirect(vha, addr1, addr);
 220
 221        ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
 222        if (ret == -1)
 223                return -1;
 224
 225        return 0;
 226}
 227/*
 228 * qla8044_rmw_crb_reg - Read value from raddr, AND with test_mask,
 229 * Shift Left,Right/OR/XOR with values RMW header and write value to waddr.
 230 *
 231 * @vha : Pointer to adapter structure
 232 * @raddr : CRB address to read from
 233 * @waddr : CRB address to write to
 234 * @p_rmw_hdr : header with shift/or/xor values.
 235 *
 236 */
 237static void
 238qla8044_rmw_crb_reg(struct scsi_qla_host *vha,
 239        uint32_t raddr, uint32_t waddr, struct qla8044_rmw *p_rmw_hdr)
 240{
 241        uint32_t value;
 242
 243        if (p_rmw_hdr->index_a)
 244                value = vha->reset_tmplt.array[p_rmw_hdr->index_a];
 245        else
 246                qla8044_rd_reg_indirect(vha, raddr, &value);
 247        value &= p_rmw_hdr->test_mask;
 248        value <<= p_rmw_hdr->shl;
 249        value >>= p_rmw_hdr->shr;
 250        value |= p_rmw_hdr->or_value;
 251        value ^= p_rmw_hdr->xor_value;
 252        qla8044_wr_reg_indirect(vha, waddr, value);
 253        return;
 254}
 255
 256static inline void
 257qla8044_set_qsnt_ready(struct scsi_qla_host *vha)
 258{
 259        uint32_t qsnt_state;
 260        struct qla_hw_data *ha = vha->hw;
 261
 262        qsnt_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
 263        qsnt_state |= (1 << ha->portnum);
 264        qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, qsnt_state);
 265        ql_log(ql_log_info, vha, 0xb08e, "%s(%ld): qsnt_state: 0x%08x\n",
 266             __func__, vha->host_no, qsnt_state);
 267}
 268
 269void
 270qla8044_clear_qsnt_ready(struct scsi_qla_host *vha)
 271{
 272        uint32_t qsnt_state;
 273        struct qla_hw_data *ha = vha->hw;
 274
 275        qsnt_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
 276        qsnt_state &= ~(1 << ha->portnum);
 277        qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, qsnt_state);
 278        ql_log(ql_log_info, vha, 0xb08f, "%s(%ld): qsnt_state: 0x%08x\n",
 279            __func__, vha->host_no, qsnt_state);
 280}
 281
 282/**
 283 * qla8044_lock_recovery - Recovers the idc_lock.
 284 * @vha : Pointer to adapter structure
 285 *
 286 * Lock Recovery Register
 287 * 5-2  Lock recovery owner: Function ID of driver doing lock recovery,
 288 *      valid if bits 1..0 are set by driver doing lock recovery.
 289 * 1-0  1 - Driver intends to force unlock the IDC lock.
 290 *      2 - Driver is moving forward to unlock the IDC lock. Driver clears
 291 *          this field after force unlocking the IDC lock.
 292 *
 293 * Lock Recovery process
 294 * a. Read the IDC_LOCK_RECOVERY register. If the value in bits 1..0 is
 295 *    greater than 0, then wait for the other driver to unlock otherwise
 296 *    move to the next step.
 297 * b. Indicate intent to force-unlock by writing 1h to the IDC_LOCK_RECOVERY
 298 *    register bits 1..0 and also set the function# in bits 5..2.
 299 * c. Read the IDC_LOCK_RECOVERY register again after a delay of 200ms.
 300 *    Wait for the other driver to perform lock recovery if the function
 301 *    number in bits 5..2 has changed, otherwise move to the next step.
 302 * d. Write a value of 2h to the IDC_LOCK_RECOVERY register bits 1..0
 303 *    leaving your function# in bits 5..2.
 304 * e. Force unlock using the DRIVER_UNLOCK register and immediately clear
 305 *    the IDC_LOCK_RECOVERY bits 5..0 by writing 0.
 306 **/
 307static int
 308qla8044_lock_recovery(struct scsi_qla_host *vha)
 309{
 310        uint32_t lock = 0, lockid;
 311        struct qla_hw_data *ha = vha->hw;
 312
 313        lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCKRECOVERY);
 314
 315        /* Check for other Recovery in progress, go wait */
 316        if ((lockid & IDC_LOCK_RECOVERY_STATE_MASK) != 0)
 317                return QLA_FUNCTION_FAILED;
 318
 319        /* Intent to Recover */
 320        qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY,
 321            (ha->portnum <<
 322             IDC_LOCK_RECOVERY_STATE_SHIFT_BITS) | INTENT_TO_RECOVER);
 323        msleep(200);
 324
 325        /* Check Intent to Recover is advertised */
 326        lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCKRECOVERY);
 327        if ((lockid & IDC_LOCK_RECOVERY_OWNER_MASK) != (ha->portnum <<
 328            IDC_LOCK_RECOVERY_STATE_SHIFT_BITS))
 329                return QLA_FUNCTION_FAILED;
 330
 331        ql_dbg(ql_dbg_p3p, vha, 0xb08B, "%s:%d: IDC Lock recovery initiated\n"
 332            , __func__, ha->portnum);
 333
 334        /* Proceed to Recover */
 335        qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY,
 336            (ha->portnum << IDC_LOCK_RECOVERY_STATE_SHIFT_BITS) |
 337            PROCEED_TO_RECOVER);
 338
 339        /* Force Unlock() */
 340        qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, 0xFF);
 341        qla8044_rd_reg(ha, QLA8044_DRV_UNLOCK);
 342
 343        /* Clear bits 0-5 in IDC_RECOVERY register*/
 344        qla8044_wr_reg(ha, QLA8044_DRV_LOCKRECOVERY, 0);
 345
 346        /* Get lock() */
 347        lock = qla8044_rd_reg(ha, QLA8044_DRV_LOCK);
 348        if (lock) {
 349                lockid = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
 350                lockid = ((lockid + (1 << 8)) & ~0xFF) | ha->portnum;
 351                qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, lockid);
 352                return QLA_SUCCESS;
 353        } else
 354                return QLA_FUNCTION_FAILED;
 355}
 356
 357int
 358qla8044_idc_lock(struct qla_hw_data *ha)
 359{
 360        uint32_t ret_val = QLA_SUCCESS, timeout = 0, status = 0;
 361        uint32_t lock_id, lock_cnt, func_num, tmo_owner = 0, first_owner = 0;
 362        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 363
 364        while (status == 0) {
 365                /* acquire semaphore5 from PCI HW block */
 366                status = qla8044_rd_reg(ha, QLA8044_DRV_LOCK);
 367
 368                if (status) {
 369                        /* Increment Counter (8-31) and update func_num (0-7) on
 370                         * getting a successful lock  */
 371                        lock_id = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
 372                        lock_id = ((lock_id + (1 << 8)) & ~0xFF) | ha->portnum;
 373                        qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, lock_id);
 374                        break;
 375                }
 376
 377                if (timeout == 0)
 378                        first_owner = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
 379
 380                if (++timeout >=
 381                    (QLA8044_DRV_LOCK_TIMEOUT / QLA8044_DRV_LOCK_MSLEEP)) {
 382                        tmo_owner = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
 383                        func_num = tmo_owner & 0xFF;
 384                        lock_cnt = tmo_owner >> 8;
 385                        ql_log(ql_log_warn, vha, 0xb114,
 386                            "%s: Lock by func %d failed after 2s, lock held "
 387                            "by func %d, lock count %d, first_owner %d\n",
 388                            __func__, ha->portnum, func_num, lock_cnt,
 389                            (first_owner & 0xFF));
 390                        if (first_owner != tmo_owner) {
 391                                /* Some other driver got lock,
 392                                 * OR same driver got lock again (counter
 393                                 * value changed), when we were waiting for
 394                                 * lock. Retry for another 2 sec */
 395                                ql_dbg(ql_dbg_p3p, vha, 0xb115,
 396                                    "%s: %d: IDC lock failed\n",
 397                                    __func__, ha->portnum);
 398                                timeout = 0;
 399                        } else {
 400                                /* Same driver holding lock > 2sec.
 401                                 * Force Recovery */
 402                                if (qla8044_lock_recovery(vha) == QLA_SUCCESS) {
 403                                        /* Recovered and got lock */
 404                                        ret_val = QLA_SUCCESS;
 405                                        ql_dbg(ql_dbg_p3p, vha, 0xb116,
 406                                            "%s:IDC lock Recovery by %d"
 407                                            "successful...\n", __func__,
 408                                             ha->portnum);
 409                                }
 410                                /* Recovery Failed, some other function
 411                                 * has the lock, wait for 2secs
 412                                 * and retry
 413                                 */
 414                                ql_dbg(ql_dbg_p3p, vha, 0xb08a,
 415                                       "%s: IDC lock Recovery by %d "
 416                                       "failed, Retrying timeout\n", __func__,
 417                                       ha->portnum);
 418                                timeout = 0;
 419                        }
 420                }
 421                msleep(QLA8044_DRV_LOCK_MSLEEP);
 422        }
 423        return ret_val;
 424}
 425
 426void
 427qla8044_idc_unlock(struct qla_hw_data *ha)
 428{
 429        int id;
 430        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 431
 432        id = qla8044_rd_reg(ha, QLA8044_DRV_LOCK_ID);
 433
 434        if ((id & 0xFF) != ha->portnum) {
 435                ql_log(ql_log_warn, vha, 0xb118,
 436                    "%s: IDC Unlock by %d failed, lock owner is %d!\n",
 437                    __func__, ha->portnum, (id & 0xFF));
 438                return;
 439        }
 440
 441        /* Keep lock counter value, update the ha->func_num to 0xFF */
 442        qla8044_wr_reg(ha, QLA8044_DRV_LOCK_ID, (id | 0xFF));
 443        qla8044_rd_reg(ha, QLA8044_DRV_UNLOCK);
 444}
 445
 446/* 8044 Flash Lock/Unlock functions */
 447static int
 448qla8044_flash_lock(scsi_qla_host_t *vha)
 449{
 450        int lock_owner;
 451        int timeout = 0;
 452        uint32_t lock_status = 0;
 453        int ret_val = QLA_SUCCESS;
 454        struct qla_hw_data *ha = vha->hw;
 455
 456        while (lock_status == 0) {
 457                lock_status = qla8044_rd_reg(ha, QLA8044_FLASH_LOCK);
 458                if (lock_status)
 459                        break;
 460
 461                if (++timeout >= QLA8044_FLASH_LOCK_TIMEOUT / 20) {
 462                        lock_owner = qla8044_rd_reg(ha,
 463                            QLA8044_FLASH_LOCK_ID);
 464                        ql_log(ql_log_warn, vha, 0xb113,
 465                            "%s: Simultaneous flash access by following ports, active port = %d: accessing port = %d",
 466                            __func__, ha->portnum, lock_owner);
 467                        ret_val = QLA_FUNCTION_FAILED;
 468                        break;
 469                }
 470                msleep(20);
 471        }
 472        qla8044_wr_reg(ha, QLA8044_FLASH_LOCK_ID, ha->portnum);
 473        return ret_val;
 474}
 475
 476static void
 477qla8044_flash_unlock(scsi_qla_host_t *vha)
 478{
 479        struct qla_hw_data *ha = vha->hw;
 480
 481        /* Reading FLASH_UNLOCK register unlocks the Flash */
 482        qla8044_wr_reg(ha, QLA8044_FLASH_LOCK_ID, 0xFF);
 483        qla8044_rd_reg(ha, QLA8044_FLASH_UNLOCK);
 484}
 485
 486
 487static
 488void qla8044_flash_lock_recovery(struct scsi_qla_host *vha)
 489{
 490
 491        if (qla8044_flash_lock(vha)) {
 492                /* Someone else is holding the lock. */
 493                ql_log(ql_log_warn, vha, 0xb120, "Resetting flash_lock\n");
 494        }
 495
 496        /*
 497         * Either we got the lock, or someone
 498         * else died while holding it.
 499         * In either case, unlock.
 500         */
 501        qla8044_flash_unlock(vha);
 502}
 503
 504/*
 505 * Address and length are byte address
 506 */
 507static int
 508qla8044_read_flash_data(scsi_qla_host_t *vha,  uint8_t *p_data,
 509        uint32_t flash_addr, int u32_word_count)
 510{
 511        int i, ret_val = QLA_SUCCESS;
 512        uint32_t u32_word;
 513
 514        if (qla8044_flash_lock(vha) != QLA_SUCCESS) {
 515                ret_val = QLA_FUNCTION_FAILED;
 516                goto exit_lock_error;
 517        }
 518
 519        if (flash_addr & 0x03) {
 520                ql_log(ql_log_warn, vha, 0xb117,
 521                    "%s: Illegal addr = 0x%x\n", __func__, flash_addr);
 522                ret_val = QLA_FUNCTION_FAILED;
 523                goto exit_flash_read;
 524        }
 525
 526        for (i = 0; i < u32_word_count; i++) {
 527                if (qla8044_wr_reg_indirect(vha, QLA8044_FLASH_DIRECT_WINDOW,
 528                    (flash_addr & 0xFFFF0000))) {
 529                        ql_log(ql_log_warn, vha, 0xb119,
 530                            "%s: failed to write addr 0x%x to "
 531                            "FLASH_DIRECT_WINDOW\n! ",
 532                            __func__, flash_addr);
 533                        ret_val = QLA_FUNCTION_FAILED;
 534                        goto exit_flash_read;
 535                }
 536
 537                ret_val = qla8044_rd_reg_indirect(vha,
 538                    QLA8044_FLASH_DIRECT_DATA(flash_addr),
 539                    &u32_word);
 540                if (ret_val != QLA_SUCCESS) {
 541                        ql_log(ql_log_warn, vha, 0xb08c,
 542                            "%s: failed to read addr 0x%x!\n",
 543                            __func__, flash_addr);
 544                        goto exit_flash_read;
 545                }
 546
 547                *(uint32_t *)p_data = u32_word;
 548                p_data = p_data + 4;
 549                flash_addr = flash_addr + 4;
 550        }
 551
 552exit_flash_read:
 553        qla8044_flash_unlock(vha);
 554
 555exit_lock_error:
 556        return ret_val;
 557}
 558
 559/*
 560 * Address and length are byte address
 561 */
 562void *
 563qla8044_read_optrom_data(struct scsi_qla_host *vha, void *buf,
 564        uint32_t offset, uint32_t length)
 565{
 566        scsi_block_requests(vha->host);
 567        if (qla8044_read_flash_data(vha, buf, offset, length / 4)
 568            != QLA_SUCCESS) {
 569                ql_log(ql_log_warn, vha,  0xb08d,
 570                    "%s: Failed to read from flash\n",
 571                    __func__);
 572        }
 573        scsi_unblock_requests(vha->host);
 574        return buf;
 575}
 576
 577static inline int
 578qla8044_need_reset(struct scsi_qla_host *vha)
 579{
 580        uint32_t drv_state, drv_active;
 581        int rval;
 582        struct qla_hw_data *ha = vha->hw;
 583
 584        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
 585        drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
 586
 587        rval = drv_state & (1 << ha->portnum);
 588
 589        if (ha->flags.eeh_busy && drv_active)
 590                rval = 1;
 591        return rval;
 592}
 593
 594/*
 595 * qla8044_write_list - Write the value (p_entry->arg2) to address specified
 596 * by p_entry->arg1 for all entries in header with delay of p_hdr->delay between
 597 * entries.
 598 *
 599 * @vha : Pointer to adapter structure
 600 * @p_hdr : reset_entry header for WRITE_LIST opcode.
 601 *
 602 */
 603static void
 604qla8044_write_list(struct scsi_qla_host *vha,
 605        struct qla8044_reset_entry_hdr *p_hdr)
 606{
 607        struct qla8044_entry *p_entry;
 608        uint32_t i;
 609
 610        p_entry = (struct qla8044_entry *)((char *)p_hdr +
 611            sizeof(struct qla8044_reset_entry_hdr));
 612
 613        for (i = 0; i < p_hdr->count; i++, p_entry++) {
 614                qla8044_wr_reg_indirect(vha, p_entry->arg1, p_entry->arg2);
 615                if (p_hdr->delay)
 616                        udelay((uint32_t)(p_hdr->delay));
 617        }
 618}
 619
 620/*
 621 * qla8044_read_write_list - Read from address specified by p_entry->arg1,
 622 * write value read to address specified by p_entry->arg2, for all entries in
 623 * header with delay of p_hdr->delay between entries.
 624 *
 625 * @vha : Pointer to adapter structure
 626 * @p_hdr : reset_entry header for READ_WRITE_LIST opcode.
 627 *
 628 */
 629static void
 630qla8044_read_write_list(struct scsi_qla_host *vha,
 631        struct qla8044_reset_entry_hdr *p_hdr)
 632{
 633        struct qla8044_entry *p_entry;
 634        uint32_t i;
 635
 636        p_entry = (struct qla8044_entry *)((char *)p_hdr +
 637            sizeof(struct qla8044_reset_entry_hdr));
 638
 639        for (i = 0; i < p_hdr->count; i++, p_entry++) {
 640                qla8044_read_write_crb_reg(vha, p_entry->arg1,
 641                    p_entry->arg2);
 642                if (p_hdr->delay)
 643                        udelay((uint32_t)(p_hdr->delay));
 644        }
 645}
 646
 647/*
 648 * qla8044_poll_reg - Poll the given CRB addr for duration msecs till
 649 * value read ANDed with test_mask is equal to test_result.
 650 *
 651 * @ha : Pointer to adapter structure
 652 * @addr : CRB register address
 653 * @duration : Poll for total of "duration" msecs
 654 * @test_mask : Mask value read with "test_mask"
 655 * @test_result : Compare (value&test_mask) with test_result.
 656 *
 657 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
 658 */
 659static int
 660qla8044_poll_reg(struct scsi_qla_host *vha, uint32_t addr,
 661        int duration, uint32_t test_mask, uint32_t test_result)
 662{
 663        uint32_t value = 0;
 664        int timeout_error;
 665        uint8_t retries;
 666        int ret_val = QLA_SUCCESS;
 667
 668        ret_val = qla8044_rd_reg_indirect(vha, addr, &value);
 669        if (ret_val == QLA_FUNCTION_FAILED) {
 670                timeout_error = 1;
 671                goto exit_poll_reg;
 672        }
 673
 674        /* poll every 1/10 of the total duration */
 675        retries = duration/10;
 676
 677        do {
 678                if ((value & test_mask) != test_result) {
 679                        timeout_error = 1;
 680                        msleep(duration/10);
 681                        ret_val = qla8044_rd_reg_indirect(vha, addr, &value);
 682                        if (ret_val == QLA_FUNCTION_FAILED) {
 683                                timeout_error = 1;
 684                                goto exit_poll_reg;
 685                        }
 686                } else {
 687                        timeout_error = 0;
 688                        break;
 689                }
 690        } while (retries--);
 691
 692exit_poll_reg:
 693        if (timeout_error) {
 694                vha->reset_tmplt.seq_error++;
 695                ql_log(ql_log_fatal, vha, 0xb090,
 696                    "%s: Poll Failed: 0x%08x 0x%08x 0x%08x\n",
 697                    __func__, value, test_mask, test_result);
 698        }
 699
 700        return timeout_error;
 701}
 702
 703/*
 704 * qla8044_poll_list - For all entries in the POLL_LIST header, poll read CRB
 705 * register specified by p_entry->arg1 and compare (value AND test_mask) with
 706 * test_result to validate it. Wait for p_hdr->delay between processing entries.
 707 *
 708 * @ha : Pointer to adapter structure
 709 * @p_hdr : reset_entry header for POLL_LIST opcode.
 710 *
 711 */
 712static void
 713qla8044_poll_list(struct scsi_qla_host *vha,
 714        struct qla8044_reset_entry_hdr *p_hdr)
 715{
 716        long delay;
 717        struct qla8044_entry *p_entry;
 718        struct qla8044_poll *p_poll;
 719        uint32_t i;
 720        uint32_t value;
 721
 722        p_poll = (struct qla8044_poll *)
 723                ((char *)p_hdr + sizeof(struct qla8044_reset_entry_hdr));
 724
 725        /* Entries start after 8 byte qla8044_poll, poll header contains
 726         * the test_mask, test_value.
 727         */
 728        p_entry = (struct qla8044_entry *)((char *)p_poll +
 729            sizeof(struct qla8044_poll));
 730
 731        delay = (long)p_hdr->delay;
 732
 733        if (!delay) {
 734                for (i = 0; i < p_hdr->count; i++, p_entry++)
 735                        qla8044_poll_reg(vha, p_entry->arg1,
 736                            delay, p_poll->test_mask, p_poll->test_value);
 737        } else {
 738                for (i = 0; i < p_hdr->count; i++, p_entry++) {
 739                        if (delay) {
 740                                if (qla8044_poll_reg(vha,
 741                                    p_entry->arg1, delay,
 742                                    p_poll->test_mask,
 743                                    p_poll->test_value)) {
 744                                        /*If
 745                                        * (data_read&test_mask != test_value)
 746                                        * read TIMEOUT_ADDR (arg1) and
 747                                        * ADDR (arg2) registers
 748                                        */
 749                                        qla8044_rd_reg_indirect(vha,
 750                                            p_entry->arg1, &value);
 751                                        qla8044_rd_reg_indirect(vha,
 752                                            p_entry->arg2, &value);
 753                                }
 754                        }
 755                }
 756        }
 757}
 758
 759/*
 760 * qla8044_poll_write_list - Write dr_value, ar_value to dr_addr/ar_addr,
 761 * read ar_addr, if (value& test_mask != test_mask) re-read till timeout
 762 * expires.
 763 *
 764 * @vha : Pointer to adapter structure
 765 * @p_hdr : reset entry header for POLL_WRITE_LIST opcode.
 766 *
 767 */
 768static void
 769qla8044_poll_write_list(struct scsi_qla_host *vha,
 770        struct qla8044_reset_entry_hdr *p_hdr)
 771{
 772        long delay;
 773        struct qla8044_quad_entry *p_entry;
 774        struct qla8044_poll *p_poll;
 775        uint32_t i;
 776
 777        p_poll = (struct qla8044_poll *)((char *)p_hdr +
 778            sizeof(struct qla8044_reset_entry_hdr));
 779
 780        p_entry = (struct qla8044_quad_entry *)((char *)p_poll +
 781            sizeof(struct qla8044_poll));
 782
 783        delay = (long)p_hdr->delay;
 784
 785        for (i = 0; i < p_hdr->count; i++, p_entry++) {
 786                qla8044_wr_reg_indirect(vha,
 787                    p_entry->dr_addr, p_entry->dr_value);
 788                qla8044_wr_reg_indirect(vha,
 789                    p_entry->ar_addr, p_entry->ar_value);
 790                if (delay) {
 791                        if (qla8044_poll_reg(vha,
 792                            p_entry->ar_addr, delay,
 793                            p_poll->test_mask,
 794                            p_poll->test_value)) {
 795                                ql_dbg(ql_dbg_p3p, vha, 0xb091,
 796                                    "%s: Timeout Error: poll list, ",
 797                                    __func__);
 798                                ql_dbg(ql_dbg_p3p, vha, 0xb092,
 799                                    "item_num %d, entry_num %d\n", i,
 800                                    vha->reset_tmplt.seq_index);
 801                        }
 802                }
 803        }
 804}
 805
 806/*
 807 * qla8044_read_modify_write - Read value from p_entry->arg1, modify the
 808 * value, write value to p_entry->arg2. Process entries with p_hdr->delay
 809 * between entries.
 810 *
 811 * @vha : Pointer to adapter structure
 812 * @p_hdr : header with shift/or/xor values.
 813 *
 814 */
 815static void
 816qla8044_read_modify_write(struct scsi_qla_host *vha,
 817        struct qla8044_reset_entry_hdr *p_hdr)
 818{
 819        struct qla8044_entry *p_entry;
 820        struct qla8044_rmw *p_rmw_hdr;
 821        uint32_t i;
 822
 823        p_rmw_hdr = (struct qla8044_rmw *)((char *)p_hdr +
 824            sizeof(struct qla8044_reset_entry_hdr));
 825
 826        p_entry = (struct qla8044_entry *)((char *)p_rmw_hdr +
 827            sizeof(struct qla8044_rmw));
 828
 829        for (i = 0; i < p_hdr->count; i++, p_entry++) {
 830                qla8044_rmw_crb_reg(vha, p_entry->arg1,
 831                    p_entry->arg2, p_rmw_hdr);
 832                if (p_hdr->delay)
 833                        udelay((uint32_t)(p_hdr->delay));
 834        }
 835}
 836
 837/*
 838 * qla8044_pause - Wait for p_hdr->delay msecs, called between processing
 839 * two entries of a sequence.
 840 *
 841 * @vha : Pointer to adapter structure
 842 * @p_hdr : Common reset entry header.
 843 *
 844 */
 845static
 846void qla8044_pause(struct scsi_qla_host *vha,
 847        struct qla8044_reset_entry_hdr *p_hdr)
 848{
 849        if (p_hdr->delay)
 850                mdelay((uint32_t)((long)p_hdr->delay));
 851}
 852
 853/*
 854 * qla8044_template_end - Indicates end of reset sequence processing.
 855 *
 856 * @vha : Pointer to adapter structure
 857 * @p_hdr : Common reset entry header.
 858 *
 859 */
 860static void
 861qla8044_template_end(struct scsi_qla_host *vha,
 862        struct qla8044_reset_entry_hdr *p_hdr)
 863{
 864        vha->reset_tmplt.template_end = 1;
 865
 866        if (vha->reset_tmplt.seq_error == 0) {
 867                ql_dbg(ql_dbg_p3p, vha, 0xb093,
 868                    "%s: Reset sequence completed SUCCESSFULLY.\n", __func__);
 869        } else {
 870                ql_log(ql_log_fatal, vha, 0xb094,
 871                    "%s: Reset sequence completed with some timeout "
 872                    "errors.\n", __func__);
 873        }
 874}
 875
 876/*
 877 * qla8044_poll_read_list - Write ar_value to ar_addr register, read ar_addr,
 878 * if (value & test_mask != test_value) re-read till timeout value expires,
 879 * read dr_addr register and assign to reset_tmplt.array.
 880 *
 881 * @vha : Pointer to adapter structure
 882 * @p_hdr : Common reset entry header.
 883 *
 884 */
 885static void
 886qla8044_poll_read_list(struct scsi_qla_host *vha,
 887        struct qla8044_reset_entry_hdr *p_hdr)
 888{
 889        long delay;
 890        int index;
 891        struct qla8044_quad_entry *p_entry;
 892        struct qla8044_poll *p_poll;
 893        uint32_t i;
 894        uint32_t value;
 895
 896        p_poll = (struct qla8044_poll *)
 897                ((char *)p_hdr + sizeof(struct qla8044_reset_entry_hdr));
 898
 899        p_entry = (struct qla8044_quad_entry *)
 900                ((char *)p_poll + sizeof(struct qla8044_poll));
 901
 902        delay = (long)p_hdr->delay;
 903
 904        for (i = 0; i < p_hdr->count; i++, p_entry++) {
 905                qla8044_wr_reg_indirect(vha, p_entry->ar_addr,
 906                    p_entry->ar_value);
 907                if (delay) {
 908                        if (qla8044_poll_reg(vha, p_entry->ar_addr, delay,
 909                            p_poll->test_mask, p_poll->test_value)) {
 910                                ql_dbg(ql_dbg_p3p, vha, 0xb095,
 911                                    "%s: Timeout Error: poll "
 912                                    "list, ", __func__);
 913                                ql_dbg(ql_dbg_p3p, vha, 0xb096,
 914                                    "Item_num %d, "
 915                                    "entry_num %d\n", i,
 916                                    vha->reset_tmplt.seq_index);
 917                        } else {
 918                                index = vha->reset_tmplt.array_index;
 919                                qla8044_rd_reg_indirect(vha,
 920                                    p_entry->dr_addr, &value);
 921                                vha->reset_tmplt.array[index++] = value;
 922                                if (index == QLA8044_MAX_RESET_SEQ_ENTRIES)
 923                                        vha->reset_tmplt.array_index = 1;
 924                        }
 925                }
 926        }
 927}
 928
 929/*
 930 * qla8031_process_reset_template - Process all entries in reset template
 931 * till entry with SEQ_END opcode, which indicates end of the reset template
 932 * processing. Each entry has a Reset Entry header, entry opcode/command, with
 933 * size of the entry, number of entries in sub-sequence and delay in microsecs
 934 * or timeout in millisecs.
 935 *
 936 * @ha : Pointer to adapter structure
 937 * @p_buff : Common reset entry header.
 938 *
 939 */
 940static void
 941qla8044_process_reset_template(struct scsi_qla_host *vha,
 942        char *p_buff)
 943{
 944        int index, entries;
 945        struct qla8044_reset_entry_hdr *p_hdr;
 946        char *p_entry = p_buff;
 947
 948        vha->reset_tmplt.seq_end = 0;
 949        vha->reset_tmplt.template_end = 0;
 950        entries = vha->reset_tmplt.hdr->entries;
 951        index = vha->reset_tmplt.seq_index;
 952
 953        for (; (!vha->reset_tmplt.seq_end) && (index  < entries); index++) {
 954                p_hdr = (struct qla8044_reset_entry_hdr *)p_entry;
 955                switch (p_hdr->cmd) {
 956                case OPCODE_NOP:
 957                        break;
 958                case OPCODE_WRITE_LIST:
 959                        qla8044_write_list(vha, p_hdr);
 960                        break;
 961                case OPCODE_READ_WRITE_LIST:
 962                        qla8044_read_write_list(vha, p_hdr);
 963                        break;
 964                case OPCODE_POLL_LIST:
 965                        qla8044_poll_list(vha, p_hdr);
 966                        break;
 967                case OPCODE_POLL_WRITE_LIST:
 968                        qla8044_poll_write_list(vha, p_hdr);
 969                        break;
 970                case OPCODE_READ_MODIFY_WRITE:
 971                        qla8044_read_modify_write(vha, p_hdr);
 972                        break;
 973                case OPCODE_SEQ_PAUSE:
 974                        qla8044_pause(vha, p_hdr);
 975                        break;
 976                case OPCODE_SEQ_END:
 977                        vha->reset_tmplt.seq_end = 1;
 978                        break;
 979                case OPCODE_TMPL_END:
 980                        qla8044_template_end(vha, p_hdr);
 981                        break;
 982                case OPCODE_POLL_READ_LIST:
 983                        qla8044_poll_read_list(vha, p_hdr);
 984                        break;
 985                default:
 986                        ql_log(ql_log_fatal, vha, 0xb097,
 987                            "%s: Unknown command ==> 0x%04x on "
 988                            "entry = %d\n", __func__, p_hdr->cmd, index);
 989                        break;
 990                }
 991                /*
 992                 *Set pointer to next entry in the sequence.
 993                */
 994                p_entry += p_hdr->size;
 995        }
 996        vha->reset_tmplt.seq_index = index;
 997}
 998
 999static void
1000qla8044_process_init_seq(struct scsi_qla_host *vha)
1001{
1002        qla8044_process_reset_template(vha,
1003            vha->reset_tmplt.init_offset);
1004        if (vha->reset_tmplt.seq_end != 1)
1005                ql_log(ql_log_fatal, vha, 0xb098,
1006                    "%s: Abrupt INIT Sub-Sequence end.\n",
1007                    __func__);
1008}
1009
1010static void
1011qla8044_process_stop_seq(struct scsi_qla_host *vha)
1012{
1013        vha->reset_tmplt.seq_index = 0;
1014        qla8044_process_reset_template(vha, vha->reset_tmplt.stop_offset);
1015        if (vha->reset_tmplt.seq_end != 1)
1016                ql_log(ql_log_fatal, vha, 0xb099,
1017                    "%s: Abrupt STOP Sub-Sequence end.\n", __func__);
1018}
1019
1020static void
1021qla8044_process_start_seq(struct scsi_qla_host *vha)
1022{
1023        qla8044_process_reset_template(vha, vha->reset_tmplt.start_offset);
1024        if (vha->reset_tmplt.template_end != 1)
1025                ql_log(ql_log_fatal, vha, 0xb09a,
1026                    "%s: Abrupt START Sub-Sequence end.\n",
1027                    __func__);
1028}
1029
1030static int
1031qla8044_lockless_flash_read_u32(struct scsi_qla_host *vha,
1032        uint32_t flash_addr, uint8_t *p_data, int u32_word_count)
1033{
1034        uint32_t i;
1035        uint32_t u32_word;
1036        uint32_t flash_offset;
1037        uint32_t addr = flash_addr;
1038        int ret_val = QLA_SUCCESS;
1039
1040        flash_offset = addr & (QLA8044_FLASH_SECTOR_SIZE - 1);
1041
1042        if (addr & 0x3) {
1043                ql_log(ql_log_fatal, vha, 0xb09b, "%s: Illegal addr = 0x%x\n",
1044                    __func__, addr);
1045                ret_val = QLA_FUNCTION_FAILED;
1046                goto exit_lockless_read;
1047        }
1048
1049        ret_val = qla8044_wr_reg_indirect(vha,
1050            QLA8044_FLASH_DIRECT_WINDOW, (addr));
1051
1052        if (ret_val != QLA_SUCCESS) {
1053                ql_log(ql_log_fatal, vha, 0xb09c,
1054                    "%s: failed to write addr 0x%x to FLASH_DIRECT_WINDOW!\n",
1055                    __func__, addr);
1056                goto exit_lockless_read;
1057        }
1058
1059        /* Check if data is spread across multiple sectors  */
1060        if ((flash_offset + (u32_word_count * sizeof(uint32_t))) >
1061            (QLA8044_FLASH_SECTOR_SIZE - 1)) {
1062                /* Multi sector read */
1063                for (i = 0; i < u32_word_count; i++) {
1064                        ret_val = qla8044_rd_reg_indirect(vha,
1065                            QLA8044_FLASH_DIRECT_DATA(addr), &u32_word);
1066                        if (ret_val != QLA_SUCCESS) {
1067                                ql_log(ql_log_fatal, vha, 0xb09d,
1068                                    "%s: failed to read addr 0x%x!\n",
1069                                    __func__, addr);
1070                                goto exit_lockless_read;
1071                        }
1072                        *(uint32_t *)p_data  = u32_word;
1073                        p_data = p_data + 4;
1074                        addr = addr + 4;
1075                        flash_offset = flash_offset + 4;
1076                        if (flash_offset > (QLA8044_FLASH_SECTOR_SIZE - 1)) {
1077                                /* This write is needed once for each sector */
1078                                ret_val = qla8044_wr_reg_indirect(vha,
1079                                    QLA8044_FLASH_DIRECT_WINDOW, (addr));
1080                                if (ret_val != QLA_SUCCESS) {
1081                                        ql_log(ql_log_fatal, vha, 0xb09f,
1082                                            "%s: failed to write addr "
1083                                            "0x%x to FLASH_DIRECT_WINDOW!\n",
1084                                            __func__, addr);
1085                                        goto exit_lockless_read;
1086                                }
1087                                flash_offset = 0;
1088                        }
1089                }
1090        } else {
1091                /* Single sector read */
1092                for (i = 0; i < u32_word_count; i++) {
1093                        ret_val = qla8044_rd_reg_indirect(vha,
1094                            QLA8044_FLASH_DIRECT_DATA(addr), &u32_word);
1095                        if (ret_val != QLA_SUCCESS) {
1096                                ql_log(ql_log_fatal, vha, 0xb0a0,
1097                                    "%s: failed to read addr 0x%x!\n",
1098                                    __func__, addr);
1099                                goto exit_lockless_read;
1100                        }
1101                        *(uint32_t *)p_data = u32_word;
1102                        p_data = p_data + 4;
1103                        addr = addr + 4;
1104                }
1105        }
1106
1107exit_lockless_read:
1108        return ret_val;
1109}
1110
1111/*
1112 * qla8044_ms_mem_write_128b - Writes data to MS/off-chip memory
1113 *
1114 * @vha : Pointer to adapter structure
1115 * addr : Flash address to write to
1116 * data : Data to be written
1117 * count : word_count to be written
1118 *
1119 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
1120 */
1121static int
1122qla8044_ms_mem_write_128b(struct scsi_qla_host *vha,
1123        uint64_t addr, uint32_t *data, uint32_t count)
1124{
1125        int i, j, ret_val = QLA_SUCCESS;
1126        uint32_t agt_ctrl;
1127        unsigned long flags;
1128        struct qla_hw_data *ha = vha->hw;
1129
1130        /* Only 128-bit aligned access */
1131        if (addr & 0xF) {
1132                ret_val = QLA_FUNCTION_FAILED;
1133                goto exit_ms_mem_write;
1134        }
1135        write_lock_irqsave(&ha->hw_lock, flags);
1136
1137        /* Write address */
1138        ret_val = qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_HI, 0);
1139        if (ret_val == QLA_FUNCTION_FAILED) {
1140                ql_log(ql_log_fatal, vha, 0xb0a1,
1141                    "%s: write to AGT_ADDR_HI failed!\n", __func__);
1142                goto exit_ms_mem_write_unlock;
1143        }
1144
1145        for (i = 0; i < count; i++, addr += 16) {
1146                if (!((addr_in_range(addr, QLA8044_ADDR_QDR_NET,
1147                    QLA8044_ADDR_QDR_NET_MAX)) ||
1148                    (addr_in_range(addr, QLA8044_ADDR_DDR_NET,
1149                        QLA8044_ADDR_DDR_NET_MAX)))) {
1150                        ret_val = QLA_FUNCTION_FAILED;
1151                        goto exit_ms_mem_write_unlock;
1152                }
1153
1154                ret_val = qla8044_wr_reg_indirect(vha,
1155                    MD_MIU_TEST_AGT_ADDR_LO, addr);
1156
1157                /* Write data */
1158                ret_val += qla8044_wr_reg_indirect(vha,
1159                    MD_MIU_TEST_AGT_WRDATA_LO, *data++);
1160                ret_val += qla8044_wr_reg_indirect(vha,
1161                    MD_MIU_TEST_AGT_WRDATA_HI, *data++);
1162                ret_val += qla8044_wr_reg_indirect(vha,
1163                    MD_MIU_TEST_AGT_WRDATA_ULO, *data++);
1164                ret_val += qla8044_wr_reg_indirect(vha,
1165                    MD_MIU_TEST_AGT_WRDATA_UHI, *data++);
1166                if (ret_val == QLA_FUNCTION_FAILED) {
1167                        ql_log(ql_log_fatal, vha, 0xb0a2,
1168                            "%s: write to AGT_WRDATA failed!\n",
1169                            __func__);
1170                        goto exit_ms_mem_write_unlock;
1171                }
1172
1173                /* Check write status */
1174                ret_val = qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
1175                    MIU_TA_CTL_WRITE_ENABLE);
1176                ret_val += qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
1177                    MIU_TA_CTL_WRITE_START);
1178                if (ret_val == QLA_FUNCTION_FAILED) {
1179                        ql_log(ql_log_fatal, vha, 0xb0a3,
1180                            "%s: write to AGT_CTRL failed!\n", __func__);
1181                        goto exit_ms_mem_write_unlock;
1182                }
1183
1184                for (j = 0; j < MAX_CTL_CHECK; j++) {
1185                        ret_val = qla8044_rd_reg_indirect(vha,
1186                            MD_MIU_TEST_AGT_CTRL, &agt_ctrl);
1187                        if (ret_val == QLA_FUNCTION_FAILED) {
1188                                ql_log(ql_log_fatal, vha, 0xb0a4,
1189                                    "%s: failed to read "
1190                                    "MD_MIU_TEST_AGT_CTRL!\n", __func__);
1191                                goto exit_ms_mem_write_unlock;
1192                        }
1193                        if ((agt_ctrl & MIU_TA_CTL_BUSY) == 0)
1194                                break;
1195                }
1196
1197                /* Status check failed */
1198                if (j >= MAX_CTL_CHECK) {
1199                        ql_log(ql_log_fatal, vha, 0xb0a5,
1200                            "%s: MS memory write failed!\n",
1201                           __func__);
1202                        ret_val = QLA_FUNCTION_FAILED;
1203                        goto exit_ms_mem_write_unlock;
1204                }
1205        }
1206
1207exit_ms_mem_write_unlock:
1208        write_unlock_irqrestore(&ha->hw_lock, flags);
1209
1210exit_ms_mem_write:
1211        return ret_val;
1212}
1213
1214static int
1215qla8044_copy_bootloader(struct scsi_qla_host *vha)
1216{
1217        uint8_t *p_cache;
1218        uint32_t src, count, size;
1219        uint64_t dest;
1220        int ret_val = QLA_SUCCESS;
1221        struct qla_hw_data *ha = vha->hw;
1222
1223        src = QLA8044_BOOTLOADER_FLASH_ADDR;
1224        dest = qla8044_rd_reg(ha, QLA8044_BOOTLOADER_ADDR);
1225        size = qla8044_rd_reg(ha, QLA8044_BOOTLOADER_SIZE);
1226
1227        /* 128 bit alignment check */
1228        if (size & 0xF)
1229                size = (size + 16) & ~0xF;
1230
1231        /* 16 byte count */
1232        count = size/16;
1233
1234        p_cache = vmalloc(size);
1235        if (p_cache == NULL) {
1236                ql_log(ql_log_fatal, vha, 0xb0a6,
1237                    "%s: Failed to allocate memory for "
1238                    "boot loader cache\n", __func__);
1239                ret_val = QLA_FUNCTION_FAILED;
1240                goto exit_copy_bootloader;
1241        }
1242
1243        ret_val = qla8044_lockless_flash_read_u32(vha, src,
1244            p_cache, size/sizeof(uint32_t));
1245        if (ret_val == QLA_FUNCTION_FAILED) {
1246                ql_log(ql_log_fatal, vha, 0xb0a7,
1247                    "%s: Error reading F/W from flash!!!\n", __func__);
1248                goto exit_copy_error;
1249        }
1250        ql_dbg(ql_dbg_p3p, vha, 0xb0a8, "%s: Read F/W from flash!\n",
1251            __func__);
1252
1253        /* 128 bit/16 byte write to MS memory */
1254        ret_val = qla8044_ms_mem_write_128b(vha, dest,
1255            (uint32_t *)p_cache, count);
1256        if (ret_val == QLA_FUNCTION_FAILED) {
1257                ql_log(ql_log_fatal, vha, 0xb0a9,
1258                    "%s: Error writing F/W to MS !!!\n", __func__);
1259                goto exit_copy_error;
1260        }
1261        ql_dbg(ql_dbg_p3p, vha, 0xb0aa,
1262            "%s: Wrote F/W (size %d) to MS !!!\n",
1263            __func__, size);
1264
1265exit_copy_error:
1266        vfree(p_cache);
1267
1268exit_copy_bootloader:
1269        return ret_val;
1270}
1271
1272static int
1273qla8044_restart(struct scsi_qla_host *vha)
1274{
1275        int ret_val = QLA_SUCCESS;
1276        struct qla_hw_data *ha = vha->hw;
1277
1278        qla8044_process_stop_seq(vha);
1279
1280        /* Collect minidump */
1281        if (ql2xmdenable)
1282                qla8044_get_minidump(vha);
1283        else
1284                ql_log(ql_log_fatal, vha, 0xb14c,
1285                    "Minidump disabled.\n");
1286
1287        qla8044_process_init_seq(vha);
1288
1289        if (qla8044_copy_bootloader(vha)) {
1290                ql_log(ql_log_fatal, vha, 0xb0ab,
1291                    "%s: Copy bootloader, firmware restart failed!\n",
1292                    __func__);
1293                ret_val = QLA_FUNCTION_FAILED;
1294                goto exit_restart;
1295        }
1296
1297        /*
1298         *  Loads F/W from flash
1299         */
1300        qla8044_wr_reg(ha, QLA8044_FW_IMAGE_VALID, QLA8044_BOOT_FROM_FLASH);
1301
1302        qla8044_process_start_seq(vha);
1303
1304exit_restart:
1305        return ret_val;
1306}
1307
1308/*
1309 * qla8044_check_cmd_peg_status - Check peg status to see if Peg is
1310 * initialized.
1311 *
1312 * @ha : Pointer to adapter structure
1313 *
1314 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
1315 */
1316static int
1317qla8044_check_cmd_peg_status(struct scsi_qla_host *vha)
1318{
1319        uint32_t val, ret_val = QLA_FUNCTION_FAILED;
1320        int retries = CRB_CMDPEG_CHECK_RETRY_COUNT;
1321        struct qla_hw_data *ha = vha->hw;
1322
1323        do {
1324                val = qla8044_rd_reg(ha, QLA8044_CMDPEG_STATE);
1325                if (val == PHAN_INITIALIZE_COMPLETE) {
1326                        ql_dbg(ql_dbg_p3p, vha, 0xb0ac,
1327                            "%s: Command Peg initialization "
1328                            "complete! state=0x%x\n", __func__, val);
1329                        ret_val = QLA_SUCCESS;
1330                        break;
1331                }
1332                msleep(CRB_CMDPEG_CHECK_DELAY);
1333        } while (--retries);
1334
1335        return ret_val;
1336}
1337
1338static int
1339qla8044_start_firmware(struct scsi_qla_host *vha)
1340{
1341        int ret_val = QLA_SUCCESS;
1342
1343        if (qla8044_restart(vha)) {
1344                ql_log(ql_log_fatal, vha, 0xb0ad,
1345                    "%s: Restart Error!!!, Need Reset!!!\n",
1346                    __func__);
1347                ret_val = QLA_FUNCTION_FAILED;
1348                goto exit_start_fw;
1349        } else
1350                ql_dbg(ql_dbg_p3p, vha, 0xb0af,
1351                    "%s: Restart done!\n", __func__);
1352
1353        ret_val = qla8044_check_cmd_peg_status(vha);
1354        if (ret_val) {
1355                ql_log(ql_log_fatal, vha, 0xb0b0,
1356                    "%s: Peg not initialized!\n", __func__);
1357                ret_val = QLA_FUNCTION_FAILED;
1358        }
1359
1360exit_start_fw:
1361        return ret_val;
1362}
1363
1364void
1365qla8044_clear_drv_active(struct qla_hw_data *ha)
1366{
1367        uint32_t drv_active;
1368        struct scsi_qla_host *vha = pci_get_drvdata(ha->pdev);
1369
1370        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1371        drv_active &= ~(1 << (ha->portnum));
1372
1373        ql_log(ql_log_info, vha, 0xb0b1,
1374            "%s(%ld): drv_active: 0x%08x\n",
1375            __func__, vha->host_no, drv_active);
1376
1377        qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active);
1378}
1379
1380/*
1381 * qla8044_device_bootstrap - Initialize device, set DEV_READY, start fw
1382 * @ha: pointer to adapter structure
1383 *
1384 * Note: IDC lock must be held upon entry
1385 **/
1386static int
1387qla8044_device_bootstrap(struct scsi_qla_host *vha)
1388{
1389        int rval = QLA_FUNCTION_FAILED;
1390        int i;
1391        uint32_t old_count = 0, count = 0;
1392        int need_reset = 0;
1393        uint32_t idc_ctrl;
1394        struct qla_hw_data *ha = vha->hw;
1395
1396        need_reset = qla8044_need_reset(vha);
1397
1398        if (!need_reset) {
1399                old_count = qla8044_rd_direct(vha,
1400                    QLA8044_PEG_ALIVE_COUNTER_INDEX);
1401
1402                for (i = 0; i < 10; i++) {
1403                        msleep(200);
1404
1405                        count = qla8044_rd_direct(vha,
1406                            QLA8044_PEG_ALIVE_COUNTER_INDEX);
1407                        if (count != old_count) {
1408                                rval = QLA_SUCCESS;
1409                                goto dev_ready;
1410                        }
1411                }
1412                qla8044_flash_lock_recovery(vha);
1413        } else {
1414                /* We are trying to perform a recovery here. */
1415                if (ha->flags.isp82xx_fw_hung)
1416                        qla8044_flash_lock_recovery(vha);
1417        }
1418
1419        /* set to DEV_INITIALIZING */
1420        ql_log(ql_log_info, vha, 0xb0b2,
1421            "%s: HW State: INITIALIZING\n", __func__);
1422        qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1423            QLA8XXX_DEV_INITIALIZING);
1424
1425        qla8044_idc_unlock(ha);
1426        rval = qla8044_start_firmware(vha);
1427        qla8044_idc_lock(ha);
1428
1429        if (rval != QLA_SUCCESS) {
1430                ql_log(ql_log_info, vha, 0xb0b3,
1431                     "%s: HW State: FAILED\n", __func__);
1432                qla8044_clear_drv_active(ha);
1433                qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1434                    QLA8XXX_DEV_FAILED);
1435                return rval;
1436        }
1437
1438        /* For ISP8044, If IDC_CTRL GRACEFUL_RESET_BIT1 is set , reset it after
1439         * device goes to INIT state. */
1440        idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1441        if (idc_ctrl & GRACEFUL_RESET_BIT1) {
1442                qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
1443                    (idc_ctrl & ~GRACEFUL_RESET_BIT1));
1444                ha->fw_dumped = false;
1445        }
1446
1447dev_ready:
1448        ql_log(ql_log_info, vha, 0xb0b4,
1449            "%s: HW State: READY\n", __func__);
1450        qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX, QLA8XXX_DEV_READY);
1451
1452        return rval;
1453}
1454
1455/*-------------------------Reset Sequence Functions-----------------------*/
1456static void
1457qla8044_dump_reset_seq_hdr(struct scsi_qla_host *vha)
1458{
1459        u8 *phdr;
1460
1461        if (!vha->reset_tmplt.buff) {
1462                ql_log(ql_log_fatal, vha, 0xb0b5,
1463                    "%s: Error Invalid reset_seq_template\n", __func__);
1464                return;
1465        }
1466
1467        phdr = vha->reset_tmplt.buff;
1468        ql_dbg(ql_dbg_p3p, vha, 0xb0b6,
1469            "Reset Template :\n\t0x%X 0x%X 0x%X 0x%X"
1470            "0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n"
1471            "\t0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n\n",
1472            *phdr, *(phdr+1), *(phdr+2), *(phdr+3), *(phdr+4),
1473            *(phdr+5), *(phdr+6), *(phdr+7), *(phdr + 8),
1474            *(phdr+9), *(phdr+10), *(phdr+11), *(phdr+12),
1475            *(phdr+13), *(phdr+14), *(phdr+15));
1476}
1477
1478/*
1479 * qla8044_reset_seq_checksum_test - Validate Reset Sequence template.
1480 *
1481 * @ha : Pointer to adapter structure
1482 *
1483 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
1484 */
1485static int
1486qla8044_reset_seq_checksum_test(struct scsi_qla_host *vha)
1487{
1488        uint32_t sum =  0;
1489        uint16_t *buff = (uint16_t *)vha->reset_tmplt.buff;
1490        int u16_count =  vha->reset_tmplt.hdr->size / sizeof(uint16_t);
1491
1492        while (u16_count-- > 0)
1493                sum += *buff++;
1494
1495        while (sum >> 16)
1496                sum = (sum & 0xFFFF) +  (sum >> 16);
1497
1498        /* checksum of 0 indicates a valid template */
1499        if (~sum) {
1500                return QLA_SUCCESS;
1501        } else {
1502                ql_log(ql_log_fatal, vha, 0xb0b7,
1503                    "%s: Reset seq checksum failed\n", __func__);
1504                return QLA_FUNCTION_FAILED;
1505        }
1506}
1507
1508/*
1509 * qla8044_read_reset_template - Read Reset Template from Flash, validate
1510 * the template and store offsets of stop/start/init offsets in ha->reset_tmplt.
1511 *
1512 * @ha : Pointer to adapter structure
1513 */
1514void
1515qla8044_read_reset_template(struct scsi_qla_host *vha)
1516{
1517        uint8_t *p_buff;
1518        uint32_t addr, tmplt_hdr_def_size, tmplt_hdr_size;
1519
1520        vha->reset_tmplt.seq_error = 0;
1521        vha->reset_tmplt.buff = vmalloc(QLA8044_RESTART_TEMPLATE_SIZE);
1522        if (vha->reset_tmplt.buff == NULL) {
1523                ql_log(ql_log_fatal, vha, 0xb0b8,
1524                    "%s: Failed to allocate reset template resources\n",
1525                    __func__);
1526                goto exit_read_reset_template;
1527        }
1528
1529        p_buff = vha->reset_tmplt.buff;
1530        addr = QLA8044_RESET_TEMPLATE_ADDR;
1531
1532        tmplt_hdr_def_size =
1533            sizeof(struct qla8044_reset_template_hdr) / sizeof(uint32_t);
1534
1535        ql_dbg(ql_dbg_p3p, vha, 0xb0b9,
1536            "%s: Read template hdr size %d from Flash\n",
1537            __func__, tmplt_hdr_def_size);
1538
1539        /* Copy template header from flash */
1540        if (qla8044_read_flash_data(vha, p_buff, addr, tmplt_hdr_def_size)) {
1541                ql_log(ql_log_fatal, vha, 0xb0ba,
1542                    "%s: Failed to read reset template\n", __func__);
1543                goto exit_read_template_error;
1544        }
1545
1546        vha->reset_tmplt.hdr =
1547         (struct qla8044_reset_template_hdr *) vha->reset_tmplt.buff;
1548
1549        /* Validate the template header size and signature */
1550        tmplt_hdr_size = vha->reset_tmplt.hdr->hdr_size/sizeof(uint32_t);
1551        if ((tmplt_hdr_size != tmplt_hdr_def_size) ||
1552            (vha->reset_tmplt.hdr->signature != RESET_TMPLT_HDR_SIGNATURE)) {
1553                ql_log(ql_log_fatal, vha, 0xb0bb,
1554                    "%s: Template Header size invalid %d "
1555                    "tmplt_hdr_def_size %d!!!\n", __func__,
1556                    tmplt_hdr_size, tmplt_hdr_def_size);
1557                goto exit_read_template_error;
1558        }
1559
1560        addr = QLA8044_RESET_TEMPLATE_ADDR + vha->reset_tmplt.hdr->hdr_size;
1561        p_buff = vha->reset_tmplt.buff + vha->reset_tmplt.hdr->hdr_size;
1562        tmplt_hdr_def_size = (vha->reset_tmplt.hdr->size -
1563            vha->reset_tmplt.hdr->hdr_size)/sizeof(uint32_t);
1564
1565        ql_dbg(ql_dbg_p3p, vha, 0xb0bc,
1566            "%s: Read rest of the template size %d\n",
1567            __func__, vha->reset_tmplt.hdr->size);
1568
1569        /* Copy rest of the template */
1570        if (qla8044_read_flash_data(vha, p_buff, addr, tmplt_hdr_def_size)) {
1571                ql_log(ql_log_fatal, vha, 0xb0bd,
1572                    "%s: Failed to read reset template\n", __func__);
1573                goto exit_read_template_error;
1574        }
1575
1576        /* Integrity check */
1577        if (qla8044_reset_seq_checksum_test(vha)) {
1578                ql_log(ql_log_fatal, vha, 0xb0be,
1579                    "%s: Reset Seq checksum failed!\n", __func__);
1580                goto exit_read_template_error;
1581        }
1582
1583        ql_dbg(ql_dbg_p3p, vha, 0xb0bf,
1584            "%s: Reset Seq checksum passed! Get stop, "
1585            "start and init seq offsets\n", __func__);
1586
1587        /* Get STOP, START, INIT sequence offsets */
1588        vha->reset_tmplt.init_offset = vha->reset_tmplt.buff +
1589            vha->reset_tmplt.hdr->init_seq_offset;
1590
1591        vha->reset_tmplt.start_offset = vha->reset_tmplt.buff +
1592            vha->reset_tmplt.hdr->start_seq_offset;
1593
1594        vha->reset_tmplt.stop_offset = vha->reset_tmplt.buff +
1595            vha->reset_tmplt.hdr->hdr_size;
1596
1597        qla8044_dump_reset_seq_hdr(vha);
1598
1599        goto exit_read_reset_template;
1600
1601exit_read_template_error:
1602        vfree(vha->reset_tmplt.buff);
1603
1604exit_read_reset_template:
1605        return;
1606}
1607
1608void
1609qla8044_set_idc_dontreset(struct scsi_qla_host *vha)
1610{
1611        uint32_t idc_ctrl;
1612        struct qla_hw_data *ha = vha->hw;
1613
1614        idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1615        idc_ctrl |= DONTRESET_BIT0;
1616        ql_dbg(ql_dbg_p3p, vha, 0xb0c0,
1617            "%s: idc_ctrl = %d\n", __func__, idc_ctrl);
1618        qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, idc_ctrl);
1619}
1620
1621static inline void
1622qla8044_set_rst_ready(struct scsi_qla_host *vha)
1623{
1624        uint32_t drv_state;
1625        struct qla_hw_data *ha = vha->hw;
1626
1627        drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
1628
1629        /* For ISP8044, drv_active register has 1 bit per function,
1630         * shift 1 by func_num to set a bit for the function.*/
1631        drv_state |= (1 << ha->portnum);
1632
1633        ql_log(ql_log_info, vha, 0xb0c1,
1634            "%s(%ld): drv_state: 0x%08x\n",
1635            __func__, vha->host_no, drv_state);
1636        qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, drv_state);
1637}
1638
1639/**
1640 * qla8044_need_reset_handler - Code to start reset sequence
1641 * @vha: pointer to adapter structure
1642 *
1643 * Note: IDC lock must be held upon entry
1644 */
1645static void
1646qla8044_need_reset_handler(struct scsi_qla_host *vha)
1647{
1648        uint32_t dev_state = 0, drv_state, drv_active;
1649        unsigned long reset_timeout;
1650        struct qla_hw_data *ha = vha->hw;
1651
1652        ql_log(ql_log_fatal, vha, 0xb0c2,
1653            "%s: Performing ISP error recovery\n", __func__);
1654
1655        if (vha->flags.online) {
1656                qla8044_idc_unlock(ha);
1657                qla2x00_abort_isp_cleanup(vha);
1658                ha->isp_ops->get_flash_version(vha, vha->req->ring);
1659                ha->isp_ops->nvram_config(vha);
1660                qla8044_idc_lock(ha);
1661        }
1662
1663        dev_state = qla8044_rd_direct(vha,
1664            QLA8044_CRB_DEV_STATE_INDEX);
1665        drv_state = qla8044_rd_direct(vha,
1666            QLA8044_CRB_DRV_STATE_INDEX);
1667        drv_active = qla8044_rd_direct(vha,
1668            QLA8044_CRB_DRV_ACTIVE_INDEX);
1669
1670        ql_log(ql_log_info, vha, 0xb0c5,
1671            "%s(%ld): drv_state = 0x%x, drv_active = 0x%x dev_state = 0x%x\n",
1672            __func__, vha->host_no, drv_state, drv_active, dev_state);
1673
1674        qla8044_set_rst_ready(vha);
1675
1676        /* wait for 10 seconds for reset ack from all functions */
1677        reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
1678
1679        do {
1680                if (time_after_eq(jiffies, reset_timeout)) {
1681                        ql_log(ql_log_info, vha, 0xb0c4,
1682                            "%s: Function %d: Reset Ack Timeout!, drv_state: 0x%08x, drv_active: 0x%08x\n",
1683                            __func__, ha->portnum, drv_state, drv_active);
1684                        break;
1685                }
1686
1687                qla8044_idc_unlock(ha);
1688                msleep(1000);
1689                qla8044_idc_lock(ha);
1690
1691                dev_state = qla8044_rd_direct(vha,
1692                    QLA8044_CRB_DEV_STATE_INDEX);
1693                drv_state = qla8044_rd_direct(vha,
1694                    QLA8044_CRB_DRV_STATE_INDEX);
1695                drv_active = qla8044_rd_direct(vha,
1696                    QLA8044_CRB_DRV_ACTIVE_INDEX);
1697        } while (((drv_state & drv_active) != drv_active) &&
1698            (dev_state == QLA8XXX_DEV_NEED_RESET));
1699
1700        /* Remove IDC participation of functions not acknowledging */
1701        if (drv_state != drv_active) {
1702                ql_log(ql_log_info, vha, 0xb0c7,
1703                    "%s(%ld): Function %d turning off drv_active of non-acking function 0x%x\n",
1704                    __func__, vha->host_no, ha->portnum,
1705                    (drv_active ^ drv_state));
1706                drv_active = drv_active & drv_state;
1707                qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX,
1708                    drv_active);
1709        } else {
1710                /*
1711                 * Reset owner should execute reset recovery,
1712                 * if all functions acknowledged
1713                 */
1714                if ((ha->flags.nic_core_reset_owner) &&
1715                    (dev_state == QLA8XXX_DEV_NEED_RESET)) {
1716                        ha->flags.nic_core_reset_owner = 0;
1717                        qla8044_device_bootstrap(vha);
1718                        return;
1719                }
1720        }
1721
1722        /* Exit if non active function */
1723        if (!(drv_active & (1 << ha->portnum))) {
1724                ha->flags.nic_core_reset_owner = 0;
1725                return;
1726        }
1727
1728        /*
1729         * Execute Reset Recovery if Reset Owner or Function 7
1730         * is the only active function
1731         */
1732        if (ha->flags.nic_core_reset_owner ||
1733            ((drv_state & drv_active) == QLA8044_FUN7_ACTIVE_INDEX)) {
1734                ha->flags.nic_core_reset_owner = 0;
1735                qla8044_device_bootstrap(vha);
1736        }
1737}
1738
1739static void
1740qla8044_set_drv_active(struct scsi_qla_host *vha)
1741{
1742        uint32_t drv_active;
1743        struct qla_hw_data *ha = vha->hw;
1744
1745        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1746
1747        /* For ISP8044, drv_active register has 1 bit per function,
1748         * shift 1 by func_num to set a bit for the function.*/
1749        drv_active |= (1 << ha->portnum);
1750
1751        ql_log(ql_log_info, vha, 0xb0c8,
1752            "%s(%ld): drv_active: 0x%08x\n",
1753            __func__, vha->host_no, drv_active);
1754        qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active);
1755}
1756
1757static int
1758qla8044_check_drv_active(struct scsi_qla_host *vha)
1759{
1760        uint32_t drv_active;
1761        struct qla_hw_data *ha = vha->hw;
1762
1763        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1764        if (drv_active & (1 << ha->portnum))
1765                return QLA_SUCCESS;
1766        else
1767                return QLA_TEST_FAILED;
1768}
1769
1770static void
1771qla8044_clear_idc_dontreset(struct scsi_qla_host *vha)
1772{
1773        uint32_t idc_ctrl;
1774        struct qla_hw_data *ha = vha->hw;
1775
1776        idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
1777        idc_ctrl &= ~DONTRESET_BIT0;
1778        ql_log(ql_log_info, vha, 0xb0c9,
1779            "%s: idc_ctrl = %d\n", __func__,
1780            idc_ctrl);
1781        qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL, idc_ctrl);
1782}
1783
1784static int
1785qla8044_set_idc_ver(struct scsi_qla_host *vha)
1786{
1787        int idc_ver;
1788        uint32_t drv_active;
1789        int rval = QLA_SUCCESS;
1790        struct qla_hw_data *ha = vha->hw;
1791
1792        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1793        if (drv_active == (1 << ha->portnum)) {
1794                idc_ver = qla8044_rd_direct(vha,
1795                    QLA8044_CRB_DRV_IDC_VERSION_INDEX);
1796                idc_ver &= (~0xFF);
1797                idc_ver |= QLA8044_IDC_VER_MAJ_VALUE;
1798                qla8044_wr_direct(vha, QLA8044_CRB_DRV_IDC_VERSION_INDEX,
1799                    idc_ver);
1800                ql_log(ql_log_info, vha, 0xb0ca,
1801                    "%s: IDC version updated to %d\n",
1802                    __func__, idc_ver);
1803        } else {
1804                idc_ver = qla8044_rd_direct(vha,
1805                    QLA8044_CRB_DRV_IDC_VERSION_INDEX);
1806                idc_ver &= 0xFF;
1807                if (QLA8044_IDC_VER_MAJ_VALUE != idc_ver) {
1808                        ql_log(ql_log_info, vha, 0xb0cb,
1809                            "%s: qla4xxx driver IDC version %d "
1810                            "is not compatible with IDC version %d "
1811                            "of other drivers!\n",
1812                            __func__, QLA8044_IDC_VER_MAJ_VALUE,
1813                            idc_ver);
1814                        rval = QLA_FUNCTION_FAILED;
1815                        goto exit_set_idc_ver;
1816                }
1817        }
1818
1819        /* Update IDC_MINOR_VERSION */
1820        idc_ver = qla8044_rd_reg(ha, QLA8044_CRB_IDC_VER_MINOR);
1821        idc_ver &= ~(0x03 << (ha->portnum * 2));
1822        idc_ver |= (QLA8044_IDC_VER_MIN_VALUE << (ha->portnum * 2));
1823        qla8044_wr_reg(ha, QLA8044_CRB_IDC_VER_MINOR, idc_ver);
1824
1825exit_set_idc_ver:
1826        return rval;
1827}
1828
1829static int
1830qla8044_update_idc_reg(struct scsi_qla_host *vha)
1831{
1832        uint32_t drv_active;
1833        int rval = QLA_SUCCESS;
1834        struct qla_hw_data *ha = vha->hw;
1835
1836        if (vha->flags.init_done)
1837                goto exit_update_idc_reg;
1838
1839        qla8044_idc_lock(ha);
1840        qla8044_set_drv_active(vha);
1841
1842        drv_active = qla8044_rd_direct(vha,
1843            QLA8044_CRB_DRV_ACTIVE_INDEX);
1844
1845        /* If we are the first driver to load and
1846         * ql2xdontresethba is not set, clear IDC_CTRL BIT0. */
1847        if ((drv_active == (1 << ha->portnum)) && !ql2xdontresethba)
1848                qla8044_clear_idc_dontreset(vha);
1849
1850        rval = qla8044_set_idc_ver(vha);
1851        if (rval == QLA_FUNCTION_FAILED)
1852                qla8044_clear_drv_active(ha);
1853        qla8044_idc_unlock(ha);
1854
1855exit_update_idc_reg:
1856        return rval;
1857}
1858
1859/**
1860 * qla8044_need_qsnt_handler - Code to start qsnt
1861 * @vha: pointer to adapter structure
1862 */
1863static void
1864qla8044_need_qsnt_handler(struct scsi_qla_host *vha)
1865{
1866        unsigned long qsnt_timeout;
1867        uint32_t drv_state, drv_active, dev_state;
1868        struct qla_hw_data *ha = vha->hw;
1869
1870        if (vha->flags.online)
1871                qla2x00_quiesce_io(vha);
1872        else
1873                return;
1874
1875        qla8044_set_qsnt_ready(vha);
1876
1877        /* Wait for 30 secs for all functions to ack qsnt mode */
1878        qsnt_timeout = jiffies + (QSNT_ACK_TOV * HZ);
1879        drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
1880        drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1881
1882        /* Shift drv_active by 1 to match drv_state. As quiescent ready bit
1883           position is at bit 1 and drv active is at bit 0 */
1884        drv_active = drv_active << 1;
1885
1886        while (drv_state != drv_active) {
1887                if (time_after_eq(jiffies, qsnt_timeout)) {
1888                        /* Other functions did not ack, changing state to
1889                         * DEV_READY
1890                         */
1891                        clear_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
1892                        qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1893                                            QLA8XXX_DEV_READY);
1894                        qla8044_clear_qsnt_ready(vha);
1895                        ql_log(ql_log_info, vha, 0xb0cc,
1896                            "Timeout waiting for quiescent ack!!!\n");
1897                        return;
1898                }
1899                qla8044_idc_unlock(ha);
1900                msleep(1000);
1901                qla8044_idc_lock(ha);
1902
1903                drv_state = qla8044_rd_direct(vha,
1904                    QLA8044_CRB_DRV_STATE_INDEX);
1905                drv_active = qla8044_rd_direct(vha,
1906                    QLA8044_CRB_DRV_ACTIVE_INDEX);
1907                drv_active = drv_active << 1;
1908        }
1909
1910        /* All functions have Acked. Set quiescent state */
1911        dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1912
1913        if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT) {
1914                qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
1915                    QLA8XXX_DEV_QUIESCENT);
1916                ql_log(ql_log_info, vha, 0xb0cd,
1917                    "%s: HW State: QUIESCENT\n", __func__);
1918        }
1919}
1920
1921/*
1922 * qla8044_device_state_handler - Adapter state machine
1923 * @ha: pointer to host adapter structure.
1924 *
1925 * Note: IDC lock must be UNLOCKED upon entry
1926 **/
1927int
1928qla8044_device_state_handler(struct scsi_qla_host *vha)
1929{
1930        uint32_t dev_state;
1931        int rval = QLA_SUCCESS;
1932        unsigned long dev_init_timeout;
1933        struct qla_hw_data *ha = vha->hw;
1934
1935        rval = qla8044_update_idc_reg(vha);
1936        if (rval == QLA_FUNCTION_FAILED)
1937                goto exit_error;
1938
1939        dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1940        ql_dbg(ql_dbg_p3p, vha, 0xb0ce,
1941            "Device state is 0x%x = %s\n",
1942            dev_state, dev_state < MAX_STATES ?
1943            qdev_state(dev_state) : "Unknown");
1944
1945        /* wait for 30 seconds for device to go ready */
1946        dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ);
1947
1948        qla8044_idc_lock(ha);
1949
1950        while (1) {
1951                if (time_after_eq(jiffies, dev_init_timeout)) {
1952                        if (qla8044_check_drv_active(vha) == QLA_SUCCESS) {
1953                                ql_log(ql_log_warn, vha, 0xb0cf,
1954                                    "%s: Device Init Failed 0x%x = %s\n",
1955                                    QLA2XXX_DRIVER_NAME, dev_state,
1956                                    dev_state < MAX_STATES ?
1957                                    qdev_state(dev_state) : "Unknown");
1958                                qla8044_wr_direct(vha,
1959                                    QLA8044_CRB_DEV_STATE_INDEX,
1960                                    QLA8XXX_DEV_FAILED);
1961                        }
1962                }
1963
1964                dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
1965                ql_log(ql_log_info, vha, 0xb0d0,
1966                    "Device state is 0x%x = %s\n",
1967                    dev_state, dev_state < MAX_STATES ?
1968                    qdev_state(dev_state) : "Unknown");
1969
1970                /* NOTE: Make sure idc unlocked upon exit of switch statement */
1971                switch (dev_state) {
1972                case QLA8XXX_DEV_READY:
1973                        ha->flags.nic_core_reset_owner = 0;
1974                        goto exit;
1975                case QLA8XXX_DEV_COLD:
1976                        rval = qla8044_device_bootstrap(vha);
1977                        break;
1978                case QLA8XXX_DEV_INITIALIZING:
1979                        qla8044_idc_unlock(ha);
1980                        msleep(1000);
1981                        qla8044_idc_lock(ha);
1982                        break;
1983                case QLA8XXX_DEV_NEED_RESET:
1984                        /* For ISP8044, if NEED_RESET is set by any driver,
1985                         * it should be honored, irrespective of IDC_CTRL
1986                         * DONTRESET_BIT0 */
1987                        qla8044_need_reset_handler(vha);
1988                        break;
1989                case QLA8XXX_DEV_NEED_QUIESCENT:
1990                        /* idc locked/unlocked in handler */
1991                        qla8044_need_qsnt_handler(vha);
1992
1993                        /* Reset the init timeout after qsnt handler */
1994                        dev_init_timeout = jiffies +
1995                            (ha->fcoe_reset_timeout * HZ);
1996                        break;
1997                case QLA8XXX_DEV_QUIESCENT:
1998                        ql_log(ql_log_info, vha, 0xb0d1,
1999                            "HW State: QUIESCENT\n");
2000
2001                        qla8044_idc_unlock(ha);
2002                        msleep(1000);
2003                        qla8044_idc_lock(ha);
2004
2005                        /* Reset the init timeout after qsnt handler */
2006                        dev_init_timeout = jiffies +
2007                            (ha->fcoe_reset_timeout * HZ);
2008                        break;
2009                case QLA8XXX_DEV_FAILED:
2010                        ha->flags.nic_core_reset_owner = 0;
2011                        qla8044_idc_unlock(ha);
2012                        qla8xxx_dev_failed_handler(vha);
2013                        rval = QLA_FUNCTION_FAILED;
2014                        qla8044_idc_lock(ha);
2015                        goto exit;
2016                default:
2017                        qla8044_idc_unlock(ha);
2018                        qla8xxx_dev_failed_handler(vha);
2019                        rval = QLA_FUNCTION_FAILED;
2020                        qla8044_idc_lock(ha);
2021                        goto exit;
2022                }
2023        }
2024exit:
2025        qla8044_idc_unlock(ha);
2026
2027exit_error:
2028        return rval;
2029}
2030
2031/**
2032 * qla8044_check_temp - Check the ISP82XX temperature.
2033 * @vha: adapter block pointer.
2034 *
2035 * Note: The caller should not hold the idc lock.
2036 */
2037static int
2038qla8044_check_temp(struct scsi_qla_host *vha)
2039{
2040        uint32_t temp, temp_state, temp_val;
2041        int status = QLA_SUCCESS;
2042
2043        temp = qla8044_rd_direct(vha, QLA8044_CRB_TEMP_STATE_INDEX);
2044        temp_state = qla82xx_get_temp_state(temp);
2045        temp_val = qla82xx_get_temp_val(temp);
2046
2047        if (temp_state == QLA82XX_TEMP_PANIC) {
2048                ql_log(ql_log_warn, vha, 0xb0d2,
2049                    "Device temperature %d degrees C"
2050                    " exceeds maximum allowed. Hardware has been shut"
2051                    " down\n", temp_val);
2052                status = QLA_FUNCTION_FAILED;
2053                return status;
2054        } else if (temp_state == QLA82XX_TEMP_WARN) {
2055                ql_log(ql_log_warn, vha, 0xb0d3,
2056                    "Device temperature %d"
2057                    " degrees C exceeds operating range."
2058                    " Immediate action needed.\n", temp_val);
2059        }
2060        return 0;
2061}
2062
2063int qla8044_read_temperature(scsi_qla_host_t *vha)
2064{
2065        uint32_t temp;
2066
2067        temp = qla8044_rd_direct(vha, QLA8044_CRB_TEMP_STATE_INDEX);
2068        return qla82xx_get_temp_val(temp);
2069}
2070
2071/**
2072 * qla8044_check_fw_alive  - Check firmware health
2073 * @vha: Pointer to host adapter structure.
2074 *
2075 * Context: Interrupt
2076 */
2077int
2078qla8044_check_fw_alive(struct scsi_qla_host *vha)
2079{
2080        uint32_t fw_heartbeat_counter;
2081        uint32_t halt_status1, halt_status2;
2082        int status = QLA_SUCCESS;
2083
2084        fw_heartbeat_counter = qla8044_rd_direct(vha,
2085            QLA8044_PEG_ALIVE_COUNTER_INDEX);
2086
2087        /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */
2088        if (fw_heartbeat_counter == 0xffffffff) {
2089                ql_dbg(ql_dbg_p3p, vha, 0xb0d4,
2090                    "scsi%ld: %s: Device in frozen "
2091                    "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",
2092                    vha->host_no, __func__);
2093                return status;
2094        }
2095
2096        if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
2097                vha->seconds_since_last_heartbeat++;
2098                /* FW not alive after 2 seconds */
2099                if (vha->seconds_since_last_heartbeat == 2) {
2100                        vha->seconds_since_last_heartbeat = 0;
2101                        halt_status1 = qla8044_rd_direct(vha,
2102                            QLA8044_PEG_HALT_STATUS1_INDEX);
2103                        halt_status2 = qla8044_rd_direct(vha,
2104                            QLA8044_PEG_HALT_STATUS2_INDEX);
2105
2106                        ql_log(ql_log_info, vha, 0xb0d5,
2107                            "scsi(%ld): %s, ISP8044 "
2108                            "Dumping hw/fw registers:\n"
2109                            " PEG_HALT_STATUS1: 0x%x, "
2110                            "PEG_HALT_STATUS2: 0x%x,\n",
2111                            vha->host_no, __func__, halt_status1,
2112                            halt_status2);
2113                        status = QLA_FUNCTION_FAILED;
2114                }
2115        } else
2116                vha->seconds_since_last_heartbeat = 0;
2117
2118        vha->fw_heartbeat_counter = fw_heartbeat_counter;
2119        return status;
2120}
2121
2122void
2123qla8044_watchdog(struct scsi_qla_host *vha)
2124{
2125        uint32_t dev_state, halt_status;
2126        int halt_status_unrecoverable = 0;
2127        struct qla_hw_data *ha = vha->hw;
2128
2129        /* don't poll if reset is going on or FW hang in quiescent state */
2130        if (!(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
2131            test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags))) {
2132                dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
2133
2134                if (qla8044_check_fw_alive(vha)) {
2135                        ha->flags.isp82xx_fw_hung = 1;
2136                        ql_log(ql_log_warn, vha, 0xb10a,
2137                            "Firmware hung.\n");
2138                        qla82xx_clear_pending_mbx(vha);
2139                }
2140
2141                if (qla8044_check_temp(vha)) {
2142                        set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
2143                        ha->flags.isp82xx_fw_hung = 1;
2144                        qla2xxx_wake_dpc(vha);
2145                } else if (dev_state == QLA8XXX_DEV_NEED_RESET &&
2146                           !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
2147                        ql_log(ql_log_info, vha, 0xb0d6,
2148                            "%s: HW State: NEED RESET!\n",
2149                            __func__);
2150                        set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
2151                        qla2xxx_wake_dpc(vha);
2152                } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT &&
2153                    !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
2154                        ql_log(ql_log_info, vha, 0xb0d7,
2155                            "%s: HW State: NEED QUIES detected!\n",
2156                            __func__);
2157                        set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
2158                        qla2xxx_wake_dpc(vha);
2159                } else  {
2160                        /* Check firmware health */
2161                        if (ha->flags.isp82xx_fw_hung) {
2162                                halt_status = qla8044_rd_direct(vha,
2163                                        QLA8044_PEG_HALT_STATUS1_INDEX);
2164                                if (halt_status &
2165                                    QLA8044_HALT_STATUS_FW_RESET) {
2166                                        ql_log(ql_log_fatal, vha,
2167                                            0xb0d8, "%s: Firmware "
2168                                            "error detected device "
2169                                            "is being reset\n",
2170                                            __func__);
2171                                } else if (halt_status &
2172                                            QLA8044_HALT_STATUS_UNRECOVERABLE) {
2173                                                halt_status_unrecoverable = 1;
2174                                }
2175
2176                                /* Since we cannot change dev_state in interrupt
2177                                 * context, set appropriate DPC flag then wakeup
2178                                 *  DPC */
2179                                if (halt_status_unrecoverable) {
2180                                        set_bit(ISP_UNRECOVERABLE,
2181                                            &vha->dpc_flags);
2182                                } else {
2183                                        if (dev_state ==
2184                                            QLA8XXX_DEV_QUIESCENT) {
2185                                                set_bit(FCOE_CTX_RESET_NEEDED,
2186                                                    &vha->dpc_flags);
2187                                                ql_log(ql_log_info, vha, 0xb0d9,
2188                                                    "%s: FW CONTEXT Reset "
2189                                                    "needed!\n", __func__);
2190                                        } else {
2191                                                ql_log(ql_log_info, vha,
2192                                                    0xb0da, "%s: "
2193                                                    "detect abort needed\n",
2194                                                    __func__);
2195                                                set_bit(ISP_ABORT_NEEDED,
2196                                                    &vha->dpc_flags);
2197                                        }
2198                                }
2199                                qla2xxx_wake_dpc(vha);
2200                        }
2201                }
2202
2203        }
2204}
2205
2206static int
2207qla8044_minidump_process_control(struct scsi_qla_host *vha,
2208                                 struct qla8044_minidump_entry_hdr *entry_hdr)
2209{
2210        struct qla8044_minidump_entry_crb *crb_entry;
2211        uint32_t read_value, opcode, poll_time, addr, index;
2212        uint32_t crb_addr, rval = QLA_SUCCESS;
2213        unsigned long wtime;
2214        struct qla8044_minidump_template_hdr *tmplt_hdr;
2215        int i;
2216        struct qla_hw_data *ha = vha->hw;
2217
2218        ql_dbg(ql_dbg_p3p, vha, 0xb0dd, "Entering fn: %s\n", __func__);
2219        tmplt_hdr = (struct qla8044_minidump_template_hdr *)
2220                ha->md_tmplt_hdr;
2221        crb_entry = (struct qla8044_minidump_entry_crb *)entry_hdr;
2222
2223        crb_addr = crb_entry->addr;
2224        for (i = 0; i < crb_entry->op_count; i++) {
2225                opcode = crb_entry->crb_ctrl.opcode;
2226
2227                if (opcode & QLA82XX_DBG_OPCODE_WR) {
2228                        qla8044_wr_reg_indirect(vha, crb_addr,
2229                            crb_entry->value_1);
2230                }
2231
2232                if (opcode & QLA82XX_DBG_OPCODE_RW) {
2233                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2234                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2235                }
2236
2237                if (opcode & QLA82XX_DBG_OPCODE_AND) {
2238                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2239                        read_value &= crb_entry->value_2;
2240                        if (opcode & QLA82XX_DBG_OPCODE_OR) {
2241                                read_value |= crb_entry->value_3;
2242                                opcode &= ~QLA82XX_DBG_OPCODE_OR;
2243                        }
2244                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2245                }
2246                if (opcode & QLA82XX_DBG_OPCODE_OR) {
2247                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2248                        read_value |= crb_entry->value_3;
2249                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2250                }
2251                if (opcode & QLA82XX_DBG_OPCODE_POLL) {
2252                        poll_time = crb_entry->crb_strd.poll_timeout;
2253                        wtime = jiffies + poll_time;
2254                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2255
2256                        do {
2257                                if ((read_value & crb_entry->value_2) ==
2258                                    crb_entry->value_1) {
2259                                        break;
2260                                } else if (time_after_eq(jiffies, wtime)) {
2261                                        /* capturing dump failed */
2262                                        rval = QLA_FUNCTION_FAILED;
2263                                        break;
2264                                } else {
2265                                        qla8044_rd_reg_indirect(vha,
2266                                            crb_addr, &read_value);
2267                                }
2268                        } while (1);
2269                }
2270
2271                if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
2272                        if (crb_entry->crb_strd.state_index_a) {
2273                                index = crb_entry->crb_strd.state_index_a;
2274                                addr = tmplt_hdr->saved_state_array[index];
2275                        } else {
2276                                addr = crb_addr;
2277                        }
2278
2279                        qla8044_rd_reg_indirect(vha, addr, &read_value);
2280                        index = crb_entry->crb_ctrl.state_index_v;
2281                        tmplt_hdr->saved_state_array[index] = read_value;
2282                }
2283
2284                if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
2285                        if (crb_entry->crb_strd.state_index_a) {
2286                                index = crb_entry->crb_strd.state_index_a;
2287                                addr = tmplt_hdr->saved_state_array[index];
2288                        } else {
2289                                addr = crb_addr;
2290                        }
2291
2292                        if (crb_entry->crb_ctrl.state_index_v) {
2293                                index = crb_entry->crb_ctrl.state_index_v;
2294                                read_value =
2295                                    tmplt_hdr->saved_state_array[index];
2296                        } else {
2297                                read_value = crb_entry->value_1;
2298                        }
2299
2300                        qla8044_wr_reg_indirect(vha, addr, read_value);
2301                }
2302
2303                if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
2304                        index = crb_entry->crb_ctrl.state_index_v;
2305                        read_value = tmplt_hdr->saved_state_array[index];
2306                        read_value <<= crb_entry->crb_ctrl.shl;
2307                        read_value >>= crb_entry->crb_ctrl.shr;
2308                        if (crb_entry->value_2)
2309                                read_value &= crb_entry->value_2;
2310                        read_value |= crb_entry->value_3;
2311                        read_value += crb_entry->value_1;
2312                        tmplt_hdr->saved_state_array[index] = read_value;
2313                }
2314                crb_addr += crb_entry->crb_strd.addr_stride;
2315        }
2316        return rval;
2317}
2318
2319static void
2320qla8044_minidump_process_rdcrb(struct scsi_qla_host *vha,
2321        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2322{
2323        uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2324        struct qla8044_minidump_entry_crb *crb_hdr;
2325        uint32_t *data_ptr = *d_ptr;
2326
2327        ql_dbg(ql_dbg_p3p, vha, 0xb0de, "Entering fn: %s\n", __func__);
2328        crb_hdr = (struct qla8044_minidump_entry_crb *)entry_hdr;
2329        r_addr = crb_hdr->addr;
2330        r_stride = crb_hdr->crb_strd.addr_stride;
2331        loop_cnt = crb_hdr->op_count;
2332
2333        for (i = 0; i < loop_cnt; i++) {
2334                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2335                *data_ptr++ = r_addr;
2336                *data_ptr++ = r_value;
2337                r_addr += r_stride;
2338        }
2339        *d_ptr = data_ptr;
2340}
2341
2342static int
2343qla8044_minidump_process_rdmem(struct scsi_qla_host *vha,
2344        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2345{
2346        uint32_t r_addr, r_value, r_data;
2347        uint32_t i, j, loop_cnt;
2348        struct qla8044_minidump_entry_rdmem *m_hdr;
2349        unsigned long flags;
2350        uint32_t *data_ptr = *d_ptr;
2351        struct qla_hw_data *ha = vha->hw;
2352
2353        ql_dbg(ql_dbg_p3p, vha, 0xb0df, "Entering fn: %s\n", __func__);
2354        m_hdr = (struct qla8044_minidump_entry_rdmem *)entry_hdr;
2355        r_addr = m_hdr->read_addr;
2356        loop_cnt = m_hdr->read_data_size/16;
2357
2358        ql_dbg(ql_dbg_p3p, vha, 0xb0f0,
2359            "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n",
2360            __func__, r_addr, m_hdr->read_data_size);
2361
2362        if (r_addr & 0xf) {
2363                ql_dbg(ql_dbg_p3p, vha, 0xb0f1,
2364                    "[%s]: Read addr 0x%x not 16 bytes aligned\n",
2365                    __func__, r_addr);
2366                return QLA_FUNCTION_FAILED;
2367        }
2368
2369        if (m_hdr->read_data_size % 16) {
2370                ql_dbg(ql_dbg_p3p, vha, 0xb0f2,
2371                    "[%s]: Read data[0x%x] not multiple of 16 bytes\n",
2372                    __func__, m_hdr->read_data_size);
2373                return QLA_FUNCTION_FAILED;
2374        }
2375
2376        ql_dbg(ql_dbg_p3p, vha, 0xb0f3,
2377            "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
2378            __func__, r_addr, m_hdr->read_data_size, loop_cnt);
2379
2380        write_lock_irqsave(&ha->hw_lock, flags);
2381        for (i = 0; i < loop_cnt; i++) {
2382                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_LO, r_addr);
2383                r_value = 0;
2384                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_HI, r_value);
2385                r_value = MIU_TA_CTL_ENABLE;
2386                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2387                r_value = MIU_TA_CTL_START_ENABLE;
2388                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2389
2390                for (j = 0; j < MAX_CTL_CHECK; j++) {
2391                        qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
2392                            &r_value);
2393                        if ((r_value & MIU_TA_CTL_BUSY) == 0)
2394                                break;
2395                }
2396
2397                if (j >= MAX_CTL_CHECK) {
2398                        write_unlock_irqrestore(&ha->hw_lock, flags);
2399                        return QLA_SUCCESS;
2400                }
2401
2402                for (j = 0; j < 4; j++) {
2403                        qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_RDDATA[j],
2404                            &r_data);
2405                        *data_ptr++ = r_data;
2406                }
2407
2408                r_addr += 16;
2409        }
2410        write_unlock_irqrestore(&ha->hw_lock, flags);
2411
2412        ql_dbg(ql_dbg_p3p, vha, 0xb0f4,
2413            "Leaving fn: %s datacount: 0x%x\n",
2414             __func__, (loop_cnt * 16));
2415
2416        *d_ptr = data_ptr;
2417        return QLA_SUCCESS;
2418}
2419
2420/* ISP83xx flash read for _RDROM _BOARD */
2421static uint32_t
2422qla8044_minidump_process_rdrom(struct scsi_qla_host *vha,
2423        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2424{
2425        uint32_t fl_addr, u32_count, rval;
2426        struct qla8044_minidump_entry_rdrom *rom_hdr;
2427        uint32_t *data_ptr = *d_ptr;
2428
2429        rom_hdr = (struct qla8044_minidump_entry_rdrom *)entry_hdr;
2430        fl_addr = rom_hdr->read_addr;
2431        u32_count = (rom_hdr->read_data_size)/sizeof(uint32_t);
2432
2433        ql_dbg(ql_dbg_p3p, vha, 0xb0f5, "[%s]: fl_addr: 0x%x, count: 0x%x\n",
2434            __func__, fl_addr, u32_count);
2435
2436        rval = qla8044_lockless_flash_read_u32(vha, fl_addr,
2437            (u8 *)(data_ptr), u32_count);
2438
2439        if (rval != QLA_SUCCESS) {
2440                ql_log(ql_log_fatal, vha, 0xb0f6,
2441                    "%s: Flash Read Error,Count=%d\n", __func__, u32_count);
2442                return QLA_FUNCTION_FAILED;
2443        } else {
2444                data_ptr += u32_count;
2445                *d_ptr = data_ptr;
2446                return QLA_SUCCESS;
2447        }
2448}
2449
2450static void
2451qla8044_mark_entry_skipped(struct scsi_qla_host *vha,
2452        struct qla8044_minidump_entry_hdr *entry_hdr, int index)
2453{
2454        entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
2455
2456        ql_log(ql_log_info, vha, 0xb0f7,
2457            "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n",
2458            vha->host_no, index, entry_hdr->entry_type,
2459            entry_hdr->d_ctrl.entry_capture_mask);
2460}
2461
2462static int
2463qla8044_minidump_process_l2tag(struct scsi_qla_host *vha,
2464        struct qla8044_minidump_entry_hdr *entry_hdr,
2465                                 uint32_t **d_ptr)
2466{
2467        uint32_t addr, r_addr, c_addr, t_r_addr;
2468        uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2469        unsigned long p_wait, w_time, p_mask;
2470        uint32_t c_value_w, c_value_r;
2471        struct qla8044_minidump_entry_cache *cache_hdr;
2472        int rval = QLA_FUNCTION_FAILED;
2473        uint32_t *data_ptr = *d_ptr;
2474
2475        ql_dbg(ql_dbg_p3p, vha, 0xb0f8, "Entering fn: %s\n", __func__);
2476        cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2477
2478        loop_count = cache_hdr->op_count;
2479        r_addr = cache_hdr->read_addr;
2480        c_addr = cache_hdr->control_addr;
2481        c_value_w = cache_hdr->cache_ctrl.write_value;
2482
2483        t_r_addr = cache_hdr->tag_reg_addr;
2484        t_value = cache_hdr->addr_ctrl.init_tag_value;
2485        r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2486        p_wait = cache_hdr->cache_ctrl.poll_wait;
2487        p_mask = cache_hdr->cache_ctrl.poll_mask;
2488
2489        for (i = 0; i < loop_count; i++) {
2490                qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2491                if (c_value_w)
2492                        qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2493
2494                if (p_mask) {
2495                        w_time = jiffies + p_wait;
2496                        do {
2497                                qla8044_rd_reg_indirect(vha, c_addr,
2498                                    &c_value_r);
2499                                if ((c_value_r & p_mask) == 0) {
2500                                        break;
2501                                } else if (time_after_eq(jiffies, w_time)) {
2502                                        /* capturing dump failed */
2503                                        return rval;
2504                                }
2505                        } while (1);
2506                }
2507
2508                addr = r_addr;
2509                for (k = 0; k < r_cnt; k++) {
2510                        qla8044_rd_reg_indirect(vha, addr, &r_value);
2511                        *data_ptr++ = r_value;
2512                        addr += cache_hdr->read_ctrl.read_addr_stride;
2513                }
2514                t_value += cache_hdr->addr_ctrl.tag_value_stride;
2515        }
2516        *d_ptr = data_ptr;
2517        return QLA_SUCCESS;
2518}
2519
2520static void
2521qla8044_minidump_process_l1cache(struct scsi_qla_host *vha,
2522        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2523{
2524        uint32_t addr, r_addr, c_addr, t_r_addr;
2525        uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2526        uint32_t c_value_w;
2527        struct qla8044_minidump_entry_cache *cache_hdr;
2528        uint32_t *data_ptr = *d_ptr;
2529
2530        cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2531        loop_count = cache_hdr->op_count;
2532        r_addr = cache_hdr->read_addr;
2533        c_addr = cache_hdr->control_addr;
2534        c_value_w = cache_hdr->cache_ctrl.write_value;
2535
2536        t_r_addr = cache_hdr->tag_reg_addr;
2537        t_value = cache_hdr->addr_ctrl.init_tag_value;
2538        r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2539
2540        for (i = 0; i < loop_count; i++) {
2541                qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2542                qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2543                addr = r_addr;
2544                for (k = 0; k < r_cnt; k++) {
2545                        qla8044_rd_reg_indirect(vha, addr, &r_value);
2546                        *data_ptr++ = r_value;
2547                        addr += cache_hdr->read_ctrl.read_addr_stride;
2548                }
2549                t_value += cache_hdr->addr_ctrl.tag_value_stride;
2550        }
2551        *d_ptr = data_ptr;
2552}
2553
2554static void
2555qla8044_minidump_process_rdocm(struct scsi_qla_host *vha,
2556        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2557{
2558        uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2559        struct qla8044_minidump_entry_rdocm *ocm_hdr;
2560        uint32_t *data_ptr = *d_ptr;
2561        struct qla_hw_data *ha = vha->hw;
2562
2563        ql_dbg(ql_dbg_p3p, vha, 0xb0f9, "Entering fn: %s\n", __func__);
2564
2565        ocm_hdr = (struct qla8044_minidump_entry_rdocm *)entry_hdr;
2566        r_addr = ocm_hdr->read_addr;
2567        r_stride = ocm_hdr->read_addr_stride;
2568        loop_cnt = ocm_hdr->op_count;
2569
2570        ql_dbg(ql_dbg_p3p, vha, 0xb0fa,
2571            "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n",
2572            __func__, r_addr, r_stride, loop_cnt);
2573
2574        for (i = 0; i < loop_cnt; i++) {
2575                r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase));
2576                *data_ptr++ = r_value;
2577                r_addr += r_stride;
2578        }
2579        ql_dbg(ql_dbg_p3p, vha, 0xb0fb, "Leaving fn: %s datacount: 0x%lx\n",
2580            __func__, (long unsigned int) (loop_cnt * sizeof(uint32_t)));
2581
2582        *d_ptr = data_ptr;
2583}
2584
2585static void
2586qla8044_minidump_process_rdmux(struct scsi_qla_host *vha,
2587        struct qla8044_minidump_entry_hdr *entry_hdr,
2588        uint32_t **d_ptr)
2589{
2590        uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value = 0;
2591        struct qla8044_minidump_entry_mux *mux_hdr;
2592        uint32_t *data_ptr = *d_ptr;
2593
2594        ql_dbg(ql_dbg_p3p, vha, 0xb0fc, "Entering fn: %s\n", __func__);
2595
2596        mux_hdr = (struct qla8044_minidump_entry_mux *)entry_hdr;
2597        r_addr = mux_hdr->read_addr;
2598        s_addr = mux_hdr->select_addr;
2599        s_stride = mux_hdr->select_value_stride;
2600        s_value = mux_hdr->select_value;
2601        loop_cnt = mux_hdr->op_count;
2602
2603        for (i = 0; i < loop_cnt; i++) {
2604                qla8044_wr_reg_indirect(vha, s_addr, s_value);
2605                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2606                *data_ptr++ = s_value;
2607                *data_ptr++ = r_value;
2608                s_value += s_stride;
2609        }
2610        *d_ptr = data_ptr;
2611}
2612
2613static void
2614qla8044_minidump_process_queue(struct scsi_qla_host *vha,
2615        struct qla8044_minidump_entry_hdr *entry_hdr,
2616        uint32_t **d_ptr)
2617{
2618        uint32_t s_addr, r_addr;
2619        uint32_t r_stride, r_value, r_cnt, qid = 0;
2620        uint32_t i, k, loop_cnt;
2621        struct qla8044_minidump_entry_queue *q_hdr;
2622        uint32_t *data_ptr = *d_ptr;
2623
2624        ql_dbg(ql_dbg_p3p, vha, 0xb0fd, "Entering fn: %s\n", __func__);
2625        q_hdr = (struct qla8044_minidump_entry_queue *)entry_hdr;
2626        s_addr = q_hdr->select_addr;
2627        r_cnt = q_hdr->rd_strd.read_addr_cnt;
2628        r_stride = q_hdr->rd_strd.read_addr_stride;
2629        loop_cnt = q_hdr->op_count;
2630
2631        for (i = 0; i < loop_cnt; i++) {
2632                qla8044_wr_reg_indirect(vha, s_addr, qid);
2633                r_addr = q_hdr->read_addr;
2634                for (k = 0; k < r_cnt; k++) {
2635                        qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2636                        *data_ptr++ = r_value;
2637                        r_addr += r_stride;
2638                }
2639                qid += q_hdr->q_strd.queue_id_stride;
2640        }
2641        *d_ptr = data_ptr;
2642}
2643
2644/* ISP83xx functions to process new minidump entries... */
2645static uint32_t
2646qla8044_minidump_process_pollrd(struct scsi_qla_host *vha,
2647        struct qla8044_minidump_entry_hdr *entry_hdr,
2648        uint32_t **d_ptr)
2649{
2650        uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask;
2651        uint16_t s_stride, i;
2652        struct qla8044_minidump_entry_pollrd *pollrd_hdr;
2653        uint32_t *data_ptr = *d_ptr;
2654
2655        pollrd_hdr = (struct qla8044_minidump_entry_pollrd *) entry_hdr;
2656        s_addr = pollrd_hdr->select_addr;
2657        r_addr = pollrd_hdr->read_addr;
2658        s_value = pollrd_hdr->select_value;
2659        s_stride = pollrd_hdr->select_value_stride;
2660
2661        poll_wait = pollrd_hdr->poll_wait;
2662        poll_mask = pollrd_hdr->poll_mask;
2663
2664        for (i = 0; i < pollrd_hdr->op_count; i++) {
2665                qla8044_wr_reg_indirect(vha, s_addr, s_value);
2666                poll_wait = pollrd_hdr->poll_wait;
2667                while (1) {
2668                        qla8044_rd_reg_indirect(vha, s_addr, &r_value);
2669                        if ((r_value & poll_mask) != 0) {
2670                                break;
2671                        } else {
2672                                usleep_range(1000, 1100);
2673                                if (--poll_wait == 0) {
2674                                        ql_log(ql_log_fatal, vha, 0xb0fe,
2675                                            "%s: TIMEOUT\n", __func__);
2676                                        goto error;
2677                                }
2678                        }
2679                }
2680                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2681                *data_ptr++ = s_value;
2682                *data_ptr++ = r_value;
2683
2684                s_value += s_stride;
2685        }
2686        *d_ptr = data_ptr;
2687        return QLA_SUCCESS;
2688
2689error:
2690        return QLA_FUNCTION_FAILED;
2691}
2692
2693static void
2694qla8044_minidump_process_rdmux2(struct scsi_qla_host *vha,
2695        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2696{
2697        uint32_t sel_val1, sel_val2, t_sel_val, data, i;
2698        uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr;
2699        struct qla8044_minidump_entry_rdmux2 *rdmux2_hdr;
2700        uint32_t *data_ptr = *d_ptr;
2701
2702        rdmux2_hdr = (struct qla8044_minidump_entry_rdmux2 *) entry_hdr;
2703        sel_val1 = rdmux2_hdr->select_value_1;
2704        sel_val2 = rdmux2_hdr->select_value_2;
2705        sel_addr1 = rdmux2_hdr->select_addr_1;
2706        sel_addr2 = rdmux2_hdr->select_addr_2;
2707        sel_val_mask = rdmux2_hdr->select_value_mask;
2708        read_addr = rdmux2_hdr->read_addr;
2709
2710        for (i = 0; i < rdmux2_hdr->op_count; i++) {
2711                qla8044_wr_reg_indirect(vha, sel_addr1, sel_val1);
2712                t_sel_val = sel_val1 & sel_val_mask;
2713                *data_ptr++ = t_sel_val;
2714
2715                qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2716                qla8044_rd_reg_indirect(vha, read_addr, &data);
2717
2718                *data_ptr++ = data;
2719
2720                qla8044_wr_reg_indirect(vha, sel_addr1, sel_val2);
2721                t_sel_val = sel_val2 & sel_val_mask;
2722                *data_ptr++ = t_sel_val;
2723
2724                qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2725                qla8044_rd_reg_indirect(vha, read_addr, &data);
2726
2727                *data_ptr++ = data;
2728
2729                sel_val1 += rdmux2_hdr->select_value_stride;
2730                sel_val2 += rdmux2_hdr->select_value_stride;
2731        }
2732
2733        *d_ptr = data_ptr;
2734}
2735
2736static uint32_t
2737qla8044_minidump_process_pollrdmwr(struct scsi_qla_host *vha,
2738        struct qla8044_minidump_entry_hdr *entry_hdr,
2739        uint32_t **d_ptr)
2740{
2741        uint32_t poll_wait, poll_mask, r_value, data;
2742        uint32_t addr_1, addr_2, value_1, value_2;
2743        struct qla8044_minidump_entry_pollrdmwr *poll_hdr;
2744        uint32_t *data_ptr = *d_ptr;
2745
2746        poll_hdr = (struct qla8044_minidump_entry_pollrdmwr *) entry_hdr;
2747        addr_1 = poll_hdr->addr_1;
2748        addr_2 = poll_hdr->addr_2;
2749        value_1 = poll_hdr->value_1;
2750        value_2 = poll_hdr->value_2;
2751        poll_mask = poll_hdr->poll_mask;
2752
2753        qla8044_wr_reg_indirect(vha, addr_1, value_1);
2754
2755        poll_wait = poll_hdr->poll_wait;
2756        while (1) {
2757                qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2758
2759                if ((r_value & poll_mask) != 0) {
2760                        break;
2761                } else {
2762                        usleep_range(1000, 1100);
2763                        if (--poll_wait == 0) {
2764                                ql_log(ql_log_fatal, vha, 0xb0ff,
2765                                    "%s: TIMEOUT\n", __func__);
2766                                goto error;
2767                        }
2768                }
2769        }
2770
2771        qla8044_rd_reg_indirect(vha, addr_2, &data);
2772        data &= poll_hdr->modify_mask;
2773        qla8044_wr_reg_indirect(vha, addr_2, data);
2774        qla8044_wr_reg_indirect(vha, addr_1, value_2);
2775
2776        poll_wait = poll_hdr->poll_wait;
2777        while (1) {
2778                qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2779
2780                if ((r_value & poll_mask) != 0) {
2781                        break;
2782                } else {
2783                        usleep_range(1000, 1100);
2784                        if (--poll_wait == 0) {
2785                                ql_log(ql_log_fatal, vha, 0xb100,
2786                                    "%s: TIMEOUT2\n", __func__);
2787                                goto error;
2788                        }
2789                }
2790        }
2791
2792        *data_ptr++ = addr_2;
2793        *data_ptr++ = data;
2794
2795        *d_ptr = data_ptr;
2796
2797        return QLA_SUCCESS;
2798
2799error:
2800        return QLA_FUNCTION_FAILED;
2801}
2802
2803#define ISP8044_PEX_DMA_ENGINE_INDEX            8
2804#define ISP8044_PEX_DMA_BASE_ADDRESS            0x77320000
2805#define ISP8044_PEX_DMA_NUM_OFFSET              0x10000UL
2806#define ISP8044_PEX_DMA_CMD_ADDR_LOW            0x0
2807#define ISP8044_PEX_DMA_CMD_ADDR_HIGH           0x04
2808#define ISP8044_PEX_DMA_CMD_STS_AND_CNTRL       0x08
2809
2810#define ISP8044_PEX_DMA_READ_SIZE       (16 * 1024)
2811#define ISP8044_PEX_DMA_MAX_WAIT        (100 * 100) /* Max wait of 100 msecs */
2812
2813static int
2814qla8044_check_dma_engine_state(struct scsi_qla_host *vha)
2815{
2816        struct qla_hw_data *ha = vha->hw;
2817        int rval = QLA_SUCCESS;
2818        uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2819        uint64_t dma_base_addr = 0;
2820        struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2821
2822        tmplt_hdr = ha->md_tmplt_hdr;
2823        dma_eng_num =
2824            tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2825        dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2826                (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2827
2828        /* Read the pex-dma's command-status-and-control register. */
2829        rval = qla8044_rd_reg_indirect(vha,
2830            (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2831            &cmd_sts_and_cntrl);
2832        if (rval)
2833                return QLA_FUNCTION_FAILED;
2834
2835        /* Check if requested pex-dma engine is available. */
2836        if (cmd_sts_and_cntrl & BIT_31)
2837                return QLA_SUCCESS;
2838
2839        return QLA_FUNCTION_FAILED;
2840}
2841
2842static int
2843qla8044_start_pex_dma(struct scsi_qla_host *vha,
2844        struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr)
2845{
2846        struct qla_hw_data *ha = vha->hw;
2847        int rval = QLA_SUCCESS, wait = 0;
2848        uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2849        uint64_t dma_base_addr = 0;
2850        struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2851
2852        tmplt_hdr = ha->md_tmplt_hdr;
2853        dma_eng_num =
2854            tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2855        dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2856                (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2857
2858        rval = qla8044_wr_reg_indirect(vha,
2859            dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_LOW,
2860            m_hdr->desc_card_addr);
2861        if (rval)
2862                goto error_exit;
2863
2864        rval = qla8044_wr_reg_indirect(vha,
2865            dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_HIGH, 0);
2866        if (rval)
2867                goto error_exit;
2868
2869        rval = qla8044_wr_reg_indirect(vha,
2870            dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL,
2871            m_hdr->start_dma_cmd);
2872        if (rval)
2873                goto error_exit;
2874
2875        /* Wait for dma operation to complete. */
2876        for (wait = 0; wait < ISP8044_PEX_DMA_MAX_WAIT; wait++) {
2877                rval = qla8044_rd_reg_indirect(vha,
2878                    (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2879                    &cmd_sts_and_cntrl);
2880                if (rval)
2881                        goto error_exit;
2882
2883                if ((cmd_sts_and_cntrl & BIT_1) == 0)
2884                        break;
2885
2886                udelay(10);
2887        }
2888
2889        /* Wait a max of 100 ms, otherwise fallback to rdmem entry read */
2890        if (wait >= ISP8044_PEX_DMA_MAX_WAIT) {
2891                rval = QLA_FUNCTION_FAILED;
2892                goto error_exit;
2893        }
2894
2895error_exit:
2896        return rval;
2897}
2898
2899static int
2900qla8044_minidump_pex_dma_read(struct scsi_qla_host *vha,
2901        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2902{
2903        struct qla_hw_data *ha = vha->hw;
2904        int rval = QLA_SUCCESS;
2905        struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr = NULL;
2906        uint32_t chunk_size, read_size;
2907        uint8_t *data_ptr = (uint8_t *)*d_ptr;
2908        void *rdmem_buffer = NULL;
2909        dma_addr_t rdmem_dma;
2910        struct qla8044_pex_dma_descriptor dma_desc;
2911
2912        rval = qla8044_check_dma_engine_state(vha);
2913        if (rval != QLA_SUCCESS) {
2914                ql_dbg(ql_dbg_p3p, vha, 0xb147,
2915                    "DMA engine not available. Fallback to rdmem-read.\n");
2916                return QLA_FUNCTION_FAILED;
2917        }
2918
2919        m_hdr = (void *)entry_hdr;
2920
2921        rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev,
2922            ISP8044_PEX_DMA_READ_SIZE, &rdmem_dma, GFP_KERNEL);
2923        if (!rdmem_buffer) {
2924                ql_dbg(ql_dbg_p3p, vha, 0xb148,
2925                    "Unable to allocate rdmem dma buffer\n");
2926                return QLA_FUNCTION_FAILED;
2927        }
2928
2929        /* Prepare pex-dma descriptor to be written to MS memory. */
2930        /* dma-desc-cmd layout:
2931         *              0-3: dma-desc-cmd 0-3
2932         *              4-7: pcid function number
2933         *              8-15: dma-desc-cmd 8-15
2934         * dma_bus_addr: dma buffer address
2935         * cmd.read_data_size: amount of data-chunk to be read.
2936         */
2937        dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f);
2938        dma_desc.cmd.dma_desc_cmd |=
2939            ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4);
2940
2941        dma_desc.dma_bus_addr = rdmem_dma;
2942        dma_desc.cmd.read_data_size = chunk_size = ISP8044_PEX_DMA_READ_SIZE;
2943        read_size = 0;
2944
2945        /*
2946         * Perform rdmem operation using pex-dma.
2947         * Prepare dma in chunks of ISP8044_PEX_DMA_READ_SIZE.
2948         */
2949        while (read_size < m_hdr->read_data_size) {
2950                if (m_hdr->read_data_size - read_size <
2951                    ISP8044_PEX_DMA_READ_SIZE) {
2952                        chunk_size = (m_hdr->read_data_size - read_size);
2953                        dma_desc.cmd.read_data_size = chunk_size;
2954                }
2955
2956                dma_desc.src_addr = m_hdr->read_addr + read_size;
2957
2958                /* Prepare: Write pex-dma descriptor to MS memory. */
2959                rval = qla8044_ms_mem_write_128b(vha,
2960                    m_hdr->desc_card_addr, (uint32_t *)&dma_desc,
2961                    (sizeof(struct qla8044_pex_dma_descriptor)/16));
2962                if (rval) {
2963                        ql_log(ql_log_warn, vha, 0xb14a,
2964                            "%s: Error writing rdmem-dma-init to MS !!!\n",
2965                            __func__);
2966                        goto error_exit;
2967                }
2968                ql_dbg(ql_dbg_p3p, vha, 0xb14b,
2969                    "%s: Dma-descriptor: Instruct for rdmem dma "
2970                    "(chunk_size 0x%x).\n", __func__, chunk_size);
2971
2972                /* Execute: Start pex-dma operation. */
2973                rval = qla8044_start_pex_dma(vha, m_hdr);
2974                if (rval)
2975                        goto error_exit;
2976
2977                memcpy(data_ptr, rdmem_buffer, chunk_size);
2978                data_ptr += chunk_size;
2979                read_size += chunk_size;
2980        }
2981
2982        *d_ptr = (uint32_t *)data_ptr;
2983
2984error_exit:
2985        if (rdmem_buffer)
2986                dma_free_coherent(&ha->pdev->dev, ISP8044_PEX_DMA_READ_SIZE,
2987                    rdmem_buffer, rdmem_dma);
2988
2989        return rval;
2990}
2991
2992static uint32_t
2993qla8044_minidump_process_rddfe(struct scsi_qla_host *vha,
2994        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2995{
2996        int loop_cnt;
2997        uint32_t addr1, addr2, value, data, temp, wrVal;
2998        uint8_t stride, stride2;
2999        uint16_t count;
3000        uint32_t poll, mask, modify_mask;
3001        uint32_t wait_count = 0;
3002        uint32_t *data_ptr = *d_ptr;
3003        struct qla8044_minidump_entry_rddfe *rddfe;
3004
3005        rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr;
3006
3007        addr1 = rddfe->addr_1;
3008        value = rddfe->value;
3009        stride = rddfe->stride;
3010        stride2 = rddfe->stride2;
3011        count = rddfe->count;
3012
3013        poll = rddfe->poll;
3014        mask = rddfe->mask;
3015        modify_mask = rddfe->modify_mask;
3016
3017        addr2 = addr1 + stride;
3018
3019        for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) {
3020                qla8044_wr_reg_indirect(vha, addr1, (0x40000000 | value));
3021
3022                wait_count = 0;
3023                while (wait_count < poll) {
3024                        qla8044_rd_reg_indirect(vha, addr1, &temp);
3025                        if ((temp & mask) != 0)
3026                                break;
3027                        wait_count++;
3028                }
3029
3030                if (wait_count == poll) {
3031                        ql_log(ql_log_warn, vha, 0xb153,
3032                            "%s: TIMEOUT\n", __func__);
3033                        goto error;
3034                } else {
3035                        qla8044_rd_reg_indirect(vha, addr2, &temp);
3036                        temp = temp & modify_mask;
3037                        temp = (temp | ((loop_cnt << 16) | loop_cnt));
3038                        wrVal = ((temp << 16) | temp);
3039
3040                        qla8044_wr_reg_indirect(vha, addr2, wrVal);
3041                        qla8044_wr_reg_indirect(vha, addr1, value);
3042
3043                        wait_count = 0;
3044                        while (wait_count < poll) {
3045                                qla8044_rd_reg_indirect(vha, addr1, &temp);
3046                                if ((temp & mask) != 0)
3047                                        break;
3048                                wait_count++;
3049                        }
3050                        if (wait_count == poll) {
3051                                ql_log(ql_log_warn, vha, 0xb154,
3052                                    "%s: TIMEOUT\n", __func__);
3053                                goto error;
3054                        }
3055
3056                        qla8044_wr_reg_indirect(vha, addr1,
3057                            ((0x40000000 | value) + stride2));
3058                        wait_count = 0;
3059                        while (wait_count < poll) {
3060                                qla8044_rd_reg_indirect(vha, addr1, &temp);
3061                                if ((temp & mask) != 0)
3062                                        break;
3063                                wait_count++;
3064                        }
3065
3066                        if (wait_count == poll) {
3067                                ql_log(ql_log_warn, vha, 0xb155,
3068                                    "%s: TIMEOUT\n", __func__);
3069                                goto error;
3070                        }
3071
3072                        qla8044_rd_reg_indirect(vha, addr2, &data);
3073
3074                        *data_ptr++ = wrVal;
3075                        *data_ptr++ = data;
3076                }
3077
3078        }
3079
3080        *d_ptr = data_ptr;
3081        return QLA_SUCCESS;
3082
3083error:
3084        return -1;
3085
3086}
3087
3088static uint32_t
3089qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha,
3090        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3091{
3092        int ret = 0;
3093        uint32_t addr1, addr2, value1, value2, data, selVal;
3094        uint8_t stride1, stride2;
3095        uint32_t addr3, addr4, addr5, addr6, addr7;
3096        uint16_t count, loop_cnt;
3097        uint32_t mask;
3098        uint32_t *data_ptr = *d_ptr;
3099
3100        struct qla8044_minidump_entry_rdmdio *rdmdio;
3101
3102        rdmdio = (struct qla8044_minidump_entry_rdmdio *) entry_hdr;
3103
3104        addr1 = rdmdio->addr_1;
3105        addr2 = rdmdio->addr_2;
3106        value1 = rdmdio->value_1;
3107        stride1 = rdmdio->stride_1;
3108        stride2 = rdmdio->stride_2;
3109        count = rdmdio->count;
3110
3111        mask = rdmdio->mask;
3112        value2 = rdmdio->value_2;
3113
3114        addr3 = addr1 + stride1;
3115
3116        for (loop_cnt = 0; loop_cnt < count; loop_cnt++) {
3117                ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3118                    addr3, mask);
3119                if (ret == -1)
3120                        goto error;
3121
3122                addr4 = addr2 - stride1;
3123                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr4,
3124                    value2);
3125                if (ret == -1)
3126                        goto error;
3127
3128                addr5 = addr2 - (2 * stride1);
3129                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr5,
3130                    value1);
3131                if (ret == -1)
3132                        goto error;
3133
3134                addr6 = addr2 - (3 * stride1);
3135                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask,
3136                    addr6, 0x2);
3137                if (ret == -1)
3138                        goto error;
3139
3140                ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3141                    addr3, mask);
3142                if (ret == -1)
3143                        goto error;
3144
3145                addr7 = addr2 - (4 * stride1);
3146                data = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr7);
3147                if (data == -1)
3148                        goto error;
3149
3150                selVal = (value2 << 18) | (value1 << 2) | 2;
3151
3152                stride2 = rdmdio->stride_2;
3153                *data_ptr++ = selVal;
3154                *data_ptr++ = data;
3155
3156                value1 = value1 + stride2;
3157                *d_ptr = data_ptr;
3158        }
3159
3160        return 0;
3161
3162error:
3163        return -1;
3164}
3165
3166static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha,
3167                struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3168{
3169        uint32_t addr1, addr2, value1, value2, poll, r_value;
3170        uint32_t wait_count = 0;
3171        struct qla8044_minidump_entry_pollwr *pollwr_hdr;
3172
3173        pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr;
3174        addr1 = pollwr_hdr->addr_1;
3175        addr2 = pollwr_hdr->addr_2;
3176        value1 = pollwr_hdr->value_1;
3177        value2 = pollwr_hdr->value_2;
3178
3179        poll = pollwr_hdr->poll;
3180
3181        while (wait_count < poll) {
3182                qla8044_rd_reg_indirect(vha, addr1, &r_value);
3183
3184                if ((r_value & poll) != 0)
3185                        break;
3186                wait_count++;
3187        }
3188
3189        if (wait_count == poll) {
3190                ql_log(ql_log_warn, vha, 0xb156, "%s: TIMEOUT\n", __func__);
3191                goto error;
3192        }
3193
3194        qla8044_wr_reg_indirect(vha, addr2, value2);
3195        qla8044_wr_reg_indirect(vha, addr1, value1);
3196
3197        wait_count = 0;
3198        while (wait_count < poll) {
3199                qla8044_rd_reg_indirect(vha, addr1, &r_value);
3200
3201                if ((r_value & poll) != 0)
3202                        break;
3203                wait_count++;
3204        }
3205
3206        return QLA_SUCCESS;
3207
3208error:
3209        return -1;
3210}
3211
3212/*
3213 *
3214 * qla8044_collect_md_data - Retrieve firmware minidump data.
3215 * @ha: pointer to adapter structure
3216 **/
3217int
3218qla8044_collect_md_data(struct scsi_qla_host *vha)
3219{
3220        int num_entry_hdr = 0;
3221        struct qla8044_minidump_entry_hdr *entry_hdr;
3222        struct qla8044_minidump_template_hdr *tmplt_hdr;
3223        uint32_t *data_ptr;
3224        uint32_t data_collected = 0, f_capture_mask;
3225        int i, rval = QLA_FUNCTION_FAILED;
3226        uint64_t now;
3227        uint32_t timestamp, idc_control;
3228        struct qla_hw_data *ha = vha->hw;
3229
3230        if (!ha->md_dump) {
3231                ql_log(ql_log_info, vha, 0xb101,
3232                    "%s(%ld) No buffer to dump\n",
3233                    __func__, vha->host_no);
3234                return rval;
3235        }
3236
3237        if (ha->fw_dumped) {
3238                ql_log(ql_log_warn, vha, 0xb10d,
3239                    "Firmware has been previously dumped (%p) "
3240                    "-- ignoring request.\n", ha->fw_dump);
3241                goto md_failed;
3242        }
3243
3244        ha->fw_dumped = false;
3245
3246        if (!ha->md_tmplt_hdr || !ha->md_dump) {
3247                ql_log(ql_log_warn, vha, 0xb10e,
3248                    "Memory not allocated for minidump capture\n");
3249                goto md_failed;
3250        }
3251
3252        qla8044_idc_lock(ha);
3253        idc_control = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3254        if (idc_control & GRACEFUL_RESET_BIT1) {
3255                ql_log(ql_log_warn, vha, 0xb112,
3256                    "Forced reset from application, "
3257                    "ignore minidump capture\n");
3258                qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
3259                    (idc_control & ~GRACEFUL_RESET_BIT1));
3260                qla8044_idc_unlock(ha);
3261
3262                goto md_failed;
3263        }
3264        qla8044_idc_unlock(ha);
3265
3266        if (qla82xx_validate_template_chksum(vha)) {
3267                ql_log(ql_log_info, vha, 0xb109,
3268                    "Template checksum validation error\n");
3269                goto md_failed;
3270        }
3271
3272        tmplt_hdr = (struct qla8044_minidump_template_hdr *)
3273                ha->md_tmplt_hdr;
3274        data_ptr = (uint32_t *)((uint8_t *)ha->md_dump);
3275        num_entry_hdr = tmplt_hdr->num_of_entries;
3276
3277        ql_dbg(ql_dbg_p3p, vha, 0xb11a,
3278            "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
3279
3280        f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
3281
3282        /* Validate whether required debug level is set */
3283        if ((f_capture_mask & 0x3) != 0x3) {
3284                ql_log(ql_log_warn, vha, 0xb10f,
3285                    "Minimum required capture mask[0x%x] level not set\n",
3286                    f_capture_mask);
3287
3288        }
3289        tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
3290        ql_log(ql_log_info, vha, 0xb102,
3291            "[%s]: starting data ptr: %p\n",
3292           __func__, data_ptr);
3293        ql_log(ql_log_info, vha, 0xb10b,
3294           "[%s]: no of entry headers in Template: 0x%x\n",
3295           __func__, num_entry_hdr);
3296        ql_log(ql_log_info, vha, 0xb10c,
3297            "[%s]: Total_data_size 0x%x, %d obtained\n",
3298           __func__, ha->md_dump_size, ha->md_dump_size);
3299
3300        /* Update current timestamp before taking dump */
3301        now = get_jiffies_64();
3302        timestamp = (u32)(jiffies_to_msecs(now) / 1000);
3303        tmplt_hdr->driver_timestamp = timestamp;
3304
3305        entry_hdr = (struct qla8044_minidump_entry_hdr *)
3306                (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
3307        tmplt_hdr->saved_state_array[QLA8044_SS_OCM_WNDREG_INDEX] =
3308            tmplt_hdr->ocm_window_reg[ha->portnum];
3309
3310        /* Walk through the entry headers - validate/perform required action */
3311        for (i = 0; i < num_entry_hdr; i++) {
3312                if (data_collected > ha->md_dump_size) {
3313                        ql_log(ql_log_info, vha, 0xb103,
3314                            "Data collected: [0x%x], "
3315                            "Total Dump size: [0x%x]\n",
3316                            data_collected, ha->md_dump_size);
3317                        return rval;
3318                }
3319
3320                if (!(entry_hdr->d_ctrl.entry_capture_mask &
3321                      ql2xmdcapmask)) {
3322                        entry_hdr->d_ctrl.driver_flags |=
3323                            QLA82XX_DBG_SKIPPED_FLAG;
3324                        goto skip_nxt_entry;
3325                }
3326
3327                ql_dbg(ql_dbg_p3p, vha, 0xb104,
3328                    "Data collected: [0x%x], Dump size left:[0x%x]\n",
3329                    data_collected,
3330                    (ha->md_dump_size - data_collected));
3331
3332                /* Decode the entry type and take required action to capture
3333                 * debug data
3334                 */
3335                switch (entry_hdr->entry_type) {
3336                case QLA82XX_RDEND:
3337                        qla8044_mark_entry_skipped(vha, entry_hdr, i);
3338                        break;
3339                case QLA82XX_CNTRL:
3340                        rval = qla8044_minidump_process_control(vha,
3341                            entry_hdr);
3342                        if (rval != QLA_SUCCESS) {
3343                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3344                                goto md_failed;
3345                        }
3346                        break;
3347                case QLA82XX_RDCRB:
3348                        qla8044_minidump_process_rdcrb(vha,
3349                            entry_hdr, &data_ptr);
3350                        break;
3351                case QLA82XX_RDMEM:
3352                        rval = qla8044_minidump_pex_dma_read(vha,
3353                            entry_hdr, &data_ptr);
3354                        if (rval != QLA_SUCCESS) {
3355                                rval = qla8044_minidump_process_rdmem(vha,
3356                                    entry_hdr, &data_ptr);
3357                                if (rval != QLA_SUCCESS) {
3358                                        qla8044_mark_entry_skipped(vha,
3359                                            entry_hdr, i);
3360                                        goto md_failed;
3361                                }
3362                        }
3363                        break;
3364                case QLA82XX_BOARD:
3365                case QLA82XX_RDROM:
3366                        rval = qla8044_minidump_process_rdrom(vha,
3367                            entry_hdr, &data_ptr);
3368                        if (rval != QLA_SUCCESS) {
3369                                qla8044_mark_entry_skipped(vha,
3370                                    entry_hdr, i);
3371                        }
3372                        break;
3373                case QLA82XX_L2DTG:
3374                case QLA82XX_L2ITG:
3375                case QLA82XX_L2DAT:
3376                case QLA82XX_L2INS:
3377                        rval = qla8044_minidump_process_l2tag(vha,
3378                            entry_hdr, &data_ptr);
3379                        if (rval != QLA_SUCCESS) {
3380                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3381                                goto md_failed;
3382                        }
3383                        break;
3384                case QLA8044_L1DTG:
3385                case QLA8044_L1ITG:
3386                case QLA82XX_L1DAT:
3387                case QLA82XX_L1INS:
3388                        qla8044_minidump_process_l1cache(vha,
3389                            entry_hdr, &data_ptr);
3390                        break;
3391                case QLA82XX_RDOCM:
3392                        qla8044_minidump_process_rdocm(vha,
3393                            entry_hdr, &data_ptr);
3394                        break;
3395                case QLA82XX_RDMUX:
3396                        qla8044_minidump_process_rdmux(vha,
3397                            entry_hdr, &data_ptr);
3398                        break;
3399                case QLA82XX_QUEUE:
3400                        qla8044_minidump_process_queue(vha,
3401                            entry_hdr, &data_ptr);
3402                        break;
3403                case QLA8044_POLLRD:
3404                        rval = qla8044_minidump_process_pollrd(vha,
3405                            entry_hdr, &data_ptr);
3406                        if (rval != QLA_SUCCESS)
3407                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3408                        break;
3409                case QLA8044_RDMUX2:
3410                        qla8044_minidump_process_rdmux2(vha,
3411                            entry_hdr, &data_ptr);
3412                        break;
3413                case QLA8044_POLLRDMWR:
3414                        rval = qla8044_minidump_process_pollrdmwr(vha,
3415                            entry_hdr, &data_ptr);
3416                        if (rval != QLA_SUCCESS)
3417                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3418                        break;
3419                case QLA8044_RDDFE:
3420                        rval = qla8044_minidump_process_rddfe(vha, entry_hdr,
3421                            &data_ptr);
3422                        if (rval != QLA_SUCCESS)
3423                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3424                        break;
3425                case QLA8044_RDMDIO:
3426                        rval = qla8044_minidump_process_rdmdio(vha, entry_hdr,
3427                            &data_ptr);
3428                        if (rval != QLA_SUCCESS)
3429                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3430                        break;
3431                case QLA8044_POLLWR:
3432                        rval = qla8044_minidump_process_pollwr(vha, entry_hdr,
3433                            &data_ptr);
3434                        if (rval != QLA_SUCCESS)
3435                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3436                        break;
3437                case QLA82XX_RDNOP:
3438                default:
3439                        qla8044_mark_entry_skipped(vha, entry_hdr, i);
3440                        break;
3441                }
3442
3443                data_collected = (uint8_t *)data_ptr -
3444                    (uint8_t *)((uint8_t *)ha->md_dump);
3445skip_nxt_entry:
3446                /*
3447                 * next entry in the template
3448                 */
3449                entry_hdr = (struct qla8044_minidump_entry_hdr *)
3450                    (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
3451        }
3452
3453        if (data_collected != ha->md_dump_size) {
3454                ql_log(ql_log_info, vha, 0xb105,
3455                    "Dump data mismatch: Data collected: "
3456                    "[0x%x], total_data_size:[0x%x]\n",
3457                    data_collected, ha->md_dump_size);
3458                rval = QLA_FUNCTION_FAILED;
3459                goto md_failed;
3460        }
3461
3462        ql_log(ql_log_info, vha, 0xb110,
3463            "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
3464            vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
3465        ha->fw_dumped = true;
3466        qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
3467
3468
3469        ql_log(ql_log_info, vha, 0xb106,
3470            "Leaving fn: %s Last entry: 0x%x\n",
3471            __func__, i);
3472md_failed:
3473        return rval;
3474}
3475
3476void
3477qla8044_get_minidump(struct scsi_qla_host *vha)
3478{
3479        struct qla_hw_data *ha = vha->hw;
3480
3481        if (!qla8044_collect_md_data(vha)) {
3482                ha->fw_dumped = true;
3483                ha->prev_minidump_failed = 0;
3484        } else {
3485                ql_log(ql_log_fatal, vha, 0xb0db,
3486                    "%s: Unable to collect minidump\n",
3487                    __func__);
3488                ha->prev_minidump_failed = 1;
3489        }
3490}
3491
3492static int
3493qla8044_poll_flash_status_reg(struct scsi_qla_host *vha)
3494{
3495        uint32_t flash_status;
3496        int retries = QLA8044_FLASH_READ_RETRY_COUNT;
3497        int ret_val = QLA_SUCCESS;
3498
3499        while (retries--) {
3500                ret_val = qla8044_rd_reg_indirect(vha, QLA8044_FLASH_STATUS,
3501                    &flash_status);
3502                if (ret_val) {
3503                        ql_log(ql_log_warn, vha, 0xb13c,
3504                            "%s: Failed to read FLASH_STATUS reg.\n",
3505                            __func__);
3506                        break;
3507                }
3508                if ((flash_status & QLA8044_FLASH_STATUS_READY) ==
3509                    QLA8044_FLASH_STATUS_READY)
3510                        break;
3511                msleep(QLA8044_FLASH_STATUS_REG_POLL_DELAY);
3512        }
3513
3514        if (!retries)
3515                ret_val = QLA_FUNCTION_FAILED;
3516
3517        return ret_val;
3518}
3519
3520static int
3521qla8044_write_flash_status_reg(struct scsi_qla_host *vha,
3522                               uint32_t data)
3523{
3524        int ret_val = QLA_SUCCESS;
3525        uint32_t cmd;
3526
3527        cmd = vha->hw->fdt_wrt_sts_reg_cmd;
3528
3529        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3530            QLA8044_FLASH_STATUS_WRITE_DEF_SIG | cmd);
3531        if (ret_val) {
3532                ql_log(ql_log_warn, vha, 0xb125,
3533                    "%s: Failed to write to FLASH_ADDR.\n", __func__);
3534                goto exit_func;
3535        }
3536
3537        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, data);
3538        if (ret_val) {
3539                ql_log(ql_log_warn, vha, 0xb126,
3540                    "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3541                goto exit_func;
3542        }
3543
3544        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3545            QLA8044_FLASH_SECOND_ERASE_MS_VAL);
3546        if (ret_val) {
3547                ql_log(ql_log_warn, vha, 0xb127,
3548                    "%s: Failed to write to FLASH_CONTROL.\n", __func__);
3549                goto exit_func;
3550        }
3551
3552        ret_val = qla8044_poll_flash_status_reg(vha);
3553        if (ret_val)
3554                ql_log(ql_log_warn, vha, 0xb128,
3555                    "%s: Error polling flash status reg.\n", __func__);
3556
3557exit_func:
3558        return ret_val;
3559}
3560
3561/*
3562 * This function assumes that the flash lock is held.
3563 */
3564static int
3565qla8044_unprotect_flash(scsi_qla_host_t *vha)
3566{
3567        int ret_val;
3568        struct qla_hw_data *ha = vha->hw;
3569
3570        ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_enable);
3571        if (ret_val)
3572                ql_log(ql_log_warn, vha, 0xb139,
3573                    "%s: Write flash status failed.\n", __func__);
3574
3575        return ret_val;
3576}
3577
3578/*
3579 * This function assumes that the flash lock is held.
3580 */
3581static int
3582qla8044_protect_flash(scsi_qla_host_t *vha)
3583{
3584        int ret_val;
3585        struct qla_hw_data *ha = vha->hw;
3586
3587        ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_disable);
3588        if (ret_val)
3589                ql_log(ql_log_warn, vha, 0xb13b,
3590                    "%s: Write flash status failed.\n", __func__);
3591
3592        return ret_val;
3593}
3594
3595
3596static int
3597qla8044_erase_flash_sector(struct scsi_qla_host *vha,
3598                           uint32_t sector_start_addr)
3599{
3600        uint32_t reversed_addr;
3601        int ret_val = QLA_SUCCESS;
3602
3603        ret_val = qla8044_poll_flash_status_reg(vha);
3604        if (ret_val) {
3605                ql_log(ql_log_warn, vha, 0xb12e,
3606                    "%s: Poll flash status after erase failed..\n", __func__);
3607        }
3608
3609        reversed_addr = (((sector_start_addr & 0xFF) << 16) |
3610            (sector_start_addr & 0xFF00) |
3611            ((sector_start_addr & 0xFF0000) >> 16));
3612
3613        ret_val = qla8044_wr_reg_indirect(vha,
3614            QLA8044_FLASH_WRDATA, reversed_addr);
3615        if (ret_val) {
3616                ql_log(ql_log_warn, vha, 0xb12f,
3617                    "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3618        }
3619        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3620           QLA8044_FLASH_ERASE_SIG | vha->hw->fdt_erase_cmd);
3621        if (ret_val) {
3622                ql_log(ql_log_warn, vha, 0xb130,
3623                    "%s: Failed to write to FLASH_ADDR.\n", __func__);
3624        }
3625        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3626            QLA8044_FLASH_LAST_ERASE_MS_VAL);
3627        if (ret_val) {
3628                ql_log(ql_log_warn, vha, 0xb131,
3629                    "%s: Failed write to FLASH_CONTROL.\n", __func__);
3630        }
3631        ret_val = qla8044_poll_flash_status_reg(vha);
3632        if (ret_val) {
3633                ql_log(ql_log_warn, vha, 0xb132,
3634                    "%s: Poll flash status failed.\n", __func__);
3635        }
3636
3637
3638        return ret_val;
3639}
3640
3641/*
3642 * qla8044_flash_write_u32 - Write data to flash
3643 *
3644 * @ha : Pointer to adapter structure
3645 * addr : Flash address to write to
3646 * p_data : Data to be written
3647 *
3648 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
3649 *
3650 * NOTE: Lock should be held on entry
3651 */
3652static int
3653qla8044_flash_write_u32(struct scsi_qla_host *vha, uint32_t addr,
3654                        uint32_t *p_data)
3655{
3656        int ret_val = QLA_SUCCESS;
3657
3658        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3659            0x00800000 | (addr >> 2));
3660        if (ret_val) {
3661                ql_log(ql_log_warn, vha, 0xb134,
3662                    "%s: Failed write to FLASH_ADDR.\n", __func__);
3663                goto exit_func;
3664        }
3665        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *p_data);
3666        if (ret_val) {
3667                ql_log(ql_log_warn, vha, 0xb135,
3668                    "%s: Failed write to FLASH_WRDATA.\n", __func__);
3669                goto exit_func;
3670        }
3671        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL, 0x3D);
3672        if (ret_val) {
3673                ql_log(ql_log_warn, vha, 0xb136,
3674                    "%s: Failed write to FLASH_CONTROL.\n", __func__);
3675                goto exit_func;
3676        }
3677        ret_val = qla8044_poll_flash_status_reg(vha);
3678        if (ret_val) {
3679                ql_log(ql_log_warn, vha, 0xb137,
3680                    "%s: Poll flash status failed.\n", __func__);
3681        }
3682
3683exit_func:
3684        return ret_val;
3685}
3686
3687static int
3688qla8044_write_flash_buffer_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3689                                uint32_t faddr, uint32_t dwords)
3690{
3691        int ret = QLA_FUNCTION_FAILED;
3692        uint32_t spi_val;
3693
3694        if (dwords < QLA8044_MIN_OPTROM_BURST_DWORDS ||
3695            dwords > QLA8044_MAX_OPTROM_BURST_DWORDS) {
3696                ql_dbg(ql_dbg_user, vha, 0xb123,
3697                    "Got unsupported dwords = 0x%x.\n",
3698                    dwords);
3699                return QLA_FUNCTION_FAILED;
3700        }
3701
3702        qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL, &spi_val);
3703        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3704            spi_val | QLA8044_FLASH_SPI_CTL);
3705        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3706            QLA8044_FLASH_FIRST_TEMP_VAL);
3707
3708        /* First DWORD write to FLASH_WRDATA */
3709        ret = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA,
3710            *dwptr++);
3711        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3712            QLA8044_FLASH_FIRST_MS_PATTERN);
3713
3714        ret = qla8044_poll_flash_status_reg(vha);
3715        if (ret) {
3716                ql_log(ql_log_warn, vha, 0xb124,
3717                    "%s: Failed.\n", __func__);
3718                goto exit_func;
3719        }
3720
3721        dwords--;
3722
3723        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3724            QLA8044_FLASH_SECOND_TEMP_VAL);
3725
3726
3727        /* Second to N-1 DWORDS writes */
3728        while (dwords != 1) {
3729                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3730                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3731                    QLA8044_FLASH_SECOND_MS_PATTERN);
3732                ret = qla8044_poll_flash_status_reg(vha);
3733                if (ret) {
3734                        ql_log(ql_log_warn, vha, 0xb129,
3735                            "%s: Failed.\n", __func__);
3736                        goto exit_func;
3737                }
3738                dwords--;
3739        }
3740
3741        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3742            QLA8044_FLASH_FIRST_TEMP_VAL | (faddr >> 2));
3743
3744        /* Last DWORD write */
3745        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3746        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3747            QLA8044_FLASH_LAST_MS_PATTERN);
3748        ret = qla8044_poll_flash_status_reg(vha);
3749        if (ret) {
3750                ql_log(ql_log_warn, vha, 0xb12a,
3751                    "%s: Failed.\n", __func__);
3752                goto exit_func;
3753        }
3754        qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_STATUS, &spi_val);
3755
3756        if ((spi_val & QLA8044_FLASH_SPI_CTL) == QLA8044_FLASH_SPI_CTL) {
3757                ql_log(ql_log_warn, vha, 0xb12b,
3758                    "%s: Failed.\n", __func__);
3759                spi_val = 0;
3760                /* Operation failed, clear error bit. */
3761                qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3762                    &spi_val);
3763                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3764                    spi_val | QLA8044_FLASH_SPI_CTL);
3765        }
3766exit_func:
3767        return ret;
3768}
3769
3770static int
3771qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3772                               uint32_t faddr, uint32_t dwords)
3773{
3774        int ret = QLA_FUNCTION_FAILED;
3775        uint32_t liter;
3776
3777        for (liter = 0; liter < dwords; liter++, faddr += 4, dwptr++) {
3778                ret = qla8044_flash_write_u32(vha, faddr, dwptr);
3779                if (ret) {
3780                        ql_dbg(ql_dbg_p3p, vha, 0xb141,
3781                            "%s: flash address=%x data=%x.\n", __func__,
3782                             faddr, *dwptr);
3783                        break;
3784                }
3785        }
3786
3787        return ret;
3788}
3789
3790int
3791qla8044_write_optrom_data(struct scsi_qla_host *vha, void *buf,
3792                          uint32_t offset, uint32_t length)
3793{
3794        int rval = QLA_FUNCTION_FAILED, i, burst_iter_count;
3795        int dword_count, erase_sec_count;
3796        uint32_t erase_offset;
3797        uint8_t *p_cache, *p_src;
3798
3799        erase_offset = offset;
3800
3801        p_cache = kcalloc(length, sizeof(uint8_t), GFP_KERNEL);
3802        if (!p_cache)
3803                return QLA_FUNCTION_FAILED;
3804
3805        memcpy(p_cache, buf, length);
3806        p_src = p_cache;
3807        dword_count = length / sizeof(uint32_t);
3808        /* Since the offset and legth are sector aligned, it will be always
3809         * multiple of burst_iter_count (64)
3810         */
3811        burst_iter_count = dword_count / QLA8044_MAX_OPTROM_BURST_DWORDS;
3812        erase_sec_count = length / QLA8044_SECTOR_SIZE;
3813
3814        /* Suspend HBA. */
3815        scsi_block_requests(vha->host);
3816        /* Lock and enable write for whole operation. */
3817        qla8044_flash_lock(vha);
3818        qla8044_unprotect_flash(vha);
3819
3820        /* Erasing the sectors */
3821        for (i = 0; i < erase_sec_count; i++) {
3822                rval = qla8044_erase_flash_sector(vha, erase_offset);
3823                ql_dbg(ql_dbg_user, vha, 0xb138,
3824                    "Done erase of sector=0x%x.\n",
3825                    erase_offset);
3826                if (rval) {
3827                        ql_log(ql_log_warn, vha, 0xb121,
3828                            "Failed to erase the sector having address: "
3829                            "0x%x.\n", erase_offset);
3830                        goto out;
3831                }
3832                erase_offset += QLA8044_SECTOR_SIZE;
3833        }
3834        ql_dbg(ql_dbg_user, vha, 0xb13f,
3835            "Got write for addr = 0x%x length=0x%x.\n",
3836            offset, length);
3837
3838        for (i = 0; i < burst_iter_count; i++) {
3839
3840                /* Go with write. */
3841                rval = qla8044_write_flash_buffer_mode(vha, (uint32_t *)p_src,
3842                    offset, QLA8044_MAX_OPTROM_BURST_DWORDS);
3843                if (rval) {
3844                        /* Buffer Mode failed skip to dword mode */
3845                        ql_log(ql_log_warn, vha, 0xb122,
3846                            "Failed to write flash in buffer mode, "
3847                            "Reverting to slow-write.\n");
3848                        rval = qla8044_write_flash_dword_mode(vha,
3849                            (uint32_t *)p_src, offset,
3850                            QLA8044_MAX_OPTROM_BURST_DWORDS);
3851                }
3852                p_src +=  sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3853                offset += sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3854        }
3855        ql_dbg(ql_dbg_user, vha, 0xb133,
3856            "Done writing.\n");
3857
3858out:
3859        qla8044_protect_flash(vha);
3860        qla8044_flash_unlock(vha);
3861        scsi_unblock_requests(vha->host);
3862        kfree(p_cache);
3863
3864        return rval;
3865}
3866
3867#define LEG_INT_PTR_B31         (1 << 31)
3868#define LEG_INT_PTR_B30         (1 << 30)
3869#define PF_BITS_MASK            (0xF << 16)
3870/**
3871 * qla8044_intr_handler() - Process interrupts for the ISP8044
3872 * @irq: interrupt number
3873 * @dev_id: SCSI driver HA context
3874 *
3875 * Called by system whenever the host adapter generates an interrupt.
3876 *
3877 * Returns handled flag.
3878 */
3879irqreturn_t
3880qla8044_intr_handler(int irq, void *dev_id)
3881{
3882        scsi_qla_host_t *vha;
3883        struct qla_hw_data *ha;
3884        struct rsp_que *rsp;
3885        struct device_reg_82xx __iomem *reg;
3886        int             status = 0;
3887        unsigned long   flags;
3888        unsigned long   iter;
3889        uint32_t        stat;
3890        uint16_t        mb[8];
3891        uint32_t leg_int_ptr = 0, pf_bit;
3892
3893        rsp = (struct rsp_que *) dev_id;
3894        if (!rsp) {
3895                ql_log(ql_log_info, NULL, 0xb143,
3896                    "%s(): NULL response queue pointer\n", __func__);
3897                return IRQ_NONE;
3898        }
3899        ha = rsp->hw;
3900        vha = pci_get_drvdata(ha->pdev);
3901
3902        if (unlikely(pci_channel_offline(ha->pdev)))
3903                return IRQ_HANDLED;
3904
3905        leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3906
3907        /* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
3908        if (!(leg_int_ptr & (LEG_INT_PTR_B31))) {
3909                ql_dbg(ql_dbg_p3p, vha, 0xb144,
3910                    "%s: Legacy Interrupt Bit 31 not set, "
3911                    "spurious interrupt!\n", __func__);
3912                return IRQ_NONE;
3913        }
3914
3915        pf_bit = ha->portnum << 16;
3916        /* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
3917        if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit) {
3918                ql_dbg(ql_dbg_p3p, vha, 0xb145,
3919                    "%s: Incorrect function ID 0x%x in "
3920                    "legacy interrupt register, "
3921                    "ha->pf_bit = 0x%x\n", __func__,
3922                    (leg_int_ptr & (PF_BITS_MASK)), pf_bit);
3923                return IRQ_NONE;
3924        }
3925
3926        /* To de-assert legacy interrupt, write 0 to Legacy Interrupt Trigger
3927         * Control register and poll till Legacy Interrupt Pointer register
3928         * bit32 is 0.
3929         */
3930        qla8044_wr_reg(ha, LEG_INTR_TRIG_OFFSET, 0);
3931        do {
3932                leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3933                if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit)
3934                        break;
3935        } while (leg_int_ptr & (LEG_INT_PTR_B30));
3936
3937        reg = &ha->iobase->isp82;
3938        spin_lock_irqsave(&ha->hardware_lock, flags);
3939        for (iter = 1; iter--; ) {
3940
3941                if (rd_reg_dword(&reg->host_int)) {
3942                        stat = rd_reg_dword(&reg->host_status);
3943                        if ((stat & HSRX_RISC_INT) == 0)
3944                                break;
3945
3946                        switch (stat & 0xff) {
3947                        case 0x1:
3948                        case 0x2:
3949                        case 0x10:
3950                        case 0x11:
3951                                qla82xx_mbx_completion(vha, MSW(stat));
3952                                status |= MBX_INTERRUPT;
3953                                break;
3954                        case 0x12:
3955                                mb[0] = MSW(stat);
3956                                mb[1] = rd_reg_word(&reg->mailbox_out[1]);
3957                                mb[2] = rd_reg_word(&reg->mailbox_out[2]);
3958                                mb[3] = rd_reg_word(&reg->mailbox_out[3]);
3959                                qla2x00_async_event(vha, rsp, mb);
3960                                break;
3961                        case 0x13:
3962                                qla24xx_process_response_queue(vha, rsp);
3963                                break;
3964                        default:
3965                                ql_dbg(ql_dbg_p3p, vha, 0xb146,
3966                                    "Unrecognized interrupt type "
3967                                    "(%d).\n", stat & 0xff);
3968                                break;
3969                        }
3970                }
3971                wrt_reg_dword(&reg->host_int, 0);
3972        }
3973
3974        qla2x00_handle_mbx_completion(ha, status);
3975        spin_unlock_irqrestore(&ha->hardware_lock, flags);
3976
3977        return IRQ_HANDLED;
3978}
3979
3980static int
3981qla8044_idc_dontreset(struct qla_hw_data *ha)
3982{
3983        uint32_t idc_ctrl;
3984
3985        idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3986        return idc_ctrl & DONTRESET_BIT0;
3987}
3988
3989static void
3990qla8044_clear_rst_ready(scsi_qla_host_t *vha)
3991{
3992        uint32_t drv_state;
3993
3994        drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
3995
3996        /*
3997         * For ISP8044, drv_active register has 1 bit per function,
3998         * shift 1 by func_num to set a bit for the function.
3999         * For ISP82xx, drv_active has 4 bits per function
4000         */
4001        drv_state &= ~(1 << vha->hw->portnum);
4002
4003        ql_dbg(ql_dbg_p3p, vha, 0xb13d,
4004            "drv_state: 0x%08x\n", drv_state);
4005        qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, drv_state);
4006}
4007
4008int
4009qla8044_abort_isp(scsi_qla_host_t *vha)
4010{
4011        int rval;
4012        uint32_t dev_state;
4013        struct qla_hw_data *ha = vha->hw;
4014
4015        qla8044_idc_lock(ha);
4016        dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
4017
4018        if (ql2xdontresethba)
4019                qla8044_set_idc_dontreset(vha);
4020
4021        /* If device_state is NEED_RESET, go ahead with
4022         * Reset,irrespective of ql2xdontresethba. This is to allow a
4023         * non-reset-owner to force a reset. Non-reset-owner sets
4024         * the IDC_CTRL BIT0 to prevent Reset-owner from doing a Reset
4025         * and then forces a Reset by setting device_state to
4026         * NEED_RESET. */
4027        if (dev_state == QLA8XXX_DEV_READY) {
4028                /* If IDC_CTRL DONTRESETHBA_BIT0 is set don't do reset
4029                 * recovery */
4030                if (qla8044_idc_dontreset(ha) == DONTRESET_BIT0) {
4031                        ql_dbg(ql_dbg_p3p, vha, 0xb13e,
4032                            "Reset recovery disabled\n");
4033                        rval = QLA_FUNCTION_FAILED;
4034                        goto exit_isp_reset;
4035                }
4036
4037                ql_dbg(ql_dbg_p3p, vha, 0xb140,
4038                    "HW State: NEED RESET\n");
4039                qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
4040                    QLA8XXX_DEV_NEED_RESET);
4041        }
4042
4043        /* For ISP8044, Reset owner is NIC, iSCSI or FCOE based on priority
4044         * and which drivers are present. Unlike ISP82XX, the function setting
4045         * NEED_RESET, may not be the Reset owner. */
4046        qla83xx_reset_ownership(vha);
4047
4048        qla8044_idc_unlock(ha);
4049        rval = qla8044_device_state_handler(vha);
4050        qla8044_idc_lock(ha);
4051        qla8044_clear_rst_ready(vha);
4052
4053exit_isp_reset:
4054        qla8044_idc_unlock(ha);
4055        if (rval == QLA_SUCCESS) {
4056                ha->flags.isp82xx_fw_hung = 0;
4057                ha->flags.nic_core_reset_hdlr_active = 0;
4058                rval = qla82xx_restart_isp(vha);
4059        }
4060
4061        return rval;
4062}
4063
4064void
4065qla8044_fw_dump(scsi_qla_host_t *vha)
4066{
4067        struct qla_hw_data *ha = vha->hw;
4068
4069        if (!ha->allow_cna_fw_dump)
4070                return;
4071
4072        scsi_block_requests(vha->host);
4073        ha->flags.isp82xx_no_md_cap = 1;
4074        qla8044_idc_lock(ha);
4075        qla82xx_set_reset_owner(vha);
4076        qla8044_idc_unlock(ha);
4077        qla2x00_wait_for_chip_reset(vha);
4078        scsi_unblock_requests(vha->host);
4079}
4080