aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_nx2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_nx2.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_nx2.c510
1 files changed, 429 insertions, 81 deletions
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index 86cf10815db0..da9e3902f219 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -1,17 +1,20 @@
1/* 1/*
2 * QLogic Fibre Channel HBA Driver 2 * QLogic Fibre Channel HBA Driver
3 * Copyright (c) 2003-2013 QLogic Corporation 3 * Copyright (c) 2003-2014 QLogic Corporation
4 * 4 *
5 * See LICENSE.qla2xxx for copyright and licensing details. 5 * See LICENSE.qla2xxx for copyright and licensing details.
6 */ 6 */
7 7
8#include <linux/vmalloc.h> 8#include <linux/vmalloc.h>
9#include <linux/delay.h>
9 10
10#include "qla_def.h" 11#include "qla_def.h"
11#include "qla_gbl.h" 12#include "qla_gbl.h"
12 13
13#include <linux/delay.h> 14#include <linux/delay.h>
14 15
16#define TIMEOUT_100_MS 100
17
15/* 8044 Flash Read/Write functions */ 18/* 8044 Flash Read/Write functions */
16uint32_t 19uint32_t
17qla8044_rd_reg(struct qla_hw_data *ha, ulong addr) 20qla8044_rd_reg(struct qla_hw_data *ha, ulong addr)
@@ -117,6 +120,95 @@ qla8044_read_write_crb_reg(struct scsi_qla_host *vha,
117 qla8044_wr_reg_indirect(vha, waddr, value); 120 qla8044_wr_reg_indirect(vha, waddr, value);
118} 121}
119 122
123static int
124qla8044_poll_wait_for_ready(struct scsi_qla_host *vha, uint32_t addr1,
125 uint32_t mask)
126{
127 unsigned long timeout;
128 uint32_t temp;
129
130 /* jiffies after 100ms */
131 timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
132 do {
133 qla8044_rd_reg_indirect(vha, addr1, &temp);
134 if ((temp & mask) != 0)
135 break;
136 if (time_after_eq(jiffies, timeout)) {
137 ql_log(ql_log_warn, vha, 0xb151,
138 "Error in processing rdmdio entry\n");
139 return -1;
140 }
141 } while (1);
142
143 return 0;
144}
145
146static uint32_t
147qla8044_ipmdio_rd_reg(struct scsi_qla_host *vha,
148 uint32_t addr1, uint32_t addr3, uint32_t mask, uint32_t addr)
149{
150 uint32_t temp;
151 int ret = 0;
152
153 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
154 if (ret == -1)
155 return -1;
156
157 temp = (0x40000000 | addr);
158 qla8044_wr_reg_indirect(vha, addr1, temp);
159
160 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
161 if (ret == -1)
162 return 0;
163
164 qla8044_rd_reg_indirect(vha, addr3, &ret);
165
166 return ret;
167}
168
169
170static int
171qla8044_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *vha,
172 uint32_t addr1, uint32_t addr2, uint32_t addr3, uint32_t mask)
173{
174 unsigned long timeout;
175 uint32_t temp;
176
177 /* jiffies after 100 msecs */
178 timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS);
179 do {
180 temp = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr2);
181 if ((temp & 0x1) != 1)
182 break;
183 if (time_after_eq(jiffies, timeout)) {
184 ql_log(ql_log_warn, vha, 0xb152,
185 "Error in processing mdiobus idle\n");
186 return -1;
187 }
188 } while (1);
189
190 return 0;
191}
192
193static int
194qla8044_ipmdio_wr_reg(struct scsi_qla_host *vha, uint32_t addr1,
195 uint32_t addr3, uint32_t mask, uint32_t addr, uint32_t value)
196{
197 int ret = 0;
198
199 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
200 if (ret == -1)
201 return -1;
202
203 qla8044_wr_reg_indirect(vha, addr3, value);
204 qla8044_wr_reg_indirect(vha, addr1, addr);
205
206 ret = qla8044_poll_wait_for_ready(vha, addr1, mask);
207 if (ret == -1)
208 return -1;
209
210 return 0;
211}
120/* 212/*
121 * qla8044_rmw_crb_reg - Read value from raddr, AND with test_mask, 213 * qla8044_rmw_crb_reg - Read value from raddr, AND with test_mask,
122 * Shift Left,Right/OR/XOR with values RMW header and write value to waddr. 214 * Shift Left,Right/OR/XOR with values RMW header and write value to waddr.
@@ -356,8 +448,8 @@ qla8044_flash_lock(scsi_qla_host_t *vha)
356 lock_owner = qla8044_rd_reg(ha, 448 lock_owner = qla8044_rd_reg(ha,
357 QLA8044_FLASH_LOCK_ID); 449 QLA8044_FLASH_LOCK_ID);
358 ql_log(ql_log_warn, vha, 0xb113, 450 ql_log(ql_log_warn, vha, 0xb113,
359 "%s: flash lock by %d failed, held by %d\n", 451 "%s: Simultaneous flash access by following ports, active port = %d: accessing port = %d",
360 __func__, ha->portnum, lock_owner); 452 __func__, ha->portnum, lock_owner);
361 ret_val = QLA_FUNCTION_FAILED; 453 ret_val = QLA_FUNCTION_FAILED;
362 break; 454 break;
363 } 455 }
@@ -1541,7 +1633,7 @@ static void
1541qla8044_need_reset_handler(struct scsi_qla_host *vha) 1633qla8044_need_reset_handler(struct scsi_qla_host *vha)
1542{ 1634{
1543 uint32_t dev_state = 0, drv_state, drv_active; 1635 uint32_t dev_state = 0, drv_state, drv_active;
1544 unsigned long reset_timeout, dev_init_timeout; 1636 unsigned long reset_timeout;
1545 struct qla_hw_data *ha = vha->hw; 1637 struct qla_hw_data *ha = vha->hw;
1546 1638
1547 ql_log(ql_log_fatal, vha, 0xb0c2, 1639 ql_log(ql_log_fatal, vha, 0xb0c2,
@@ -1555,84 +1647,78 @@ qla8044_need_reset_handler(struct scsi_qla_host *vha)
1555 qla8044_idc_lock(ha); 1647 qla8044_idc_lock(ha);
1556 } 1648 }
1557 1649
1650 dev_state = qla8044_rd_direct(vha,
1651 QLA8044_CRB_DEV_STATE_INDEX);
1558 drv_state = qla8044_rd_direct(vha, 1652 drv_state = qla8044_rd_direct(vha,
1559 QLA8044_CRB_DRV_STATE_INDEX); 1653 QLA8044_CRB_DRV_STATE_INDEX);
1560 drv_active = qla8044_rd_direct(vha, 1654 drv_active = qla8044_rd_direct(vha,
1561 QLA8044_CRB_DRV_ACTIVE_INDEX); 1655 QLA8044_CRB_DRV_ACTIVE_INDEX);
1562 1656
1563 ql_log(ql_log_info, vha, 0xb0c5, 1657 ql_log(ql_log_info, vha, 0xb0c5,
1564 "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", 1658 "%s(%ld): drv_state = 0x%x, drv_active = 0x%x dev_state = 0x%x\n",
1565 __func__, vha->host_no, drv_state, drv_active); 1659 __func__, vha->host_no, drv_state, drv_active, dev_state);
1566 1660
1567 if (!ha->flags.nic_core_reset_owner) { 1661 qla8044_set_rst_ready(vha);
1568 ql_dbg(ql_dbg_p3p, vha, 0xb0c3,
1569 "%s(%ld): reset acknowledged\n",
1570 __func__, vha->host_no);
1571 qla8044_set_rst_ready(vha);
1572 1662
1573 /* Non-reset owners ACK Reset and wait for device INIT state 1663 /* wait for 10 seconds for reset ack from all functions */
1574 * as part of Reset Recovery by Reset Owner 1664 reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
1575 */
1576 dev_init_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
1577 1665
1578 do { 1666 do {
1579 if (time_after_eq(jiffies, dev_init_timeout)) { 1667 if (time_after_eq(jiffies, reset_timeout)) {
1580 ql_log(ql_log_info, vha, 0xb0c4, 1668 ql_log(ql_log_info, vha, 0xb0c4,
1581 "%s: Non Reset owner: Reset Ack Timeout!\n", 1669 "%s: Function %d: Reset Ack Timeout!, drv_state: 0x%08x, drv_active: 0x%08x\n",
1582 __func__); 1670 __func__, ha->portnum, drv_state, drv_active);
1583 break; 1671 break;
1584 } 1672 }
1585 1673
1586 qla8044_idc_unlock(ha); 1674 qla8044_idc_unlock(ha);
1587 msleep(1000); 1675 msleep(1000);
1588 qla8044_idc_lock(ha); 1676 qla8044_idc_lock(ha);
1589 1677
1590 dev_state = qla8044_rd_direct(vha, 1678 dev_state = qla8044_rd_direct(vha,
1591 QLA8044_CRB_DEV_STATE_INDEX); 1679 QLA8044_CRB_DEV_STATE_INDEX);
1592 } while (((drv_state & drv_active) != drv_active) && 1680 drv_state = qla8044_rd_direct(vha,
1593 (dev_state == QLA8XXX_DEV_NEED_RESET)); 1681 QLA8044_CRB_DRV_STATE_INDEX);
1682 drv_active = qla8044_rd_direct(vha,
1683 QLA8044_CRB_DRV_ACTIVE_INDEX);
1684 } while (((drv_state & drv_active) != drv_active) &&
1685 (dev_state == QLA8XXX_DEV_NEED_RESET));
1686
1687 /* Remove IDC participation of functions not acknowledging */
1688 if (drv_state != drv_active) {
1689 ql_log(ql_log_info, vha, 0xb0c7,
1690 "%s(%ld): Function %d turning off drv_active of non-acking function 0x%x\n",
1691 __func__, vha->host_no, ha->portnum,
1692 (drv_active ^ drv_state));
1693 drv_active = drv_active & drv_state;
1694 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX,
1695 drv_active);
1594 } else { 1696 } else {
1595 qla8044_set_rst_ready(vha); 1697 /*
1596 1698 * Reset owner should execute reset recovery,
1597 /* wait for 10 seconds for reset ack from all functions */ 1699 * if all functions acknowledged
1598 reset_timeout = jiffies + (ha->fcoe_reset_timeout * HZ); 1700 */
1599 1701 if ((ha->flags.nic_core_reset_owner) &&
1600 while ((drv_state & drv_active) != drv_active) { 1702 (dev_state == QLA8XXX_DEV_NEED_RESET)) {
1601 if (time_after_eq(jiffies, reset_timeout)) { 1703 ha->flags.nic_core_reset_owner = 0;
1602 ql_log(ql_log_info, vha, 0xb0c6, 1704 qla8044_device_bootstrap(vha);
1603 "%s: RESET TIMEOUT!" 1705 return;
1604 "drv_state: 0x%08x, drv_active: 0x%08x\n",
1605 QLA2XXX_DRIVER_NAME, drv_state, drv_active);
1606 break;
1607 }
1608
1609 qla8044_idc_unlock(ha);
1610 msleep(1000);
1611 qla8044_idc_lock(ha);
1612
1613 drv_state = qla8044_rd_direct(vha,
1614 QLA8044_CRB_DRV_STATE_INDEX);
1615 drv_active = qla8044_rd_direct(vha,
1616 QLA8044_CRB_DRV_ACTIVE_INDEX);
1617 }
1618
1619 if (drv_state != drv_active) {
1620 ql_log(ql_log_info, vha, 0xb0c7,
1621 "%s(%ld): Reset_owner turning off drv_active "
1622 "of non-acking function 0x%x\n", __func__,
1623 vha->host_no, (drv_active ^ drv_state));
1624 drv_active = drv_active & drv_state;
1625 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX,
1626 drv_active);
1627 } 1706 }
1707 }
1628 1708
1629 /* 1709 /* Exit if non active function */
1630 * Clear RESET OWNER, will be set at next reset 1710 if (!(drv_active & (1 << ha->portnum))) {
1631 * by next RST_OWNER
1632 */
1633 ha->flags.nic_core_reset_owner = 0; 1711 ha->flags.nic_core_reset_owner = 0;
1712 return;
1713 }
1634 1714
1635 /* Start Reset Recovery */ 1715 /*
1716 * Execute Reset Recovery if Reset Owner or Function 7
1717 * is the only active function
1718 */
1719 if (ha->flags.nic_core_reset_owner ||
1720 ((drv_state & drv_active) == QLA8044_FUN7_ACTIVE_INDEX)) {
1721 ha->flags.nic_core_reset_owner = 0;
1636 qla8044_device_bootstrap(vha); 1722 qla8044_device_bootstrap(vha);
1637 } 1723 }
1638} 1724}
@@ -1655,6 +1741,19 @@ qla8044_set_drv_active(struct scsi_qla_host *vha)
1655 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active); 1741 qla8044_wr_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX, drv_active);
1656} 1742}
1657 1743
1744static int
1745qla8044_check_drv_active(struct scsi_qla_host *vha)
1746{
1747 uint32_t drv_active;
1748 struct qla_hw_data *ha = vha->hw;
1749
1750 drv_active = qla8044_rd_direct(vha, QLA8044_CRB_DRV_ACTIVE_INDEX);
1751 if (drv_active & (1 << ha->portnum))
1752 return QLA_SUCCESS;
1753 else
1754 return QLA_TEST_FAILED;
1755}
1756
1658static void 1757static void
1659qla8044_clear_idc_dontreset(struct scsi_qla_host *vha) 1758qla8044_clear_idc_dontreset(struct scsi_qla_host *vha)
1660{ 1759{
@@ -1837,14 +1936,16 @@ qla8044_device_state_handler(struct scsi_qla_host *vha)
1837 1936
1838 while (1) { 1937 while (1) {
1839 if (time_after_eq(jiffies, dev_init_timeout)) { 1938 if (time_after_eq(jiffies, dev_init_timeout)) {
1840 ql_log(ql_log_warn, vha, 0xb0cf, 1939 if (qla8044_check_drv_active(vha) == QLA_SUCCESS) {
1841 "%s: Device Init Failed 0x%x = %s\n", 1940 ql_log(ql_log_warn, vha, 0xb0cf,
1842 QLA2XXX_DRIVER_NAME, dev_state, 1941 "%s: Device Init Failed 0x%x = %s\n",
1843 dev_state < MAX_STATES ? 1942 QLA2XXX_DRIVER_NAME, dev_state,
1844 qdev_state(dev_state) : "Unknown"); 1943 dev_state < MAX_STATES ?
1845 1944 qdev_state(dev_state) : "Unknown");
1846 qla8044_wr_direct(vha, QLA8044_CRB_DEV_STATE_INDEX, 1945 qla8044_wr_direct(vha,
1847 QLA8XXX_DEV_FAILED); 1946 QLA8044_CRB_DEV_STATE_INDEX,
1947 QLA8XXX_DEV_FAILED);
1948 }
1848 } 1949 }
1849 1950
1850 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX); 1951 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
@@ -2017,6 +2118,13 @@ qla8044_watchdog(struct scsi_qla_host *vha)
2017 test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags))) { 2118 test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags))) {
2018 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX); 2119 dev_state = qla8044_rd_direct(vha, QLA8044_CRB_DEV_STATE_INDEX);
2019 2120
2121 if (qla8044_check_fw_alive(vha)) {
2122 ha->flags.isp82xx_fw_hung = 1;
2123 ql_log(ql_log_warn, vha, 0xb10a,
2124 "Firmware hung.\n");
2125 qla82xx_clear_pending_mbx(vha);
2126 }
2127
2020 if (qla8044_check_temp(vha)) { 2128 if (qla8044_check_temp(vha)) {
2021 set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags); 2129 set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
2022 ha->flags.isp82xx_fw_hung = 1; 2130 ha->flags.isp82xx_fw_hung = 1;
@@ -2037,7 +2145,7 @@ qla8044_watchdog(struct scsi_qla_host *vha)
2037 qla2xxx_wake_dpc(vha); 2145 qla2xxx_wake_dpc(vha);
2038 } else { 2146 } else {
2039 /* Check firmware health */ 2147 /* Check firmware health */
2040 if (qla8044_check_fw_alive(vha)) { 2148 if (ha->flags.isp82xx_fw_hung) {
2041 halt_status = qla8044_rd_direct(vha, 2149 halt_status = qla8044_rd_direct(vha,
2042 QLA8044_PEG_HALT_STATUS1_INDEX); 2150 QLA8044_PEG_HALT_STATUS1_INDEX);
2043 if (halt_status & 2151 if (halt_status &
@@ -2073,12 +2181,8 @@ qla8044_watchdog(struct scsi_qla_host *vha)
2073 __func__); 2181 __func__);
2074 set_bit(ISP_ABORT_NEEDED, 2182 set_bit(ISP_ABORT_NEEDED,
2075 &vha->dpc_flags); 2183 &vha->dpc_flags);
2076 qla82xx_clear_pending_mbx(vha);
2077 } 2184 }
2078 } 2185 }
2079 ha->flags.isp82xx_fw_hung = 1;
2080 ql_log(ql_log_warn, vha, 0xb10a,
2081 "Firmware hung.\n");
2082 qla2xxx_wake_dpc(vha); 2186 qla2xxx_wake_dpc(vha);
2083 } 2187 }
2084 } 2188 }
@@ -2286,8 +2390,6 @@ qla8044_minidump_process_rdmem(struct scsi_qla_host *vha,
2286 } 2390 }
2287 2391
2288 if (j >= MAX_CTL_CHECK) { 2392 if (j >= MAX_CTL_CHECK) {
2289 printk_ratelimited(KERN_ERR
2290 "%s: failed to read through agent\n", __func__);
2291 write_unlock_irqrestore(&ha->hw_lock, flags); 2393 write_unlock_irqrestore(&ha->hw_lock, flags);
2292 return QLA_SUCCESS; 2394 return QLA_SUCCESS;
2293 } 2395 }
@@ -2882,6 +2984,231 @@ error_exit:
2882 return rval; 2984 return rval;
2883} 2985}
2884 2986
2987static uint32_t
2988qla8044_minidump_process_rddfe(struct scsi_qla_host *vha,
2989 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
2990{
2991 int loop_cnt;
2992 uint32_t addr1, addr2, value, data, temp, wrVal;
2993 uint8_t stride, stride2;
2994 uint16_t count;
2995 uint32_t poll, mask, data_size, modify_mask;
2996 uint32_t wait_count = 0;
2997
2998 uint32_t *data_ptr = *d_ptr;
2999
3000 struct qla8044_minidump_entry_rddfe *rddfe;
3001 rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr;
3002
3003 addr1 = rddfe->addr_1;
3004 value = rddfe->value;
3005 stride = rddfe->stride;
3006 stride2 = rddfe->stride2;
3007 count = rddfe->count;
3008
3009 poll = rddfe->poll;
3010 mask = rddfe->mask;
3011 modify_mask = rddfe->modify_mask;
3012 data_size = rddfe->data_size;
3013
3014 addr2 = addr1 + stride;
3015
3016 for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) {
3017 qla8044_wr_reg_indirect(vha, addr1, (0x40000000 | value));
3018
3019 wait_count = 0;
3020 while (wait_count < poll) {
3021 qla8044_rd_reg_indirect(vha, addr1, &temp);
3022 if ((temp & mask) != 0)
3023 break;
3024 wait_count++;
3025 }
3026
3027 if (wait_count == poll) {
3028 ql_log(ql_log_warn, vha, 0xb153,
3029 "%s: TIMEOUT\n", __func__);
3030 goto error;
3031 } else {
3032 qla8044_rd_reg_indirect(vha, addr2, &temp);
3033 temp = temp & modify_mask;
3034 temp = (temp | ((loop_cnt << 16) | loop_cnt));
3035 wrVal = ((temp << 16) | temp);
3036
3037 qla8044_wr_reg_indirect(vha, addr2, wrVal);
3038 qla8044_wr_reg_indirect(vha, addr1, value);
3039
3040 wait_count = 0;
3041 while (wait_count < poll) {
3042 qla8044_rd_reg_indirect(vha, addr1, &temp);
3043 if ((temp & mask) != 0)
3044 break;
3045 wait_count++;
3046 }
3047 if (wait_count == poll) {
3048 ql_log(ql_log_warn, vha, 0xb154,
3049 "%s: TIMEOUT\n", __func__);
3050 goto error;
3051 }
3052
3053 qla8044_wr_reg_indirect(vha, addr1,
3054 ((0x40000000 | value) + stride2));
3055 wait_count = 0;
3056 while (wait_count < poll) {
3057 qla8044_rd_reg_indirect(vha, addr1, &temp);
3058 if ((temp & mask) != 0)
3059 break;
3060 wait_count++;
3061 }
3062
3063 if (wait_count == poll) {
3064 ql_log(ql_log_warn, vha, 0xb155,
3065 "%s: TIMEOUT\n", __func__);
3066 goto error;
3067 }
3068
3069 qla8044_rd_reg_indirect(vha, addr2, &data);
3070
3071 *data_ptr++ = wrVal;
3072 *data_ptr++ = data;
3073 }
3074
3075 }
3076
3077 *d_ptr = data_ptr;
3078 return QLA_SUCCESS;
3079
3080error:
3081 return -1;
3082
3083}
3084
3085static uint32_t
3086qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha,
3087 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3088{
3089 int ret = 0;
3090 uint32_t addr1, addr2, value1, value2, data, selVal;
3091 uint8_t stride1, stride2;
3092 uint32_t addr3, addr4, addr5, addr6, addr7;
3093 uint16_t count, loop_cnt;
3094 uint32_t poll, mask;
3095 uint32_t *data_ptr = *d_ptr;
3096
3097 struct qla8044_minidump_entry_rdmdio *rdmdio;
3098
3099 rdmdio = (struct qla8044_minidump_entry_rdmdio *) entry_hdr;
3100
3101 addr1 = rdmdio->addr_1;
3102 addr2 = rdmdio->addr_2;
3103 value1 = rdmdio->value_1;
3104 stride1 = rdmdio->stride_1;
3105 stride2 = rdmdio->stride_2;
3106 count = rdmdio->count;
3107
3108 poll = rdmdio->poll;
3109 mask = rdmdio->mask;
3110 value2 = rdmdio->value_2;
3111
3112 addr3 = addr1 + stride1;
3113
3114 for (loop_cnt = 0; loop_cnt < count; loop_cnt++) {
3115 ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3116 addr3, mask);
3117 if (ret == -1)
3118 goto error;
3119
3120 addr4 = addr2 - stride1;
3121 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr4,
3122 value2);
3123 if (ret == -1)
3124 goto error;
3125
3126 addr5 = addr2 - (2 * stride1);
3127 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask, addr5,
3128 value1);
3129 if (ret == -1)
3130 goto error;
3131
3132 addr6 = addr2 - (3 * stride1);
3133 ret = qla8044_ipmdio_wr_reg(vha, addr1, addr3, mask,
3134 addr6, 0x2);
3135 if (ret == -1)
3136 goto error;
3137
3138 ret = qla8044_poll_wait_ipmdio_bus_idle(vha, addr1, addr2,
3139 addr3, mask);
3140 if (ret == -1)
3141 goto error;
3142
3143 addr7 = addr2 - (4 * stride1);
3144 data = qla8044_ipmdio_rd_reg(vha, addr1, addr3,
3145 mask, addr7);
3146 if (data == -1)
3147 goto error;
3148
3149 selVal = (value2 << 18) | (value1 << 2) | 2;
3150
3151 stride2 = rdmdio->stride_2;
3152 *data_ptr++ = selVal;
3153 *data_ptr++ = data;
3154
3155 value1 = value1 + stride2;
3156 *d_ptr = data_ptr;
3157 }
3158
3159 return 0;
3160
3161error:
3162 return -1;
3163}
3164
3165static uint32_t qla8044_minidump_process_pollwr(struct scsi_qla_host *vha,
3166 struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr)
3167{
3168 uint32_t addr1, addr2, value1, value2, poll, mask, r_value;
3169 uint32_t wait_count = 0;
3170 struct qla8044_minidump_entry_pollwr *pollwr_hdr;
3171
3172 pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr;
3173 addr1 = pollwr_hdr->addr_1;
3174 addr2 = pollwr_hdr->addr_2;
3175 value1 = pollwr_hdr->value_1;
3176 value2 = pollwr_hdr->value_2;
3177
3178 poll = pollwr_hdr->poll;
3179 mask = pollwr_hdr->mask;
3180
3181 while (wait_count < poll) {
3182 qla8044_rd_reg_indirect(vha, addr1, &r_value);
3183
3184 if ((r_value & poll) != 0)
3185 break;
3186 wait_count++;
3187 }
3188
3189 if (wait_count == poll) {
3190 ql_log(ql_log_warn, vha, 0xb156, "%s: TIMEOUT\n", __func__);
3191 goto error;
3192 }
3193
3194 qla8044_wr_reg_indirect(vha, addr2, value2);
3195 qla8044_wr_reg_indirect(vha, addr1, value1);
3196
3197 wait_count = 0;
3198 while (wait_count < poll) {
3199 qla8044_rd_reg_indirect(vha, addr1, &r_value);
3200
3201 if ((r_value & poll) != 0)
3202 break;
3203 wait_count++;
3204 }
3205
3206 return QLA_SUCCESS;
3207
3208error:
3209 return -1;
3210}
3211
2885/* 3212/*
2886 * 3213 *
2887 * qla8044_collect_md_data - Retrieve firmware minidump data. 3214 * qla8044_collect_md_data - Retrieve firmware minidump data.
@@ -3089,6 +3416,24 @@ qla8044_collect_md_data(struct scsi_qla_host *vha)
3089 if (rval != QLA_SUCCESS) 3416 if (rval != QLA_SUCCESS)
3090 qla8044_mark_entry_skipped(vha, entry_hdr, i); 3417 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3091 break; 3418 break;
3419 case QLA8044_RDDFE:
3420 rval = qla8044_minidump_process_rddfe(vha, entry_hdr,
3421 &data_ptr);
3422 if (rval != QLA_SUCCESS)
3423 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3424 break;
3425 case QLA8044_RDMDIO:
3426 rval = qla8044_minidump_process_rdmdio(vha, entry_hdr,
3427 &data_ptr);
3428 if (rval != QLA_SUCCESS)
3429 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3430 break;
3431 case QLA8044_POLLWR:
3432 rval = qla8044_minidump_process_pollwr(vha, entry_hdr,
3433 &data_ptr);
3434 if (rval != QLA_SUCCESS)
3435 qla8044_mark_entry_skipped(vha, entry_hdr, i);
3436 break;
3092 case QLA82XX_RDNOP: 3437 case QLA82XX_RDNOP:
3093 default: 3438 default:
3094 qla8044_mark_entry_skipped(vha, entry_hdr, i); 3439 qla8044_mark_entry_skipped(vha, entry_hdr, i);
@@ -3110,6 +3455,7 @@ skip_nxt_entry:
3110 "Dump data mismatch: Data collected: " 3455 "Dump data mismatch: Data collected: "
3111 "[0x%x], total_data_size:[0x%x]\n", 3456 "[0x%x], total_data_size:[0x%x]\n",
3112 data_collected, ha->md_dump_size); 3457 data_collected, ha->md_dump_size);
3458 rval = QLA_FUNCTION_FAILED;
3113 goto md_failed; 3459 goto md_failed;
3114 } 3460 }
3115 3461
@@ -3134,10 +3480,12 @@ qla8044_get_minidump(struct scsi_qla_host *vha)
3134 3480
3135 if (!qla8044_collect_md_data(vha)) { 3481 if (!qla8044_collect_md_data(vha)) {
3136 ha->fw_dumped = 1; 3482 ha->fw_dumped = 1;
3483 ha->prev_minidump_failed = 0;
3137 } else { 3484 } else {
3138 ql_log(ql_log_fatal, vha, 0xb0db, 3485 ql_log(ql_log_fatal, vha, 0xb0db,
3139 "%s: Unable to collect minidump\n", 3486 "%s: Unable to collect minidump\n",
3140 __func__); 3487 __func__);
3488 ha->prev_minidump_failed = 1;
3141 } 3489 }
3142} 3490}
3143 3491