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;
 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 */
 562uint8_t *
 563qla8044_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
 564        uint32_t offset, uint32_t length)
 565{
 566        scsi_block_requests(vha->host);
 567        if (qla8044_read_flash_data(vha, (uint8_t *)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;
 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 = 0;
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 * qla4_8xxx_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                        opcode &= ~QLA82XX_DBG_OPCODE_WR;
2231                }
2232
2233                if (opcode & QLA82XX_DBG_OPCODE_RW) {
2234                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2235                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2236                        opcode &= ~QLA82XX_DBG_OPCODE_RW;
2237                }
2238
2239                if (opcode & QLA82XX_DBG_OPCODE_AND) {
2240                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2241                        read_value &= crb_entry->value_2;
2242                        opcode &= ~QLA82XX_DBG_OPCODE_AND;
2243                        if (opcode & QLA82XX_DBG_OPCODE_OR) {
2244                                read_value |= crb_entry->value_3;
2245                                opcode &= ~QLA82XX_DBG_OPCODE_OR;
2246                        }
2247                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2248                }
2249                if (opcode & QLA82XX_DBG_OPCODE_OR) {
2250                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2251                        read_value |= crb_entry->value_3;
2252                        qla8044_wr_reg_indirect(vha, crb_addr, read_value);
2253                        opcode &= ~QLA82XX_DBG_OPCODE_OR;
2254                }
2255                if (opcode & QLA82XX_DBG_OPCODE_POLL) {
2256                        poll_time = crb_entry->crb_strd.poll_timeout;
2257                        wtime = jiffies + poll_time;
2258                        qla8044_rd_reg_indirect(vha, crb_addr, &read_value);
2259
2260                        do {
2261                                if ((read_value & crb_entry->value_2) ==
2262                                    crb_entry->value_1) {
2263                                        break;
2264                                } else if (time_after_eq(jiffies, wtime)) {
2265                                        /* capturing dump failed */
2266                                        rval = QLA_FUNCTION_FAILED;
2267                                        break;
2268                                } else {
2269                                        qla8044_rd_reg_indirect(vha,
2270                                            crb_addr, &read_value);
2271                                }
2272                        } while (1);
2273                        opcode &= ~QLA82XX_DBG_OPCODE_POLL;
2274                }
2275
2276                if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) {
2277                        if (crb_entry->crb_strd.state_index_a) {
2278                                index = crb_entry->crb_strd.state_index_a;
2279                                addr = tmplt_hdr->saved_state_array[index];
2280                        } else {
2281                                addr = crb_addr;
2282                        }
2283
2284                        qla8044_rd_reg_indirect(vha, addr, &read_value);
2285                        index = crb_entry->crb_ctrl.state_index_v;
2286                        tmplt_hdr->saved_state_array[index] = read_value;
2287                        opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE;
2288                }
2289
2290                if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) {
2291                        if (crb_entry->crb_strd.state_index_a) {
2292                                index = crb_entry->crb_strd.state_index_a;
2293                                addr = tmplt_hdr->saved_state_array[index];
2294                        } else {
2295                                addr = crb_addr;
2296                        }
2297
2298                        if (crb_entry->crb_ctrl.state_index_v) {
2299                                index = crb_entry->crb_ctrl.state_index_v;
2300                                read_value =
2301                                    tmplt_hdr->saved_state_array[index];
2302                        } else {
2303                                read_value = crb_entry->value_1;
2304                        }
2305
2306                        qla8044_wr_reg_indirect(vha, addr, read_value);
2307                        opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE;
2308                }
2309
2310                if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) {
2311                        index = crb_entry->crb_ctrl.state_index_v;
2312                        read_value = tmplt_hdr->saved_state_array[index];
2313                        read_value <<= crb_entry->crb_ctrl.shl;
2314                        read_value >>= crb_entry->crb_ctrl.shr;
2315                        if (crb_entry->value_2)
2316                                read_value &= crb_entry->value_2;
2317                        read_value |= crb_entry->value_3;
2318                        read_value += crb_entry->value_1;
2319                        tmplt_hdr->saved_state_array[index] = read_value;
2320                        opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE;
2321                }
2322                crb_addr += crb_entry->crb_strd.addr_stride;
2323        }
2324        return rval;
2325}
2326
2327static void
2328qla8044_minidump_process_rdcrb(struct scsi_qla_host *vha,
2329        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2330{
2331        uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2332        struct qla8044_minidump_entry_crb *crb_hdr;
2333        uint32_t *data_ptr = *d_ptr;
2334
2335        ql_dbg(ql_dbg_p3p, vha, 0xb0de, "Entering fn: %s\n", __func__);
2336        crb_hdr = (struct qla8044_minidump_entry_crb *)entry_hdr;
2337        r_addr = crb_hdr->addr;
2338        r_stride = crb_hdr->crb_strd.addr_stride;
2339        loop_cnt = crb_hdr->op_count;
2340
2341        for (i = 0; i < loop_cnt; i++) {
2342                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2343                *data_ptr++ = r_addr;
2344                *data_ptr++ = r_value;
2345                r_addr += r_stride;
2346        }
2347        *d_ptr = data_ptr;
2348}
2349
2350static int
2351qla8044_minidump_process_rdmem(struct scsi_qla_host *vha,
2352        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2353{
2354        uint32_t r_addr, r_value, r_data;
2355        uint32_t i, j, loop_cnt;
2356        struct qla8044_minidump_entry_rdmem *m_hdr;
2357        unsigned long flags;
2358        uint32_t *data_ptr = *d_ptr;
2359        struct qla_hw_data *ha = vha->hw;
2360
2361        ql_dbg(ql_dbg_p3p, vha, 0xb0df, "Entering fn: %s\n", __func__);
2362        m_hdr = (struct qla8044_minidump_entry_rdmem *)entry_hdr;
2363        r_addr = m_hdr->read_addr;
2364        loop_cnt = m_hdr->read_data_size/16;
2365
2366        ql_dbg(ql_dbg_p3p, vha, 0xb0f0,
2367            "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n",
2368            __func__, r_addr, m_hdr->read_data_size);
2369
2370        if (r_addr & 0xf) {
2371                ql_dbg(ql_dbg_p3p, vha, 0xb0f1,
2372                    "[%s]: Read addr 0x%x not 16 bytes aligned\n",
2373                    __func__, r_addr);
2374                return QLA_FUNCTION_FAILED;
2375        }
2376
2377        if (m_hdr->read_data_size % 16) {
2378                ql_dbg(ql_dbg_p3p, vha, 0xb0f2,
2379                    "[%s]: Read data[0x%x] not multiple of 16 bytes\n",
2380                    __func__, m_hdr->read_data_size);
2381                return QLA_FUNCTION_FAILED;
2382        }
2383
2384        ql_dbg(ql_dbg_p3p, vha, 0xb0f3,
2385            "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n",
2386            __func__, r_addr, m_hdr->read_data_size, loop_cnt);
2387
2388        write_lock_irqsave(&ha->hw_lock, flags);
2389        for (i = 0; i < loop_cnt; i++) {
2390                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_LO, r_addr);
2391                r_value = 0;
2392                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_ADDR_HI, r_value);
2393                r_value = MIU_TA_CTL_ENABLE;
2394                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2395                r_value = MIU_TA_CTL_START_ENABLE;
2396                qla8044_wr_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL, r_value);
2397
2398                for (j = 0; j < MAX_CTL_CHECK; j++) {
2399                        qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_CTRL,
2400                            &r_value);
2401                        if ((r_value & MIU_TA_CTL_BUSY) == 0)
2402                                break;
2403                }
2404
2405                if (j >= MAX_CTL_CHECK) {
2406                        write_unlock_irqrestore(&ha->hw_lock, flags);
2407                        return QLA_SUCCESS;
2408                }
2409
2410                for (j = 0; j < 4; j++) {
2411                        qla8044_rd_reg_indirect(vha, MD_MIU_TEST_AGT_RDDATA[j],
2412                            &r_data);
2413                        *data_ptr++ = r_data;
2414                }
2415
2416                r_addr += 16;
2417        }
2418        write_unlock_irqrestore(&ha->hw_lock, flags);
2419
2420        ql_dbg(ql_dbg_p3p, vha, 0xb0f4,
2421            "Leaving fn: %s datacount: 0x%x\n",
2422             __func__, (loop_cnt * 16));
2423
2424        *d_ptr = data_ptr;
2425        return QLA_SUCCESS;
2426}
2427
2428/* ISP83xx flash read for _RDROM _BOARD */
2429static uint32_t
2430qla8044_minidump_process_rdrom(struct scsi_qla_host *vha,
2431        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2432{
2433        uint32_t fl_addr, u32_count, rval;
2434        struct qla8044_minidump_entry_rdrom *rom_hdr;
2435        uint32_t *data_ptr = *d_ptr;
2436
2437        rom_hdr = (struct qla8044_minidump_entry_rdrom *)entry_hdr;
2438        fl_addr = rom_hdr->read_addr;
2439        u32_count = (rom_hdr->read_data_size)/sizeof(uint32_t);
2440
2441        ql_dbg(ql_dbg_p3p, vha, 0xb0f5, "[%s]: fl_addr: 0x%x, count: 0x%x\n",
2442            __func__, fl_addr, u32_count);
2443
2444        rval = qla8044_lockless_flash_read_u32(vha, fl_addr,
2445            (u8 *)(data_ptr), u32_count);
2446
2447        if (rval != QLA_SUCCESS) {
2448                ql_log(ql_log_fatal, vha, 0xb0f6,
2449                    "%s: Flash Read Error,Count=%d\n", __func__, u32_count);
2450                return QLA_FUNCTION_FAILED;
2451        } else {
2452                data_ptr += u32_count;
2453                *d_ptr = data_ptr;
2454                return QLA_SUCCESS;
2455        }
2456}
2457
2458static void
2459qla8044_mark_entry_skipped(struct scsi_qla_host *vha,
2460        struct qla8044_minidump_entry_hdr *entry_hdr, int index)
2461{
2462        entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG;
2463
2464        ql_log(ql_log_info, vha, 0xb0f7,
2465            "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n",
2466            vha->host_no, index, entry_hdr->entry_type,
2467            entry_hdr->d_ctrl.entry_capture_mask);
2468}
2469
2470static int
2471qla8044_minidump_process_l2tag(struct scsi_qla_host *vha,
2472        struct qla8044_minidump_entry_hdr *entry_hdr,
2473                                 uint32_t **d_ptr)
2474{
2475        uint32_t addr, r_addr, c_addr, t_r_addr;
2476        uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2477        unsigned long p_wait, w_time, p_mask;
2478        uint32_t c_value_w, c_value_r;
2479        struct qla8044_minidump_entry_cache *cache_hdr;
2480        int rval = QLA_FUNCTION_FAILED;
2481        uint32_t *data_ptr = *d_ptr;
2482
2483        ql_dbg(ql_dbg_p3p, vha, 0xb0f8, "Entering fn: %s\n", __func__);
2484        cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2485
2486        loop_count = cache_hdr->op_count;
2487        r_addr = cache_hdr->read_addr;
2488        c_addr = cache_hdr->control_addr;
2489        c_value_w = cache_hdr->cache_ctrl.write_value;
2490
2491        t_r_addr = cache_hdr->tag_reg_addr;
2492        t_value = cache_hdr->addr_ctrl.init_tag_value;
2493        r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2494        p_wait = cache_hdr->cache_ctrl.poll_wait;
2495        p_mask = cache_hdr->cache_ctrl.poll_mask;
2496
2497        for (i = 0; i < loop_count; i++) {
2498                qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2499                if (c_value_w)
2500                        qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2501
2502                if (p_mask) {
2503                        w_time = jiffies + p_wait;
2504                        do {
2505                                qla8044_rd_reg_indirect(vha, c_addr,
2506                                    &c_value_r);
2507                                if ((c_value_r & p_mask) == 0) {
2508                                        break;
2509                                } else if (time_after_eq(jiffies, w_time)) {
2510                                        /* capturing dump failed */
2511                                        return rval;
2512                                }
2513                        } while (1);
2514                }
2515
2516                addr = r_addr;
2517                for (k = 0; k < r_cnt; k++) {
2518                        qla8044_rd_reg_indirect(vha, addr, &r_value);
2519                        *data_ptr++ = r_value;
2520                        addr += cache_hdr->read_ctrl.read_addr_stride;
2521                }
2522                t_value += cache_hdr->addr_ctrl.tag_value_stride;
2523        }
2524        *d_ptr = data_ptr;
2525        return QLA_SUCCESS;
2526}
2527
2528static void
2529qla8044_minidump_process_l1cache(struct scsi_qla_host *vha,
2530        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2531{
2532        uint32_t addr, r_addr, c_addr, t_r_addr;
2533        uint32_t i, k, loop_count, t_value, r_cnt, r_value;
2534        uint32_t c_value_w;
2535        struct qla8044_minidump_entry_cache *cache_hdr;
2536        uint32_t *data_ptr = *d_ptr;
2537
2538        cache_hdr = (struct qla8044_minidump_entry_cache *)entry_hdr;
2539        loop_count = cache_hdr->op_count;
2540        r_addr = cache_hdr->read_addr;
2541        c_addr = cache_hdr->control_addr;
2542        c_value_w = cache_hdr->cache_ctrl.write_value;
2543
2544        t_r_addr = cache_hdr->tag_reg_addr;
2545        t_value = cache_hdr->addr_ctrl.init_tag_value;
2546        r_cnt = cache_hdr->read_ctrl.read_addr_cnt;
2547
2548        for (i = 0; i < loop_count; i++) {
2549                qla8044_wr_reg_indirect(vha, t_r_addr, t_value);
2550                qla8044_wr_reg_indirect(vha, c_addr, c_value_w);
2551                addr = r_addr;
2552                for (k = 0; k < r_cnt; k++) {
2553                        qla8044_rd_reg_indirect(vha, addr, &r_value);
2554                        *data_ptr++ = r_value;
2555                        addr += cache_hdr->read_ctrl.read_addr_stride;
2556                }
2557                t_value += cache_hdr->addr_ctrl.tag_value_stride;
2558        }
2559        *d_ptr = data_ptr;
2560}
2561
2562static void
2563qla8044_minidump_process_rdocm(struct scsi_qla_host *vha,
2564        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2565{
2566        uint32_t r_addr, r_stride, loop_cnt, i, r_value;
2567        struct qla8044_minidump_entry_rdocm *ocm_hdr;
2568        uint32_t *data_ptr = *d_ptr;
2569        struct qla_hw_data *ha = vha->hw;
2570
2571        ql_dbg(ql_dbg_p3p, vha, 0xb0f9, "Entering fn: %s\n", __func__);
2572
2573        ocm_hdr = (struct qla8044_minidump_entry_rdocm *)entry_hdr;
2574        r_addr = ocm_hdr->read_addr;
2575        r_stride = ocm_hdr->read_addr_stride;
2576        loop_cnt = ocm_hdr->op_count;
2577
2578        ql_dbg(ql_dbg_p3p, vha, 0xb0fa,
2579            "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n",
2580            __func__, r_addr, r_stride, loop_cnt);
2581
2582        for (i = 0; i < loop_cnt; i++) {
2583                r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase));
2584                *data_ptr++ = r_value;
2585                r_addr += r_stride;
2586        }
2587        ql_dbg(ql_dbg_p3p, vha, 0xb0fb, "Leaving fn: %s datacount: 0x%lx\n",
2588            __func__, (long unsigned int) (loop_cnt * sizeof(uint32_t)));
2589
2590        *d_ptr = data_ptr;
2591}
2592
2593static void
2594qla8044_minidump_process_rdmux(struct scsi_qla_host *vha,
2595        struct qla8044_minidump_entry_hdr *entry_hdr,
2596        uint32_t **d_ptr)
2597{
2598        uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
2599        struct qla8044_minidump_entry_mux *mux_hdr;
2600        uint32_t *data_ptr = *d_ptr;
2601
2602        ql_dbg(ql_dbg_p3p, vha, 0xb0fc, "Entering fn: %s\n", __func__);
2603
2604        mux_hdr = (struct qla8044_minidump_entry_mux *)entry_hdr;
2605        r_addr = mux_hdr->read_addr;
2606        s_addr = mux_hdr->select_addr;
2607        s_stride = mux_hdr->select_value_stride;
2608        s_value = mux_hdr->select_value;
2609        loop_cnt = mux_hdr->op_count;
2610
2611        for (i = 0; i < loop_cnt; i++) {
2612                qla8044_wr_reg_indirect(vha, s_addr, s_value);
2613                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2614                *data_ptr++ = s_value;
2615                *data_ptr++ = r_value;
2616                s_value += s_stride;
2617        }
2618        *d_ptr = data_ptr;
2619}
2620
2621static void
2622qla8044_minidump_process_queue(struct scsi_qla_host *vha,
2623        struct qla8044_minidump_entry_hdr *entry_hdr,
2624        uint32_t **d_ptr)
2625{
2626        uint32_t s_addr, r_addr;
2627        uint32_t r_stride, r_value, r_cnt, qid = 0;
2628        uint32_t i, k, loop_cnt;
2629        struct qla8044_minidump_entry_queue *q_hdr;
2630        uint32_t *data_ptr = *d_ptr;
2631
2632        ql_dbg(ql_dbg_p3p, vha, 0xb0fd, "Entering fn: %s\n", __func__);
2633        q_hdr = (struct qla8044_minidump_entry_queue *)entry_hdr;
2634        s_addr = q_hdr->select_addr;
2635        r_cnt = q_hdr->rd_strd.read_addr_cnt;
2636        r_stride = q_hdr->rd_strd.read_addr_stride;
2637        loop_cnt = q_hdr->op_count;
2638
2639        for (i = 0; i < loop_cnt; i++) {
2640                qla8044_wr_reg_indirect(vha, s_addr, qid);
2641                r_addr = q_hdr->read_addr;
2642                for (k = 0; k < r_cnt; k++) {
2643                        qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2644                        *data_ptr++ = r_value;
2645                        r_addr += r_stride;
2646                }
2647                qid += q_hdr->q_strd.queue_id_stride;
2648        }
2649        *d_ptr = data_ptr;
2650}
2651
2652/* ISP83xx functions to process new minidump entries... */
2653static uint32_t
2654qla8044_minidump_process_pollrd(struct scsi_qla_host *vha,
2655        struct qla8044_minidump_entry_hdr *entry_hdr,
2656        uint32_t **d_ptr)
2657{
2658        uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask;
2659        uint16_t s_stride, i;
2660        struct qla8044_minidump_entry_pollrd *pollrd_hdr;
2661        uint32_t *data_ptr = *d_ptr;
2662
2663        pollrd_hdr = (struct qla8044_minidump_entry_pollrd *) entry_hdr;
2664        s_addr = pollrd_hdr->select_addr;
2665        r_addr = pollrd_hdr->read_addr;
2666        s_value = pollrd_hdr->select_value;
2667        s_stride = pollrd_hdr->select_value_stride;
2668
2669        poll_wait = pollrd_hdr->poll_wait;
2670        poll_mask = pollrd_hdr->poll_mask;
2671
2672        for (i = 0; i < pollrd_hdr->op_count; i++) {
2673                qla8044_wr_reg_indirect(vha, s_addr, s_value);
2674                poll_wait = pollrd_hdr->poll_wait;
2675                while (1) {
2676                        qla8044_rd_reg_indirect(vha, s_addr, &r_value);
2677                        if ((r_value & poll_mask) != 0) {
2678                                break;
2679                        } else {
2680                                usleep_range(1000, 1100);
2681                                if (--poll_wait == 0) {
2682                                        ql_log(ql_log_fatal, vha, 0xb0fe,
2683                                            "%s: TIMEOUT\n", __func__);
2684                                        goto error;
2685                                }
2686                        }
2687                }
2688                qla8044_rd_reg_indirect(vha, r_addr, &r_value);
2689                *data_ptr++ = s_value;
2690                *data_ptr++ = r_value;
2691
2692                s_value += s_stride;
2693        }
2694        *d_ptr = data_ptr;
2695        return QLA_SUCCESS;
2696
2697error:
2698        return QLA_FUNCTION_FAILED;
2699}
2700
2701static void
2702qla8044_minidump_process_rdmux2(struct scsi_qla_host *vha,
2703        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2704{
2705        uint32_t sel_val1, sel_val2, t_sel_val, data, i;
2706        uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr;
2707        struct qla8044_minidump_entry_rdmux2 *rdmux2_hdr;
2708        uint32_t *data_ptr = *d_ptr;
2709
2710        rdmux2_hdr = (struct qla8044_minidump_entry_rdmux2 *) entry_hdr;
2711        sel_val1 = rdmux2_hdr->select_value_1;
2712        sel_val2 = rdmux2_hdr->select_value_2;
2713        sel_addr1 = rdmux2_hdr->select_addr_1;
2714        sel_addr2 = rdmux2_hdr->select_addr_2;
2715        sel_val_mask = rdmux2_hdr->select_value_mask;
2716        read_addr = rdmux2_hdr->read_addr;
2717
2718        for (i = 0; i < rdmux2_hdr->op_count; i++) {
2719                qla8044_wr_reg_indirect(vha, sel_addr1, sel_val1);
2720                t_sel_val = sel_val1 & sel_val_mask;
2721                *data_ptr++ = t_sel_val;
2722
2723                qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2724                qla8044_rd_reg_indirect(vha, read_addr, &data);
2725
2726                *data_ptr++ = data;
2727
2728                qla8044_wr_reg_indirect(vha, sel_addr1, sel_val2);
2729                t_sel_val = sel_val2 & sel_val_mask;
2730                *data_ptr++ = t_sel_val;
2731
2732                qla8044_wr_reg_indirect(vha, sel_addr2, t_sel_val);
2733                qla8044_rd_reg_indirect(vha, read_addr, &data);
2734
2735                *data_ptr++ = data;
2736
2737                sel_val1 += rdmux2_hdr->select_value_stride;
2738                sel_val2 += rdmux2_hdr->select_value_stride;
2739        }
2740
2741        *d_ptr = data_ptr;
2742}
2743
2744static uint32_t
2745qla8044_minidump_process_pollrdmwr(struct scsi_qla_host *vha,
2746        struct qla8044_minidump_entry_hdr *entry_hdr,
2747        uint32_t **d_ptr)
2748{
2749        uint32_t poll_wait, poll_mask, r_value, data;
2750        uint32_t addr_1, addr_2, value_1, value_2;
2751        struct qla8044_minidump_entry_pollrdmwr *poll_hdr;
2752        uint32_t *data_ptr = *d_ptr;
2753
2754        poll_hdr = (struct qla8044_minidump_entry_pollrdmwr *) entry_hdr;
2755        addr_1 = poll_hdr->addr_1;
2756        addr_2 = poll_hdr->addr_2;
2757        value_1 = poll_hdr->value_1;
2758        value_2 = poll_hdr->value_2;
2759        poll_mask = poll_hdr->poll_mask;
2760
2761        qla8044_wr_reg_indirect(vha, addr_1, value_1);
2762
2763        poll_wait = poll_hdr->poll_wait;
2764        while (1) {
2765                qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2766
2767                if ((r_value & poll_mask) != 0) {
2768                        break;
2769                } else {
2770                        usleep_range(1000, 1100);
2771                        if (--poll_wait == 0) {
2772                                ql_log(ql_log_fatal, vha, 0xb0ff,
2773                                    "%s: TIMEOUT\n", __func__);
2774                                goto error;
2775                        }
2776                }
2777        }
2778
2779        qla8044_rd_reg_indirect(vha, addr_2, &data);
2780        data &= poll_hdr->modify_mask;
2781        qla8044_wr_reg_indirect(vha, addr_2, data);
2782        qla8044_wr_reg_indirect(vha, addr_1, value_2);
2783
2784        poll_wait = poll_hdr->poll_wait;
2785        while (1) {
2786                qla8044_rd_reg_indirect(vha, addr_1, &r_value);
2787
2788                if ((r_value & poll_mask) != 0) {
2789                        break;
2790                } else {
2791                        usleep_range(1000, 1100);
2792                        if (--poll_wait == 0) {
2793                                ql_log(ql_log_fatal, vha, 0xb100,
2794                                    "%s: TIMEOUT2\n", __func__);
2795                                goto error;
2796                        }
2797                }
2798        }
2799
2800        *data_ptr++ = addr_2;
2801        *data_ptr++ = data;
2802
2803        *d_ptr = data_ptr;
2804
2805        return QLA_SUCCESS;
2806
2807error:
2808        return QLA_FUNCTION_FAILED;
2809}
2810
2811#define ISP8044_PEX_DMA_ENGINE_INDEX            8
2812#define ISP8044_PEX_DMA_BASE_ADDRESS            0x77320000
2813#define ISP8044_PEX_DMA_NUM_OFFSET              0x10000
2814#define ISP8044_PEX_DMA_CMD_ADDR_LOW            0x0
2815#define ISP8044_PEX_DMA_CMD_ADDR_HIGH           0x04
2816#define ISP8044_PEX_DMA_CMD_STS_AND_CNTRL       0x08
2817
2818#define ISP8044_PEX_DMA_READ_SIZE       (16 * 1024)
2819#define ISP8044_PEX_DMA_MAX_WAIT        (100 * 100) /* Max wait of 100 msecs */
2820
2821static int
2822qla8044_check_dma_engine_state(struct scsi_qla_host *vha)
2823{
2824        struct qla_hw_data *ha = vha->hw;
2825        int rval = QLA_SUCCESS;
2826        uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2827        uint64_t dma_base_addr = 0;
2828        struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2829
2830        tmplt_hdr = ha->md_tmplt_hdr;
2831        dma_eng_num =
2832            tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2833        dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2834                (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2835
2836        /* Read the pex-dma's command-status-and-control register. */
2837        rval = qla8044_rd_reg_indirect(vha,
2838            (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2839            &cmd_sts_and_cntrl);
2840        if (rval)
2841                return QLA_FUNCTION_FAILED;
2842
2843        /* Check if requested pex-dma engine is available. */
2844        if (cmd_sts_and_cntrl & BIT_31)
2845                return QLA_SUCCESS;
2846
2847        return QLA_FUNCTION_FAILED;
2848}
2849
2850static int
2851qla8044_start_pex_dma(struct scsi_qla_host *vha,
2852        struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr)
2853{
2854        struct qla_hw_data *ha = vha->hw;
2855        int rval = QLA_SUCCESS, wait = 0;
2856        uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0;
2857        uint64_t dma_base_addr = 0;
2858        struct qla8044_minidump_template_hdr *tmplt_hdr = NULL;
2859
2860        tmplt_hdr = ha->md_tmplt_hdr;
2861        dma_eng_num =
2862            tmplt_hdr->saved_state_array[ISP8044_PEX_DMA_ENGINE_INDEX];
2863        dma_base_addr = ISP8044_PEX_DMA_BASE_ADDRESS +
2864                (dma_eng_num * ISP8044_PEX_DMA_NUM_OFFSET);
2865
2866        rval = qla8044_wr_reg_indirect(vha,
2867            dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_LOW,
2868            m_hdr->desc_card_addr);
2869        if (rval)
2870                goto error_exit;
2871
2872        rval = qla8044_wr_reg_indirect(vha,
2873            dma_base_addr + ISP8044_PEX_DMA_CMD_ADDR_HIGH, 0);
2874        if (rval)
2875                goto error_exit;
2876
2877        rval = qla8044_wr_reg_indirect(vha,
2878            dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL,
2879            m_hdr->start_dma_cmd);
2880        if (rval)
2881                goto error_exit;
2882
2883        /* Wait for dma operation to complete. */
2884        for (wait = 0; wait < ISP8044_PEX_DMA_MAX_WAIT; wait++) {
2885                rval = qla8044_rd_reg_indirect(vha,
2886                    (dma_base_addr + ISP8044_PEX_DMA_CMD_STS_AND_CNTRL),
2887                    &cmd_sts_and_cntrl);
2888                if (rval)
2889                        goto error_exit;
2890
2891                if ((cmd_sts_and_cntrl & BIT_1) == 0)
2892                        break;
2893
2894                udelay(10);
2895        }
2896
2897        /* Wait a max of 100 ms, otherwise fallback to rdmem entry read */
2898        if (wait >= ISP8044_PEX_DMA_MAX_WAIT) {
2899                rval = QLA_FUNCTION_FAILED;
2900                goto error_exit;
2901        }
2902
2903error_exit:
2904        return rval;
2905}
2906
2907static int
2908qla8044_minidump_pex_dma_read(struct scsi_qla_host *vha,
2909        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2910{
2911        struct qla_hw_data *ha = vha->hw;
2912        int rval = QLA_SUCCESS;
2913        struct qla8044_minidump_entry_rdmem_pex_dma *m_hdr = NULL;
2914        uint32_t chunk_size, read_size;
2915        uint8_t *data_ptr = (uint8_t *)*d_ptr;
2916        void *rdmem_buffer = NULL;
2917        dma_addr_t rdmem_dma;
2918        struct qla8044_pex_dma_descriptor dma_desc;
2919
2920        rval = qla8044_check_dma_engine_state(vha);
2921        if (rval != QLA_SUCCESS) {
2922                ql_dbg(ql_dbg_p3p, vha, 0xb147,
2923                    "DMA engine not available. Fallback to rdmem-read.\n");
2924                return QLA_FUNCTION_FAILED;
2925        }
2926
2927        m_hdr = (void *)entry_hdr;
2928
2929        rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev,
2930            ISP8044_PEX_DMA_READ_SIZE, &rdmem_dma, GFP_KERNEL);
2931        if (!rdmem_buffer) {
2932                ql_dbg(ql_dbg_p3p, vha, 0xb148,
2933                    "Unable to allocate rdmem dma buffer\n");
2934                return QLA_FUNCTION_FAILED;
2935        }
2936
2937        /* Prepare pex-dma descriptor to be written to MS memory. */
2938        /* dma-desc-cmd layout:
2939         *              0-3: dma-desc-cmd 0-3
2940         *              4-7: pcid function number
2941         *              8-15: dma-desc-cmd 8-15
2942         * dma_bus_addr: dma buffer address
2943         * cmd.read_data_size: amount of data-chunk to be read.
2944         */
2945        dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f);
2946        dma_desc.cmd.dma_desc_cmd |=
2947            ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4);
2948
2949        dma_desc.dma_bus_addr = rdmem_dma;
2950        dma_desc.cmd.read_data_size = chunk_size = ISP8044_PEX_DMA_READ_SIZE;
2951        read_size = 0;
2952
2953        /*
2954         * Perform rdmem operation using pex-dma.
2955         * Prepare dma in chunks of ISP8044_PEX_DMA_READ_SIZE.
2956         */
2957        while (read_size < m_hdr->read_data_size) {
2958                if (m_hdr->read_data_size - read_size <
2959                    ISP8044_PEX_DMA_READ_SIZE) {
2960                        chunk_size = (m_hdr->read_data_size - read_size);
2961                        dma_desc.cmd.read_data_size = chunk_size;
2962                }
2963
2964                dma_desc.src_addr = m_hdr->read_addr + read_size;
2965
2966                /* Prepare: Write pex-dma descriptor to MS memory. */
2967                rval = qla8044_ms_mem_write_128b(vha,
2968                    m_hdr->desc_card_addr, (void *)&dma_desc,
2969                    (sizeof(struct qla8044_pex_dma_descriptor)/16));
2970                if (rval) {
2971                        ql_log(ql_log_warn, vha, 0xb14a,
2972                            "%s: Error writing rdmem-dma-init to MS !!!\n",
2973                            __func__);
2974                        goto error_exit;
2975                }
2976                ql_dbg(ql_dbg_p3p, vha, 0xb14b,
2977                    "%s: Dma-descriptor: Instruct for rdmem dma "
2978                    "(chunk_size 0x%x).\n", __func__, chunk_size);
2979
2980                /* Execute: Start pex-dma operation. */
2981                rval = qla8044_start_pex_dma(vha, m_hdr);
2982                if (rval)
2983                        goto error_exit;
2984
2985                memcpy(data_ptr, rdmem_buffer, chunk_size);
2986                data_ptr += chunk_size;
2987                read_size += chunk_size;
2988        }
2989
2990        *d_ptr = (void *)data_ptr;
2991
2992error_exit:
2993        if (rdmem_buffer)
2994                dma_free_coherent(&ha->pdev->dev, ISP8044_PEX_DMA_READ_SIZE,
2995                    rdmem_buffer, rdmem_dma);
2996
2997        return rval;
2998}
2999
3000static uint32_t
3001qla8044_minidump_process_rddfe(struct scsi_qla_host *vha,
3002        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3003{
3004        int loop_cnt;
3005        uint32_t addr1, addr2, value, data, temp, wrVal;
3006        uint8_t stride, stride2;
3007        uint16_t count;
3008        uint32_t poll, mask, modify_mask;
3009        uint32_t wait_count = 0;
3010
3011        uint32_t *data_ptr = *d_ptr;
3012
3013        struct qla8044_minidump_entry_rddfe *rddfe;
3014        rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr;
3015
3016        addr1 = rddfe->addr_1;
3017        value = rddfe->value;
3018        stride = rddfe->stride;
3019        stride2 = rddfe->stride2;
3020        count = rddfe->count;
3021
3022        poll = rddfe->poll;
3023        mask = rddfe->mask;
3024        modify_mask = rddfe->modify_mask;
3025
3026        addr2 = addr1 + stride;
3027
3028        for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) {
3029                qla8044_wr_reg_indirect(vha, addr1, (0x40000000 | value));
3030
3031                wait_count = 0;
3032                while (wait_count < poll) {
3033                        qla8044_rd_reg_indirect(vha, addr1, &temp);
3034                        if ((temp & mask) != 0)
3035                                break;
3036                        wait_count++;
3037                }
3038
3039                if (wait_count == poll) {
3040                        ql_log(ql_log_warn, vha, 0xb153,
3041                            "%s: TIMEOUT\n", __func__);
3042                        goto error;
3043                } else {
3044                        qla8044_rd_reg_indirect(vha, addr2, &temp);
3045                        temp = temp & modify_mask;
3046                        temp = (temp | ((loop_cnt << 16) | loop_cnt));
3047                        wrVal = ((temp << 16) | temp);
3048
3049                        qla8044_wr_reg_indirect(vha, addr2, wrVal);
3050                        qla8044_wr_reg_indirect(vha, addr1, value);
3051
3052                        wait_count = 0;
3053                        while (wait_count < poll) {
3054                                qla8044_rd_reg_indirect(vha, addr1, &temp);
3055                                if ((temp & mask) != 0)
3056                                        break;
3057                                wait_count++;
3058                        }
3059                        if (wait_count == poll) {
3060                                ql_log(ql_log_warn, vha, 0xb154,
3061                                    "%s: TIMEOUT\n", __func__);
3062                                goto error;
3063                        }
3064
3065                        qla8044_wr_reg_indirect(vha, addr1,
3066                            ((0x40000000 | value) + stride2));
3067                        wait_count = 0;
3068                        while (wait_count < poll) {
3069                                qla8044_rd_reg_indirect(vha, addr1, &temp);
3070                                if ((temp & mask) != 0)
3071                                        break;
3072                                wait_count++;
3073                        }
3074
3075                        if (wait_count == poll) {
3076                                ql_log(ql_log_warn, vha, 0xb155,
3077                                    "%s: TIMEOUT\n", __func__);
3078                                goto error;
3079                        }
3080
3081                        qla8044_rd_reg_indirect(vha, addr2, &data);
3082
3083                        *data_ptr++ = wrVal;
3084                        *data_ptr++ = data;
3085                }
3086
3087        }
3088
3089        *d_ptr = data_ptr;
3090        return QLA_SUCCESS;
3091
3092error:
3093        return -1;
3094
3095}
3096
3097static uint32_t
3098qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha,
3099        struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3100{
3101        int ret = 0;
3102        uint32_t addr1, addr2, value1, value2, data, selVal;
3103        uint8_t stride1, stride2;
3104        uint32_t addr3, addr4, addr5, addr6, addr7;
3105        uint16_t count, loop_cnt;
3106        uint32_t mask;
3107        uint32_t *data_ptr = *d_ptr;
3108
3109        struct qla8044_minidump_entry_rdmdio *rdmdio;
3110
3111        rdmdio = (struct qla8044_minidump_entry_rdmdio *) entry_hdr;
3112
3113        addr1 = rdmdio->addr_1;
3114        addr2 = rdmdio->addr_2;
3115        value1 = rdmdio->value_1;
3116        stride1 = rdmdio->stride_1;
3117        stride2 = rdmdio->stride_2;
3118        count = rdmdio->count;
3119
3120        mask = rdmdio->mask;
3121        value2 = rdmdio->value_2;
3122
3123        addr3 = addr1 + stride1;
3124
3125        for (loop_cnt = 0; loop_cnt < count; loop_cnt++) {
3126                ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3127                    addr3, mask);
3128                if (ret == -1)
3129                        goto error;
3130
3131                addr4 = addr2 - stride1;
3132                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr4,
3133                    value2);
3134                if (ret == -1)
3135                        goto error;
3136
3137                addr5 = addr2 - (2 * stride1);
3138                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr5,
3139                    value1);
3140                if (ret == -1)
3141                        goto error;
3142
3143                addr6 = addr2 - (3 * stride1);
3144                ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask,
3145                    addr6, 0x2);
3146                if (ret == -1)
3147                        goto error;
3148
3149                ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3150                    addr3, mask);
3151                if (ret == -1)
3152                        goto error;
3153
3154                addr7 = addr2 - (4 * stride1);
3155                data = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr7);
3156                if (data == -1)
3157                        goto error;
3158
3159                selVal = (value2 << 18) | (value1 << 2) | 2;
3160
3161                stride2 = rdmdio->stride_2;
3162                *data_ptr++ = selVal;
3163                *data_ptr++ = data;
3164
3165                value1 = value1 + stride2;
3166                *d_ptr = data_ptr;
3167        }
3168
3169        return 0;
3170
3171error:
3172        return -1;
3173}
3174
3175static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha,
3176                struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3177{
3178        uint32_t addr1, addr2, value1, value2, poll, r_value;
3179        uint32_t wait_count = 0;
3180        struct qla8044_minidump_entry_pollwr *pollwr_hdr;
3181
3182        pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr;
3183        addr1 = pollwr_hdr->addr_1;
3184        addr2 = pollwr_hdr->addr_2;
3185        value1 = pollwr_hdr->value_1;
3186        value2 = pollwr_hdr->value_2;
3187
3188        poll = pollwr_hdr->poll;
3189
3190        while (wait_count < poll) {
3191                qla8044_rd_reg_indirect(vha, addr1, &r_value);
3192
3193                if ((r_value & poll) != 0)
3194                        break;
3195                wait_count++;
3196        }
3197
3198        if (wait_count == poll) {
3199                ql_log(ql_log_warn, vha, 0xb156, "%s: TIMEOUT\n", __func__);
3200                goto error;
3201        }
3202
3203        qla8044_wr_reg_indirect(vha, addr2, value2);
3204        qla8044_wr_reg_indirect(vha, addr1, value1);
3205
3206        wait_count = 0;
3207        while (wait_count < poll) {
3208                qla8044_rd_reg_indirect(vha, addr1, &r_value);
3209
3210                if ((r_value & poll) != 0)
3211                        break;
3212                wait_count++;
3213        }
3214
3215        return QLA_SUCCESS;
3216
3217error:
3218        return -1;
3219}
3220
3221/*
3222 *
3223 * qla8044_collect_md_data - Retrieve firmware minidump data.
3224 * @ha: pointer to adapter structure
3225 **/
3226int
3227qla8044_collect_md_data(struct scsi_qla_host *vha)
3228{
3229        int num_entry_hdr = 0;
3230        struct qla8044_minidump_entry_hdr *entry_hdr;
3231        struct qla8044_minidump_template_hdr *tmplt_hdr;
3232        uint32_t *data_ptr;
3233        uint32_t data_collected = 0, f_capture_mask;
3234        int i, rval = QLA_FUNCTION_FAILED;
3235        uint64_t now;
3236        uint32_t timestamp, idc_control;
3237        struct qla_hw_data *ha = vha->hw;
3238
3239        if (!ha->md_dump) {
3240                ql_log(ql_log_info, vha, 0xb101,
3241                    "%s(%ld) No buffer to dump\n",
3242                    __func__, vha->host_no);
3243                return rval;
3244        }
3245
3246        if (ha->fw_dumped) {
3247                ql_log(ql_log_warn, vha, 0xb10d,
3248                    "Firmware has been previously dumped (%p) "
3249                    "-- ignoring request.\n", ha->fw_dump);
3250                goto md_failed;
3251        }
3252
3253        ha->fw_dumped = 0;
3254
3255        if (!ha->md_tmplt_hdr || !ha->md_dump) {
3256                ql_log(ql_log_warn, vha, 0xb10e,
3257                    "Memory not allocated for minidump capture\n");
3258                goto md_failed;
3259        }
3260
3261        qla8044_idc_lock(ha);
3262        idc_control = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3263        if (idc_control & GRACEFUL_RESET_BIT1) {
3264                ql_log(ql_log_warn, vha, 0xb112,
3265                    "Forced reset from application, "
3266                    "ignore minidump capture\n");
3267                qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
3268                    (idc_control & ~GRACEFUL_RESET_BIT1));
3269                qla8044_idc_unlock(ha);
3270
3271                goto md_failed;
3272        }
3273        qla8044_idc_unlock(ha);
3274
3275        if (qla82xx_validate_template_chksum(vha)) {
3276                ql_log(ql_log_info, vha, 0xb109,
3277                    "Template checksum validation error\n");
3278                goto md_failed;
3279        }
3280
3281        tmplt_hdr = (struct qla8044_minidump_template_hdr *)
3282                ha->md_tmplt_hdr;
3283        data_ptr = (uint32_t *)((uint8_t *)ha->md_dump);
3284        num_entry_hdr = tmplt_hdr->num_of_entries;
3285
3286        ql_dbg(ql_dbg_p3p, vha, 0xb11a,
3287            "Capture Mask obtained: 0x%x\n", tmplt_hdr->capture_debug_level);
3288
3289        f_capture_mask = tmplt_hdr->capture_debug_level & 0xFF;
3290
3291        /* Validate whether required debug level is set */
3292        if ((f_capture_mask & 0x3) != 0x3) {
3293                ql_log(ql_log_warn, vha, 0xb10f,
3294                    "Minimum required capture mask[0x%x] level not set\n",
3295                    f_capture_mask);
3296
3297        }
3298        tmplt_hdr->driver_capture_mask = ql2xmdcapmask;
3299        ql_log(ql_log_info, vha, 0xb102,
3300            "[%s]: starting data ptr: %p\n",
3301           __func__, data_ptr);
3302        ql_log(ql_log_info, vha, 0xb10b,
3303           "[%s]: no of entry headers in Template: 0x%x\n",
3304           __func__, num_entry_hdr);
3305        ql_log(ql_log_info, vha, 0xb10c,
3306            "[%s]: Total_data_size 0x%x, %d obtained\n",
3307           __func__, ha->md_dump_size, ha->md_dump_size);
3308
3309        /* Update current timestamp before taking dump */
3310        now = get_jiffies_64();
3311        timestamp = (u32)(jiffies_to_msecs(now) / 1000);
3312        tmplt_hdr->driver_timestamp = timestamp;
3313
3314        entry_hdr = (struct qla8044_minidump_entry_hdr *)
3315                (((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
3316        tmplt_hdr->saved_state_array[QLA8044_SS_OCM_WNDREG_INDEX] =
3317            tmplt_hdr->ocm_window_reg[ha->portnum];
3318
3319        /* Walk through the entry headers - validate/perform required action */
3320        for (i = 0; i < num_entry_hdr; i++) {
3321                if (data_collected > ha->md_dump_size) {
3322                        ql_log(ql_log_info, vha, 0xb103,
3323                            "Data collected: [0x%x], "
3324                            "Total Dump size: [0x%x]\n",
3325                            data_collected, ha->md_dump_size);
3326                        return rval;
3327                }
3328
3329                if (!(entry_hdr->d_ctrl.entry_capture_mask &
3330                      ql2xmdcapmask)) {
3331                        entry_hdr->d_ctrl.driver_flags |=
3332                            QLA82XX_DBG_SKIPPED_FLAG;
3333                        goto skip_nxt_entry;
3334                }
3335
3336                ql_dbg(ql_dbg_p3p, vha, 0xb104,
3337                    "Data collected: [0x%x], Dump size left:[0x%x]\n",
3338                    data_collected,
3339                    (ha->md_dump_size - data_collected));
3340
3341                /* Decode the entry type and take required action to capture
3342                 * debug data
3343                 */
3344                switch (entry_hdr->entry_type) {
3345                case QLA82XX_RDEND:
3346                        qla8044_mark_entry_skipped(vha, entry_hdr, i);
3347                        break;
3348                case QLA82XX_CNTRL:
3349                        rval = qla8044_minidump_process_control(vha,
3350                            entry_hdr);
3351                        if (rval != QLA_SUCCESS) {
3352                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3353                                goto md_failed;
3354                        }
3355                        break;
3356                case QLA82XX_RDCRB:
3357                        qla8044_minidump_process_rdcrb(vha,
3358                            entry_hdr, &data_ptr);
3359                        break;
3360                case QLA82XX_RDMEM:
3361                        rval = qla8044_minidump_pex_dma_read(vha,
3362                            entry_hdr, &data_ptr);
3363                        if (rval != QLA_SUCCESS) {
3364                                rval = qla8044_minidump_process_rdmem(vha,
3365                                    entry_hdr, &data_ptr);
3366                                if (rval != QLA_SUCCESS) {
3367                                        qla8044_mark_entry_skipped(vha,
3368                                            entry_hdr, i);
3369                                        goto md_failed;
3370                                }
3371                        }
3372                        break;
3373                case QLA82XX_BOARD:
3374                case QLA82XX_RDROM:
3375                        rval = qla8044_minidump_process_rdrom(vha,
3376                            entry_hdr, &data_ptr);
3377                        if (rval != QLA_SUCCESS) {
3378                                qla8044_mark_entry_skipped(vha,
3379                                    entry_hdr, i);
3380                        }
3381                        break;
3382                case QLA82XX_L2DTG:
3383                case QLA82XX_L2ITG:
3384                case QLA82XX_L2DAT:
3385                case QLA82XX_L2INS:
3386                        rval = qla8044_minidump_process_l2tag(vha,
3387                            entry_hdr, &data_ptr);
3388                        if (rval != QLA_SUCCESS) {
3389                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3390                                goto md_failed;
3391                        }
3392                        break;
3393                case QLA8044_L1DTG:
3394                case QLA8044_L1ITG:
3395                case QLA82XX_L1DAT:
3396                case QLA82XX_L1INS:
3397                        qla8044_minidump_process_l1cache(vha,
3398                            entry_hdr, &data_ptr);
3399                        break;
3400                case QLA82XX_RDOCM:
3401                        qla8044_minidump_process_rdocm(vha,
3402                            entry_hdr, &data_ptr);
3403                        break;
3404                case QLA82XX_RDMUX:
3405                        qla8044_minidump_process_rdmux(vha,
3406                            entry_hdr, &data_ptr);
3407                        break;
3408                case QLA82XX_QUEUE:
3409                        qla8044_minidump_process_queue(vha,
3410                            entry_hdr, &data_ptr);
3411                        break;
3412                case QLA8044_POLLRD:
3413                        rval = qla8044_minidump_process_pollrd(vha,
3414                            entry_hdr, &data_ptr);
3415                        if (rval != QLA_SUCCESS)
3416                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3417                        break;
3418                case QLA8044_RDMUX2:
3419                        qla8044_minidump_process_rdmux2(vha,
3420                            entry_hdr, &data_ptr);
3421                        break;
3422                case QLA8044_POLLRDMWR:
3423                        rval = qla8044_minidump_process_pollrdmwr(vha,
3424                            entry_hdr, &data_ptr);
3425                        if (rval != QLA_SUCCESS)
3426                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3427                        break;
3428                case QLA8044_RDDFE:
3429                        rval = qla8044_minidump_process_rddfe(vha, entry_hdr,
3430                            &data_ptr);
3431                        if (rval != QLA_SUCCESS)
3432                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3433                        break;
3434                case QLA8044_RDMDIO:
3435                        rval = qla8044_minidump_process_rdmdio(vha, entry_hdr,
3436                            &data_ptr);
3437                        if (rval != QLA_SUCCESS)
3438                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3439                        break;
3440                case QLA8044_POLLWR:
3441                        rval = qla8044_minidump_process_pollwr(vha, entry_hdr,
3442                            &data_ptr);
3443                        if (rval != QLA_SUCCESS)
3444                                qla8044_mark_entry_skipped(vha, entry_hdr, i);
3445                        break;
3446                case QLA82XX_RDNOP:
3447                default:
3448                        qla8044_mark_entry_skipped(vha, entry_hdr, i);
3449                        break;
3450                }
3451
3452                data_collected = (uint8_t *)data_ptr -
3453                    (uint8_t *)((uint8_t *)ha->md_dump);
3454skip_nxt_entry:
3455                /*
3456                 * next entry in the template
3457                 */
3458                entry_hdr = (struct qla8044_minidump_entry_hdr *)
3459                    (((uint8_t *)entry_hdr) + entry_hdr->entry_size);
3460        }
3461
3462        if (data_collected != ha->md_dump_size) {
3463                ql_log(ql_log_info, vha, 0xb105,
3464                    "Dump data mismatch: Data collected: "
3465                    "[0x%x], total_data_size:[0x%x]\n",
3466                    data_collected, ha->md_dump_size);
3467                rval = QLA_FUNCTION_FAILED;
3468                goto md_failed;
3469        }
3470
3471        ql_log(ql_log_info, vha, 0xb110,
3472            "Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
3473            vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
3474        ha->fw_dumped = 1;
3475        qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
3476
3477
3478        ql_log(ql_log_info, vha, 0xb106,
3479            "Leaving fn: %s Last entry: 0x%x\n",
3480            __func__, i);
3481md_failed:
3482        return rval;
3483}
3484
3485void
3486qla8044_get_minidump(struct scsi_qla_host *vha)
3487{
3488        struct qla_hw_data *ha = vha->hw;
3489
3490        if (!qla8044_collect_md_data(vha)) {
3491                ha->fw_dumped = 1;
3492                ha->prev_minidump_failed = 0;
3493        } else {
3494                ql_log(ql_log_fatal, vha, 0xb0db,
3495                    "%s: Unable to collect minidump\n",
3496                    __func__);
3497                ha->prev_minidump_failed = 1;
3498        }
3499}
3500
3501static int
3502qla8044_poll_flash_status_reg(struct scsi_qla_host *vha)
3503{
3504        uint32_t flash_status;
3505        int retries = QLA8044_FLASH_READ_RETRY_COUNT;
3506        int ret_val = QLA_SUCCESS;
3507
3508        while (retries--) {
3509                ret_val = qla8044_rd_reg_indirect(vha, QLA8044_FLASH_STATUS,
3510                    &flash_status);
3511                if (ret_val) {
3512                        ql_log(ql_log_warn, vha, 0xb13c,
3513                            "%s: Failed to read FLASH_STATUS reg.\n",
3514                            __func__);
3515                        break;
3516                }
3517                if ((flash_status & QLA8044_FLASH_STATUS_READY) ==
3518                    QLA8044_FLASH_STATUS_READY)
3519                        break;
3520                msleep(QLA8044_FLASH_STATUS_REG_POLL_DELAY);
3521        }
3522
3523        if (!retries)
3524                ret_val = QLA_FUNCTION_FAILED;
3525
3526        return ret_val;
3527}
3528
3529static int
3530qla8044_write_flash_status_reg(struct scsi_qla_host *vha,
3531                               uint32_t data)
3532{
3533        int ret_val = QLA_SUCCESS;
3534        uint32_t cmd;
3535
3536        cmd = vha->hw->fdt_wrt_sts_reg_cmd;
3537
3538        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3539            QLA8044_FLASH_STATUS_WRITE_DEF_SIG | cmd);
3540        if (ret_val) {
3541                ql_log(ql_log_warn, vha, 0xb125,
3542                    "%s: Failed to write to FLASH_ADDR.\n", __func__);
3543                goto exit_func;
3544        }
3545
3546        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, data);
3547        if (ret_val) {
3548                ql_log(ql_log_warn, vha, 0xb126,
3549                    "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3550                goto exit_func;
3551        }
3552
3553        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3554            QLA8044_FLASH_SECOND_ERASE_MS_VAL);
3555        if (ret_val) {
3556                ql_log(ql_log_warn, vha, 0xb127,
3557                    "%s: Failed to write to FLASH_CONTROL.\n", __func__);
3558                goto exit_func;
3559        }
3560
3561        ret_val = qla8044_poll_flash_status_reg(vha);
3562        if (ret_val)
3563                ql_log(ql_log_warn, vha, 0xb128,
3564                    "%s: Error polling flash status reg.\n", __func__);
3565
3566exit_func:
3567        return ret_val;
3568}
3569
3570/*
3571 * This function assumes that the flash lock is held.
3572 */
3573static int
3574qla8044_unprotect_flash(scsi_qla_host_t *vha)
3575{
3576        int ret_val;
3577        struct qla_hw_data *ha = vha->hw;
3578
3579        ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_enable);
3580        if (ret_val)
3581                ql_log(ql_log_warn, vha, 0xb139,
3582                    "%s: Write flash status failed.\n", __func__);
3583
3584        return ret_val;
3585}
3586
3587/*
3588 * This function assumes that the flash lock is held.
3589 */
3590static int
3591qla8044_protect_flash(scsi_qla_host_t *vha)
3592{
3593        int ret_val;
3594        struct qla_hw_data *ha = vha->hw;
3595
3596        ret_val = qla8044_write_flash_status_reg(vha, ha->fdt_wrt_disable);
3597        if (ret_val)
3598                ql_log(ql_log_warn, vha, 0xb13b,
3599                    "%s: Write flash status failed.\n", __func__);
3600
3601        return ret_val;
3602}
3603
3604
3605static int
3606qla8044_erase_flash_sector(struct scsi_qla_host *vha,
3607                           uint32_t sector_start_addr)
3608{
3609        uint32_t reversed_addr;
3610        int ret_val = QLA_SUCCESS;
3611
3612        ret_val = qla8044_poll_flash_status_reg(vha);
3613        if (ret_val) {
3614                ql_log(ql_log_warn, vha, 0xb12e,
3615                    "%s: Poll flash status after erase failed..\n", __func__);
3616        }
3617
3618        reversed_addr = (((sector_start_addr & 0xFF) << 16) |
3619            (sector_start_addr & 0xFF00) |
3620            ((sector_start_addr & 0xFF0000) >> 16));
3621
3622        ret_val = qla8044_wr_reg_indirect(vha,
3623            QLA8044_FLASH_WRDATA, reversed_addr);
3624        if (ret_val) {
3625                ql_log(ql_log_warn, vha, 0xb12f,
3626                    "%s: Failed to write to FLASH_WRDATA.\n", __func__);
3627        }
3628        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3629           QLA8044_FLASH_ERASE_SIG | vha->hw->fdt_erase_cmd);
3630        if (ret_val) {
3631                ql_log(ql_log_warn, vha, 0xb130,
3632                    "%s: Failed to write to FLASH_ADDR.\n", __func__);
3633        }
3634        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3635            QLA8044_FLASH_LAST_ERASE_MS_VAL);
3636        if (ret_val) {
3637                ql_log(ql_log_warn, vha, 0xb131,
3638                    "%s: Failed write to FLASH_CONTROL.\n", __func__);
3639        }
3640        ret_val = qla8044_poll_flash_status_reg(vha);
3641        if (ret_val) {
3642                ql_log(ql_log_warn, vha, 0xb132,
3643                    "%s: Poll flash status failed.\n", __func__);
3644        }
3645
3646
3647        return ret_val;
3648}
3649
3650/*
3651 * qla8044_flash_write_u32 - Write data to flash
3652 *
3653 * @ha : Pointer to adapter structure
3654 * addr : Flash address to write to
3655 * p_data : Data to be written
3656 *
3657 * Return Value - QLA_SUCCESS/QLA_FUNCTION_FAILED
3658 *
3659 * NOTE: Lock should be held on entry
3660 */
3661static int
3662qla8044_flash_write_u32(struct scsi_qla_host *vha, uint32_t addr,
3663                        uint32_t *p_data)
3664{
3665        int ret_val = QLA_SUCCESS;
3666
3667        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3668            0x00800000 | (addr >> 2));
3669        if (ret_val) {
3670                ql_log(ql_log_warn, vha, 0xb134,
3671                    "%s: Failed write to FLASH_ADDR.\n", __func__);
3672                goto exit_func;
3673        }
3674        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *p_data);
3675        if (ret_val) {
3676                ql_log(ql_log_warn, vha, 0xb135,
3677                    "%s: Failed write to FLASH_WRDATA.\n", __func__);
3678                goto exit_func;
3679        }
3680        ret_val = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL, 0x3D);
3681        if (ret_val) {
3682                ql_log(ql_log_warn, vha, 0xb136,
3683                    "%s: Failed write to FLASH_CONTROL.\n", __func__);
3684                goto exit_func;
3685        }
3686        ret_val = qla8044_poll_flash_status_reg(vha);
3687        if (ret_val) {
3688                ql_log(ql_log_warn, vha, 0xb137,
3689                    "%s: Poll flash status failed.\n", __func__);
3690        }
3691
3692exit_func:
3693        return ret_val;
3694}
3695
3696static int
3697qla8044_write_flash_buffer_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3698                                uint32_t faddr, uint32_t dwords)
3699{
3700        int ret = QLA_FUNCTION_FAILED;
3701        uint32_t spi_val;
3702
3703        if (dwords < QLA8044_MIN_OPTROM_BURST_DWORDS ||
3704            dwords > QLA8044_MAX_OPTROM_BURST_DWORDS) {
3705                ql_dbg(ql_dbg_user, vha, 0xb123,
3706                    "Got unsupported dwords = 0x%x.\n",
3707                    dwords);
3708                return QLA_FUNCTION_FAILED;
3709        }
3710
3711        qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL, &spi_val);
3712        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3713            spi_val | QLA8044_FLASH_SPI_CTL);
3714        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3715            QLA8044_FLASH_FIRST_TEMP_VAL);
3716
3717        /* First DWORD write to FLASH_WRDATA */
3718        ret = qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA,
3719            *dwptr++);
3720        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3721            QLA8044_FLASH_FIRST_MS_PATTERN);
3722
3723        ret = qla8044_poll_flash_status_reg(vha);
3724        if (ret) {
3725                ql_log(ql_log_warn, vha, 0xb124,
3726                    "%s: Failed.\n", __func__);
3727                goto exit_func;
3728        }
3729
3730        dwords--;
3731
3732        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3733            QLA8044_FLASH_SECOND_TEMP_VAL);
3734
3735
3736        /* Second to N-1 DWORDS writes */
3737        while (dwords != 1) {
3738                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3739                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3740                    QLA8044_FLASH_SECOND_MS_PATTERN);
3741                ret = qla8044_poll_flash_status_reg(vha);
3742                if (ret) {
3743                        ql_log(ql_log_warn, vha, 0xb129,
3744                            "%s: Failed.\n", __func__);
3745                        goto exit_func;
3746                }
3747                dwords--;
3748        }
3749
3750        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_ADDR,
3751            QLA8044_FLASH_FIRST_TEMP_VAL | (faddr >> 2));
3752
3753        /* Last DWORD write */
3754        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_WRDATA, *dwptr++);
3755        qla8044_wr_reg_indirect(vha, QLA8044_FLASH_CONTROL,
3756            QLA8044_FLASH_LAST_MS_PATTERN);
3757        ret = qla8044_poll_flash_status_reg(vha);
3758        if (ret) {
3759                ql_log(ql_log_warn, vha, 0xb12a,
3760                    "%s: Failed.\n", __func__);
3761                goto exit_func;
3762        }
3763        qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_STATUS, &spi_val);
3764
3765        if ((spi_val & QLA8044_FLASH_SPI_CTL) == QLA8044_FLASH_SPI_CTL) {
3766                ql_log(ql_log_warn, vha, 0xb12b,
3767                    "%s: Failed.\n", __func__);
3768                spi_val = 0;
3769                /* Operation failed, clear error bit. */
3770                qla8044_rd_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3771                    &spi_val);
3772                qla8044_wr_reg_indirect(vha, QLA8044_FLASH_SPI_CONTROL,
3773                    spi_val | QLA8044_FLASH_SPI_CTL);
3774        }
3775exit_func:
3776        return ret;
3777}
3778
3779static int
3780qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
3781                               uint32_t faddr, uint32_t dwords)
3782{
3783        int ret = QLA_FUNCTION_FAILED;
3784        uint32_t liter;
3785
3786        for (liter = 0; liter < dwords; liter++, faddr += 4, dwptr++) {
3787                ret = qla8044_flash_write_u32(vha, faddr, dwptr);
3788                if (ret) {
3789                        ql_dbg(ql_dbg_p3p, vha, 0xb141,
3790                            "%s: flash address=%x data=%x.\n", __func__,
3791                             faddr, *dwptr);
3792                        break;
3793                }
3794        }
3795
3796        return ret;
3797}
3798
3799int
3800qla8044_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
3801                          uint32_t offset, uint32_t length)
3802{
3803        int rval = QLA_FUNCTION_FAILED, i, burst_iter_count;
3804        int dword_count, erase_sec_count;
3805        uint32_t erase_offset;
3806        uint8_t *p_cache, *p_src;
3807
3808        erase_offset = offset;
3809
3810        p_cache = kcalloc(length, sizeof(uint8_t), GFP_KERNEL);
3811        if (!p_cache)
3812                return QLA_FUNCTION_FAILED;
3813
3814        memcpy(p_cache, buf, length);
3815        p_src = p_cache;
3816        dword_count = length / sizeof(uint32_t);
3817        /* Since the offset and legth are sector aligned, it will be always
3818         * multiple of burst_iter_count (64)
3819         */
3820        burst_iter_count = dword_count / QLA8044_MAX_OPTROM_BURST_DWORDS;
3821        erase_sec_count = length / QLA8044_SECTOR_SIZE;
3822
3823        /* Suspend HBA. */
3824        scsi_block_requests(vha->host);
3825        /* Lock and enable write for whole operation. */
3826        qla8044_flash_lock(vha);
3827        qla8044_unprotect_flash(vha);
3828
3829        /* Erasing the sectors */
3830        for (i = 0; i < erase_sec_count; i++) {
3831                rval = qla8044_erase_flash_sector(vha, erase_offset);
3832                ql_dbg(ql_dbg_user, vha, 0xb138,
3833                    "Done erase of sector=0x%x.\n",
3834                    erase_offset);
3835                if (rval) {
3836                        ql_log(ql_log_warn, vha, 0xb121,
3837                            "Failed to erase the sector having address: "
3838                            "0x%x.\n", erase_offset);
3839                        goto out;
3840                }
3841                erase_offset += QLA8044_SECTOR_SIZE;
3842        }
3843        ql_dbg(ql_dbg_user, vha, 0xb13f,
3844            "Got write for addr = 0x%x length=0x%x.\n",
3845            offset, length);
3846
3847        for (i = 0; i < burst_iter_count; i++) {
3848
3849                /* Go with write. */
3850                rval = qla8044_write_flash_buffer_mode(vha, (uint32_t *)p_src,
3851                    offset, QLA8044_MAX_OPTROM_BURST_DWORDS);
3852                if (rval) {
3853                        /* Buffer Mode failed skip to dword mode */
3854                        ql_log(ql_log_warn, vha, 0xb122,
3855                            "Failed to write flash in buffer mode, "
3856                            "Reverting to slow-write.\n");
3857                        rval = qla8044_write_flash_dword_mode(vha,
3858                            (uint32_t *)p_src, offset,
3859                            QLA8044_MAX_OPTROM_BURST_DWORDS);
3860                }
3861                p_src +=  sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3862                offset += sizeof(uint32_t) * QLA8044_MAX_OPTROM_BURST_DWORDS;
3863        }
3864        ql_dbg(ql_dbg_user, vha, 0xb133,
3865            "Done writing.\n");
3866
3867out:
3868        qla8044_protect_flash(vha);
3869        qla8044_flash_unlock(vha);
3870        scsi_unblock_requests(vha->host);
3871        kfree(p_cache);
3872
3873        return rval;
3874}
3875
3876#define LEG_INT_PTR_B31         (1 << 31)
3877#define LEG_INT_PTR_B30         (1 << 30)
3878#define PF_BITS_MASK            (0xF << 16)
3879/**
3880 * qla8044_intr_handler() - Process interrupts for the ISP8044
3881 * @irq:
3882 * @dev_id: SCSI driver HA context
3883 *
3884 * Called by system whenever the host adapter generates an interrupt.
3885 *
3886 * Returns handled flag.
3887 */
3888irqreturn_t
3889qla8044_intr_handler(int irq, void *dev_id)
3890{
3891        scsi_qla_host_t *vha;
3892        struct qla_hw_data *ha;
3893        struct rsp_que *rsp;
3894        struct device_reg_82xx __iomem *reg;
3895        int             status = 0;
3896        unsigned long   flags;
3897        unsigned long   iter;
3898        uint32_t        stat;
3899        uint16_t        mb[4];
3900        uint32_t leg_int_ptr = 0, pf_bit;
3901
3902        rsp = (struct rsp_que *) dev_id;
3903        if (!rsp) {
3904                ql_log(ql_log_info, NULL, 0xb143,
3905                    "%s(): NULL response queue pointer\n", __func__);
3906                return IRQ_NONE;
3907        }
3908        ha = rsp->hw;
3909        vha = pci_get_drvdata(ha->pdev);
3910
3911        if (unlikely(pci_channel_offline(ha->pdev)))
3912                return IRQ_HANDLED;
3913
3914        leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3915
3916        /* Legacy interrupt is valid if bit31 of leg_int_ptr is set */
3917        if (!(leg_int_ptr & (LEG_INT_PTR_B31))) {
3918                ql_dbg(ql_dbg_p3p, vha, 0xb144,
3919                    "%s: Legacy Interrupt Bit 31 not set, "
3920                    "spurious interrupt!\n", __func__);
3921                return IRQ_NONE;
3922        }
3923
3924        pf_bit = ha->portnum << 16;
3925        /* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */
3926        if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit) {
3927                ql_dbg(ql_dbg_p3p, vha, 0xb145,
3928                    "%s: Incorrect function ID 0x%x in "
3929                    "legacy interrupt register, "
3930                    "ha->pf_bit = 0x%x\n", __func__,
3931                    (leg_int_ptr & (PF_BITS_MASK)), pf_bit);
3932                return IRQ_NONE;
3933        }
3934
3935        /* To de-assert legacy interrupt, write 0 to Legacy Interrupt Trigger
3936         * Control register and poll till Legacy Interrupt Pointer register
3937         * bit32 is 0.
3938         */
3939        qla8044_wr_reg(ha, LEG_INTR_TRIG_OFFSET, 0);
3940        do {
3941                leg_int_ptr = qla8044_rd_reg(ha, LEG_INTR_PTR_OFFSET);
3942                if ((leg_int_ptr & (PF_BITS_MASK)) != pf_bit)
3943                        break;
3944        } while (leg_int_ptr & (LEG_INT_PTR_B30));
3945
3946        reg = &ha->iobase->isp82;
3947        spin_lock_irqsave(&ha->hardware_lock, flags);
3948        for (iter = 1; iter--; ) {
3949
3950                if (RD_REG_DWORD(&reg->host_int)) {
3951                        stat = RD_REG_DWORD(&reg->host_status);
3952                        if ((stat & HSRX_RISC_INT) == 0)
3953                                break;
3954
3955                        switch (stat & 0xff) {
3956                        case 0x1:
3957                        case 0x2:
3958                        case 0x10:
3959                        case 0x11:
3960                                qla82xx_mbx_completion(vha, MSW(stat));
3961                                status |= MBX_INTERRUPT;
3962                                break;
3963                        case 0x12:
3964                                mb[0] = MSW(stat);
3965                                mb[1] = RD_REG_WORD(&reg->mailbox_out[1]);
3966                                mb[2] = RD_REG_WORD(&reg->mailbox_out[2]);
3967                                mb[3] = RD_REG_WORD(&reg->mailbox_out[3]);
3968                                qla2x00_async_event(vha, rsp, mb);
3969                                break;
3970                        case 0x13:
3971                                qla24xx_process_response_queue(vha, rsp);
3972                                break;
3973                        default:
3974                                ql_dbg(ql_dbg_p3p, vha, 0xb146,
3975                                    "Unrecognized interrupt type "
3976                                    "(%d).\n", stat & 0xff);
3977                                break;
3978                        }
3979                }
3980                WRT_REG_DWORD(&reg->host_int, 0);
3981        }
3982
3983        qla2x00_handle_mbx_completion(ha, status);
3984        spin_unlock_irqrestore(&ha->hardware_lock, flags);
3985
3986        return IRQ_HANDLED;
3987}
3988
3989static int
3990qla8044_idc_dontreset(struct qla_hw_data *ha)
3991{
3992        uint32_t idc_ctrl;
3993
3994        idc_ctrl = qla8044_rd_reg(ha, QLA8044_IDC_DRV_CTRL);
3995        return idc_ctrl & DONTRESET_BIT0;
3996}
3997
3998static void
3999qla8044_clear_rst_ready(scsi_qla_host_t *vha)
4000{
4001        uint32_t drv_state;
4002
4003        drv_state = qla8044_rd_direct(vha, QLA8044_CRB_DRV_STATE_INDEX);
4004
4005        /*
4006         * For ISP8044, drv_active register has 1 bit per function,
4007         * shift 1 by func_num to set a bit for the function.
4008         * For ISP82xx, drv_active has 4 bits per function
4009         */
4010        drv_state &= ~(1 << vha->hw->portnum);
4011
4012        ql_dbg(ql_dbg_p3p, vha, 0xb13d,
4013            "drv_state: 0x%08x\n", drv_state);
4014        qla8044_wr_direct(vha, QLA8044_CRB_DRV_STATE_INDEX, drv_state);
4015}
4016
4017int
4018qla8044_abort_isp(scsi_qla_host_t *vha)
4019{
4020        int rval;
4021        uint32_t dev_state;
4022        struct qla_hw_data *ha = vha->hw;
4023
4024        qla8044_idc_lock(ha);
4025        dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
4026
4027        if (ql2xdontresethba)
4028                qla8044_set_idc_dontreset(vha);
4029
4030        /* If device_state is NEED_RESET, go ahead with
4031         * Reset,irrespective of ql2xdontresethba. This is to allow a
4032         * non-reset-owner to force a reset. Non-reset-owner sets
4033         * the IDC_CTRL BIT0 to prevent Reset-owner from doing a Reset
4034         * and then forces a Reset by setting device_state to
4035         * NEED_RESET. */
4036        if (dev_state == QLA8XXX_DEV_READY) {
4037                /* If IDC_CTRL DONTRESETHBA_BIT0 is set don't do reset
4038                 * recovery */
4039                if (qla8044_idc_dontreset(ha) == DONTRESET_BIT0) {
4040                        ql_dbg(ql_dbg_p3p, vha, 0xb13e,
4041                            "Reset recovery disabled\n");
4042                        rval = QLA_FUNCTION_FAILED;
4043                        goto exit_isp_reset;
4044                }
4045
4046                ql_dbg(ql_dbg_p3p, vha, 0xb140,
4047                    "HW State: NEED RESET\n");
4048                qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX,
4049                    QLA8XXX_DEV_NEED_RESET);
4050        }
4051
4052        /* For ISP8044, Reset owner is NIC, iSCSI or FCOE based on priority
4053         * and which drivers are present. Unlike ISP82XX, the function setting
4054         * NEED_RESET, may not be the Reset owner. */
4055        qla83xx_reset_ownership(vha);
4056
4057        qla8044_idc_unlock(ha);
4058        rval = qla8044_device_state_handler(vha);
4059        qla8044_idc_lock(ha);
4060        qla8044_clear_rst_ready(vha);
4061
4062exit_isp_reset:
4063        qla8044_idc_unlock(ha);
4064        if (rval == QLA_SUCCESS) {
4065                ha->flags.isp82xx_fw_hung = 0;
4066                ha->flags.nic_core_reset_hdlr_active = 0;
4067                rval = qla82xx_restart_isp(vha);
4068        }
4069
4070        return rval;
4071}
4072
4073void
4074qla8044_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
4075{
4076        struct qla_hw_data *ha = vha->hw;
4077
4078        if (!ha->allow_cna_fw_dump)
4079                return;
4080
4081        scsi_block_requests(vha->host);
4082        ha->flags.isp82xx_no_md_cap = 1;
4083        qla8044_idc_lock(ha);
4084        qla82xx_set_reset_owner(vha);
4085        qla8044_idc_unlock(ha);
4086        qla2x00_wait_for_chip_reset(vha);
4087        scsi_unblock_requests(vha->host);
4088}
4089