diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_nx.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 488 |
1 files changed, 444 insertions, 44 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 6daa25c50a99..3e5560840364 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/ratelimit.h> | 10 | #include <linux/ratelimit.h> |
11 | #include "ql4_def.h" | 11 | #include "ql4_def.h" |
12 | #include "ql4_glbl.h" | 12 | #include "ql4_glbl.h" |
13 | #include "ql4_inline.h" | ||
13 | 14 | ||
14 | #include <asm-generic/io-64-nonatomic-lo-hi.h> | 15 | #include <asm-generic/io-64-nonatomic-lo-hi.h> |
15 | 16 | ||
@@ -1511,7 +1512,17 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | |||
1511 | uint32_t drv_active; | 1512 | uint32_t drv_active; |
1512 | 1513 | ||
1513 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); | 1514 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); |
1514 | drv_active |= (1 << (ha->func_num * 4)); | 1515 | |
1516 | /* | ||
1517 | * For ISP8324, drv_active register has 1 bit per function, | ||
1518 | * shift 1 by func_num to set a bit for the function. | ||
1519 | * For ISP8022, drv_active has 4 bits per function | ||
1520 | */ | ||
1521 | if (is_qla8032(ha)) | ||
1522 | drv_active |= (1 << ha->func_num); | ||
1523 | else | ||
1524 | drv_active |= (1 << (ha->func_num * 4)); | ||
1525 | |||
1515 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | 1526 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", |
1516 | __func__, ha->host_no, drv_active); | 1527 | __func__, ha->host_no, drv_active); |
1517 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); | 1528 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); |
@@ -1523,7 +1534,17 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | |||
1523 | uint32_t drv_active; | 1534 | uint32_t drv_active; |
1524 | 1535 | ||
1525 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); | 1536 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); |
1526 | drv_active &= ~(1 << (ha->func_num * 4)); | 1537 | |
1538 | /* | ||
1539 | * For ISP8324, drv_active register has 1 bit per function, | ||
1540 | * shift 1 by func_num to set a bit for the function. | ||
1541 | * For ISP8022, drv_active has 4 bits per function | ||
1542 | */ | ||
1543 | if (is_qla8032(ha)) | ||
1544 | drv_active &= ~(1 << (ha->func_num)); | ||
1545 | else | ||
1546 | drv_active &= ~(1 << (ha->func_num * 4)); | ||
1547 | |||
1527 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | 1548 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", |
1528 | __func__, ha->host_no, drv_active); | 1549 | __func__, ha->host_no, drv_active); |
1529 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); | 1550 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_ACTIVE, drv_active); |
@@ -1536,32 +1557,60 @@ inline int qla4_8xxx_need_reset(struct scsi_qla_host *ha) | |||
1536 | 1557 | ||
1537 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); | 1558 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); |
1538 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); | 1559 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); |
1539 | rval = drv_state & (1 << (ha->func_num * 4)); | 1560 | |
1561 | /* | ||
1562 | * For ISP8324, drv_active register has 1 bit per function, | ||
1563 | * shift 1 by func_num to set a bit for the function. | ||
1564 | * For ISP8022, drv_active has 4 bits per function | ||
1565 | */ | ||
1566 | if (is_qla8032(ha)) | ||
1567 | rval = drv_state & (1 << ha->func_num); | ||
1568 | else | ||
1569 | rval = drv_state & (1 << (ha->func_num * 4)); | ||
1570 | |||
1540 | if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) | 1571 | if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) |
1541 | rval = 1; | 1572 | rval = 1; |
1542 | 1573 | ||
1543 | return rval; | 1574 | return rval; |
1544 | } | 1575 | } |
1545 | 1576 | ||
1546 | static inline void | 1577 | void qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) |
1547 | qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) | ||
1548 | { | 1578 | { |
1549 | uint32_t drv_state; | 1579 | uint32_t drv_state; |
1550 | 1580 | ||
1551 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); | 1581 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); |
1552 | drv_state |= (1 << (ha->func_num * 4)); | 1582 | |
1583 | /* | ||
1584 | * For ISP8324, drv_active register has 1 bit per function, | ||
1585 | * shift 1 by func_num to set a bit for the function. | ||
1586 | * For ISP8022, drv_active has 4 bits per function | ||
1587 | */ | ||
1588 | if (is_qla8032(ha)) | ||
1589 | drv_state |= (1 << ha->func_num); | ||
1590 | else | ||
1591 | drv_state |= (1 << (ha->func_num * 4)); | ||
1592 | |||
1553 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | 1593 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", |
1554 | __func__, ha->host_no, drv_state); | 1594 | __func__, ha->host_no, drv_state); |
1555 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); | 1595 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); |
1556 | } | 1596 | } |
1557 | 1597 | ||
1558 | static inline void | 1598 | void qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) |
1559 | qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) | ||
1560 | { | 1599 | { |
1561 | uint32_t drv_state; | 1600 | uint32_t drv_state; |
1562 | 1601 | ||
1563 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); | 1602 | drv_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); |
1564 | drv_state &= ~(1 << (ha->func_num * 4)); | 1603 | |
1604 | /* | ||
1605 | * For ISP8324, drv_active register has 1 bit per function, | ||
1606 | * shift 1 by func_num to set a bit for the function. | ||
1607 | * For ISP8022, drv_active has 4 bits per function | ||
1608 | */ | ||
1609 | if (is_qla8032(ha)) | ||
1610 | drv_state &= ~(1 << ha->func_num); | ||
1611 | else | ||
1612 | drv_state &= ~(1 << (ha->func_num * 4)); | ||
1613 | |||
1565 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | 1614 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", |
1566 | __func__, ha->host_no, drv_state); | 1615 | __func__, ha->host_no, drv_state); |
1567 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); | 1616 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, drv_state); |
@@ -1573,7 +1622,17 @@ qla4_8xxx_set_qsnt_ready(struct scsi_qla_host *ha) | |||
1573 | uint32_t qsnt_state; | 1622 | uint32_t qsnt_state; |
1574 | 1623 | ||
1575 | qsnt_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); | 1624 | qsnt_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_STATE); |
1576 | qsnt_state |= (2 << (ha->func_num * 4)); | 1625 | |
1626 | /* | ||
1627 | * For ISP8324, drv_active register has 1 bit per function, | ||
1628 | * shift 1 by func_num to set a bit for the function. | ||
1629 | * For ISP8022, drv_active has 4 bits per function. | ||
1630 | */ | ||
1631 | if (is_qla8032(ha)) | ||
1632 | qsnt_state |= (1 << ha->func_num); | ||
1633 | else | ||
1634 | qsnt_state |= (2 << (ha->func_num * 4)); | ||
1635 | |||
1577 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, qsnt_state); | 1636 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, qsnt_state); |
1578 | } | 1637 | } |
1579 | 1638 | ||
@@ -2104,6 +2163,196 @@ static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, | |||
2104 | entry_hdr->d_ctrl.entry_capture_mask)); | 2163 | entry_hdr->d_ctrl.entry_capture_mask)); |
2105 | } | 2164 | } |
2106 | 2165 | ||
2166 | /* ISP83xx functions to process new minidump entries... */ | ||
2167 | static uint32_t qla83xx_minidump_process_pollrd(struct scsi_qla_host *ha, | ||
2168 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2169 | uint32_t **d_ptr) | ||
2170 | { | ||
2171 | uint32_t r_addr, s_addr, s_value, r_value, poll_wait, poll_mask; | ||
2172 | uint16_t s_stride, i; | ||
2173 | uint32_t *data_ptr = *d_ptr; | ||
2174 | uint32_t rval = QLA_SUCCESS; | ||
2175 | struct qla83xx_minidump_entry_pollrd *pollrd_hdr; | ||
2176 | |||
2177 | pollrd_hdr = (struct qla83xx_minidump_entry_pollrd *)entry_hdr; | ||
2178 | s_addr = le32_to_cpu(pollrd_hdr->select_addr); | ||
2179 | r_addr = le32_to_cpu(pollrd_hdr->read_addr); | ||
2180 | s_value = le32_to_cpu(pollrd_hdr->select_value); | ||
2181 | s_stride = le32_to_cpu(pollrd_hdr->select_value_stride); | ||
2182 | |||
2183 | poll_wait = le32_to_cpu(pollrd_hdr->poll_wait); | ||
2184 | poll_mask = le32_to_cpu(pollrd_hdr->poll_mask); | ||
2185 | |||
2186 | for (i = 0; i < le32_to_cpu(pollrd_hdr->op_count); i++) { | ||
2187 | ha->isp_ops->wr_reg_indirect(ha, s_addr, s_value); | ||
2188 | poll_wait = le32_to_cpu(pollrd_hdr->poll_wait); | ||
2189 | while (1) { | ||
2190 | ha->isp_ops->rd_reg_indirect(ha, s_addr, &r_value); | ||
2191 | |||
2192 | if ((r_value & poll_mask) != 0) { | ||
2193 | break; | ||
2194 | } else { | ||
2195 | msleep(1); | ||
2196 | if (--poll_wait == 0) { | ||
2197 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", | ||
2198 | __func__); | ||
2199 | rval = QLA_ERROR; | ||
2200 | goto exit_process_pollrd; | ||
2201 | } | ||
2202 | } | ||
2203 | } | ||
2204 | ha->isp_ops->rd_reg_indirect(ha, r_addr, &r_value); | ||
2205 | *data_ptr++ = cpu_to_le32(s_value); | ||
2206 | *data_ptr++ = cpu_to_le32(r_value); | ||
2207 | s_value += s_stride; | ||
2208 | } | ||
2209 | |||
2210 | *d_ptr = data_ptr; | ||
2211 | |||
2212 | exit_process_pollrd: | ||
2213 | return rval; | ||
2214 | } | ||
2215 | |||
2216 | static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha, | ||
2217 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2218 | uint32_t **d_ptr) | ||
2219 | { | ||
2220 | uint32_t sel_val1, sel_val2, t_sel_val, data, i; | ||
2221 | uint32_t sel_addr1, sel_addr2, sel_val_mask, read_addr; | ||
2222 | struct qla83xx_minidump_entry_rdmux2 *rdmux2_hdr; | ||
2223 | uint32_t *data_ptr = *d_ptr; | ||
2224 | |||
2225 | rdmux2_hdr = (struct qla83xx_minidump_entry_rdmux2 *)entry_hdr; | ||
2226 | sel_val1 = le32_to_cpu(rdmux2_hdr->select_value_1); | ||
2227 | sel_val2 = le32_to_cpu(rdmux2_hdr->select_value_2); | ||
2228 | sel_addr1 = le32_to_cpu(rdmux2_hdr->select_addr_1); | ||
2229 | sel_addr2 = le32_to_cpu(rdmux2_hdr->select_addr_2); | ||
2230 | sel_val_mask = le32_to_cpu(rdmux2_hdr->select_value_mask); | ||
2231 | read_addr = le32_to_cpu(rdmux2_hdr->read_addr); | ||
2232 | |||
2233 | for (i = 0; i < rdmux2_hdr->op_count; i++) { | ||
2234 | ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val1); | ||
2235 | t_sel_val = sel_val1 & sel_val_mask; | ||
2236 | *data_ptr++ = cpu_to_le32(t_sel_val); | ||
2237 | |||
2238 | ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val); | ||
2239 | ha->isp_ops->rd_reg_indirect(ha, read_addr, &data); | ||
2240 | |||
2241 | *data_ptr++ = cpu_to_le32(data); | ||
2242 | |||
2243 | ha->isp_ops->wr_reg_indirect(ha, sel_addr1, sel_val2); | ||
2244 | t_sel_val = sel_val2 & sel_val_mask; | ||
2245 | *data_ptr++ = cpu_to_le32(t_sel_val); | ||
2246 | |||
2247 | ha->isp_ops->wr_reg_indirect(ha, sel_addr2, t_sel_val); | ||
2248 | ha->isp_ops->rd_reg_indirect(ha, read_addr, &data); | ||
2249 | |||
2250 | *data_ptr++ = cpu_to_le32(data); | ||
2251 | |||
2252 | sel_val1 += rdmux2_hdr->select_value_stride; | ||
2253 | sel_val2 += rdmux2_hdr->select_value_stride; | ||
2254 | } | ||
2255 | |||
2256 | *d_ptr = data_ptr; | ||
2257 | } | ||
2258 | |||
2259 | static uint32_t qla83xx_minidump_process_pollrdmwr(struct scsi_qla_host *ha, | ||
2260 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2261 | uint32_t **d_ptr) | ||
2262 | { | ||
2263 | uint32_t poll_wait, poll_mask, r_value, data; | ||
2264 | uint32_t addr_1, addr_2, value_1, value_2; | ||
2265 | uint32_t *data_ptr = *d_ptr; | ||
2266 | uint32_t rval = QLA_SUCCESS; | ||
2267 | struct qla83xx_minidump_entry_pollrdmwr *poll_hdr; | ||
2268 | |||
2269 | poll_hdr = (struct qla83xx_minidump_entry_pollrdmwr *)entry_hdr; | ||
2270 | addr_1 = le32_to_cpu(poll_hdr->addr_1); | ||
2271 | addr_2 = le32_to_cpu(poll_hdr->addr_2); | ||
2272 | value_1 = le32_to_cpu(poll_hdr->value_1); | ||
2273 | value_2 = le32_to_cpu(poll_hdr->value_2); | ||
2274 | poll_mask = le32_to_cpu(poll_hdr->poll_mask); | ||
2275 | |||
2276 | ha->isp_ops->wr_reg_indirect(ha, addr_1, value_1); | ||
2277 | |||
2278 | poll_wait = le32_to_cpu(poll_hdr->poll_wait); | ||
2279 | while (1) { | ||
2280 | ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value); | ||
2281 | |||
2282 | if ((r_value & poll_mask) != 0) { | ||
2283 | break; | ||
2284 | } else { | ||
2285 | msleep(1); | ||
2286 | if (--poll_wait == 0) { | ||
2287 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_1\n", | ||
2288 | __func__); | ||
2289 | rval = QLA_ERROR; | ||
2290 | goto exit_process_pollrdmwr; | ||
2291 | } | ||
2292 | } | ||
2293 | } | ||
2294 | |||
2295 | ha->isp_ops->rd_reg_indirect(ha, addr_2, &data); | ||
2296 | data &= le32_to_cpu(poll_hdr->modify_mask); | ||
2297 | ha->isp_ops->wr_reg_indirect(ha, addr_2, data); | ||
2298 | ha->isp_ops->wr_reg_indirect(ha, addr_1, value_2); | ||
2299 | |||
2300 | poll_wait = le32_to_cpu(poll_hdr->poll_wait); | ||
2301 | while (1) { | ||
2302 | ha->isp_ops->rd_reg_indirect(ha, addr_1, &r_value); | ||
2303 | |||
2304 | if ((r_value & poll_mask) != 0) { | ||
2305 | break; | ||
2306 | } else { | ||
2307 | msleep(1); | ||
2308 | if (--poll_wait == 0) { | ||
2309 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT_2\n", | ||
2310 | __func__); | ||
2311 | rval = QLA_ERROR; | ||
2312 | goto exit_process_pollrdmwr; | ||
2313 | } | ||
2314 | } | ||
2315 | } | ||
2316 | |||
2317 | *data_ptr++ = cpu_to_le32(addr_2); | ||
2318 | *data_ptr++ = cpu_to_le32(data); | ||
2319 | *d_ptr = data_ptr; | ||
2320 | |||
2321 | exit_process_pollrdmwr: | ||
2322 | return rval; | ||
2323 | } | ||
2324 | |||
2325 | static uint32_t qla4_83xx_minidump_process_rdrom(struct scsi_qla_host *ha, | ||
2326 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2327 | uint32_t **d_ptr) | ||
2328 | { | ||
2329 | uint32_t fl_addr, u32_count, rval; | ||
2330 | struct qla8xxx_minidump_entry_rdrom *rom_hdr; | ||
2331 | uint32_t *data_ptr = *d_ptr; | ||
2332 | |||
2333 | rom_hdr = (struct qla8xxx_minidump_entry_rdrom *)entry_hdr; | ||
2334 | fl_addr = le32_to_cpu(rom_hdr->read_addr); | ||
2335 | u32_count = le32_to_cpu(rom_hdr->read_data_size)/sizeof(uint32_t); | ||
2336 | |||
2337 | DEBUG2(ql4_printk(KERN_INFO, ha, "[%s]: fl_addr: 0x%x, count: 0x%x\n", | ||
2338 | __func__, fl_addr, u32_count)); | ||
2339 | |||
2340 | rval = qla4_83xx_lockless_flash_read_u32(ha, fl_addr, | ||
2341 | (u8 *)(data_ptr), u32_count); | ||
2342 | |||
2343 | if (rval == QLA_ERROR) { | ||
2344 | ql4_printk(KERN_ERR, ha, "%s: Flash Read Error,Count=%d\n", | ||
2345 | __func__, u32_count); | ||
2346 | goto exit_process_rdrom; | ||
2347 | } | ||
2348 | |||
2349 | data_ptr += u32_count; | ||
2350 | *d_ptr = data_ptr; | ||
2351 | |||
2352 | exit_process_rdrom: | ||
2353 | return rval; | ||
2354 | } | ||
2355 | |||
2107 | /** | 2356 | /** |
2108 | * qla4_8xxx_collect_md_data - Retrieve firmware minidump data. | 2357 | * qla4_8xxx_collect_md_data - Retrieve firmware minidump data. |
2109 | * @ha: pointer to adapter structure | 2358 | * @ha: pointer to adapter structure |
@@ -2151,6 +2400,10 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | |||
2151 | (((uint8_t *)ha->fw_dump_tmplt_hdr) + | 2400 | (((uint8_t *)ha->fw_dump_tmplt_hdr) + |
2152 | tmplt_hdr->first_entry_offset); | 2401 | tmplt_hdr->first_entry_offset); |
2153 | 2402 | ||
2403 | if (is_qla8032(ha)) | ||
2404 | tmplt_hdr->saved_state_array[QLA83XX_SS_OCM_WNDREG_INDEX] = | ||
2405 | tmplt_hdr->ocm_window_reg[ha->func_num]; | ||
2406 | |||
2154 | /* Walk through the entry headers - validate/perform required action */ | 2407 | /* Walk through the entry headers - validate/perform required action */ |
2155 | for (i = 0; i < num_entry_hdr; i++) { | 2408 | for (i = 0; i < num_entry_hdr; i++) { |
2156 | if (data_collected >= ha->fw_dump_size) { | 2409 | if (data_collected >= ha->fw_dump_size) { |
@@ -2201,8 +2454,18 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | |||
2201 | break; | 2454 | break; |
2202 | case QLA8XXX_BOARD: | 2455 | case QLA8XXX_BOARD: |
2203 | case QLA8XXX_RDROM: | 2456 | case QLA8XXX_RDROM: |
2204 | qla4_82xx_minidump_process_rdrom(ha, entry_hdr, | 2457 | if (is_qla8022(ha)) { |
2205 | &data_ptr); | 2458 | qla4_82xx_minidump_process_rdrom(ha, entry_hdr, |
2459 | &data_ptr); | ||
2460 | } else if (is_qla8032(ha)) { | ||
2461 | rval = qla4_83xx_minidump_process_rdrom(ha, | ||
2462 | entry_hdr, | ||
2463 | &data_ptr); | ||
2464 | if (rval != QLA_SUCCESS) | ||
2465 | qla4_8xxx_mark_entry_skipped(ha, | ||
2466 | entry_hdr, | ||
2467 | i); | ||
2468 | } | ||
2206 | break; | 2469 | break; |
2207 | case QLA8XXX_L2DTG: | 2470 | case QLA8XXX_L2DTG: |
2208 | case QLA8XXX_L2ITG: | 2471 | case QLA8XXX_L2ITG: |
@@ -2215,6 +2478,8 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | |||
2215 | goto md_failed; | 2478 | goto md_failed; |
2216 | } | 2479 | } |
2217 | break; | 2480 | break; |
2481 | case QLA8XXX_L1DTG: | ||
2482 | case QLA8XXX_L1ITG: | ||
2218 | case QLA8XXX_L1DAT: | 2483 | case QLA8XXX_L1DAT: |
2219 | case QLA8XXX_L1INS: | 2484 | case QLA8XXX_L1INS: |
2220 | qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, | 2485 | qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, |
@@ -2232,6 +2497,34 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | |||
2232 | qla4_8xxx_minidump_process_queue(ha, entry_hdr, | 2497 | qla4_8xxx_minidump_process_queue(ha, entry_hdr, |
2233 | &data_ptr); | 2498 | &data_ptr); |
2234 | break; | 2499 | break; |
2500 | case QLA83XX_POLLRD: | ||
2501 | if (!is_qla8032(ha)) { | ||
2502 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2503 | break; | ||
2504 | } | ||
2505 | rval = qla83xx_minidump_process_pollrd(ha, entry_hdr, | ||
2506 | &data_ptr); | ||
2507 | if (rval != QLA_SUCCESS) | ||
2508 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2509 | break; | ||
2510 | case QLA83XX_RDMUX2: | ||
2511 | if (!is_qla8032(ha)) { | ||
2512 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2513 | break; | ||
2514 | } | ||
2515 | qla83xx_minidump_process_rdmux2(ha, entry_hdr, | ||
2516 | &data_ptr); | ||
2517 | break; | ||
2518 | case QLA83XX_POLLRDMWR: | ||
2519 | if (!is_qla8032(ha)) { | ||
2520 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2521 | break; | ||
2522 | } | ||
2523 | rval = qla83xx_minidump_process_pollrdmwr(ha, entry_hdr, | ||
2524 | &data_ptr); | ||
2525 | if (rval != QLA_SUCCESS) | ||
2526 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2527 | break; | ||
2235 | case QLA8XXX_RDNOP: | 2528 | case QLA8XXX_RDNOP: |
2236 | default: | 2529 | default: |
2237 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | 2530 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); |
@@ -2283,7 +2576,7 @@ static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) | |||
2283 | kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); | 2576 | kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); |
2284 | } | 2577 | } |
2285 | 2578 | ||
2286 | static void qla4_8xxx_get_minidump(struct scsi_qla_host *ha) | 2579 | void qla4_8xxx_get_minidump(struct scsi_qla_host *ha) |
2287 | { | 2580 | { |
2288 | if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && | 2581 | if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && |
2289 | !test_bit(AF_82XX_FW_DUMPED, &ha->flags)) { | 2582 | !test_bit(AF_82XX_FW_DUMPED, &ha->flags)) { |
@@ -2303,12 +2596,11 @@ static void qla4_8xxx_get_minidump(struct scsi_qla_host *ha) | |||
2303 | * | 2596 | * |
2304 | * Note: IDC lock must be held upon entry | 2597 | * Note: IDC lock must be held upon entry |
2305 | **/ | 2598 | **/ |
2306 | static int | 2599 | int qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) |
2307 | qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) | ||
2308 | { | 2600 | { |
2309 | int rval = QLA_ERROR; | 2601 | int rval = QLA_ERROR; |
2310 | int i, timeout; | 2602 | int i, timeout; |
2311 | uint32_t old_count, count; | 2603 | uint32_t old_count, count, idc_ctrl; |
2312 | int need_reset = 0, peg_stuck = 1; | 2604 | int need_reset = 0, peg_stuck = 1; |
2313 | 2605 | ||
2314 | need_reset = ha->isp_ops->need_reset(ha); | 2606 | need_reset = ha->isp_ops->need_reset(ha); |
@@ -2351,8 +2643,24 @@ dev_initialize: | |||
2351 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, | 2643 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, |
2352 | QLA8XXX_DEV_INITIALIZING); | 2644 | QLA8XXX_DEV_INITIALIZING); |
2353 | 2645 | ||
2646 | /* | ||
2647 | * For ISP8324, if IDC_CTRL GRACEFUL_RESET_BIT1 is set, reset it after | ||
2648 | * device goes to INIT state. | ||
2649 | */ | ||
2650 | if (is_qla8032(ha)) { | ||
2651 | idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL); | ||
2652 | if (idc_ctrl & GRACEFUL_RESET_BIT1) { | ||
2653 | qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL, | ||
2654 | (idc_ctrl & ~GRACEFUL_RESET_BIT1)); | ||
2655 | set_bit(AF_83XX_NO_FW_DUMP, &ha->flags); | ||
2656 | } | ||
2657 | } | ||
2658 | |||
2354 | ha->isp_ops->idc_unlock(ha); | 2659 | ha->isp_ops->idc_unlock(ha); |
2355 | qla4_8xxx_get_minidump(ha); | 2660 | |
2661 | if (is_qla8022(ha)) | ||
2662 | qla4_8xxx_get_minidump(ha); | ||
2663 | |||
2356 | rval = ha->isp_ops->restart_firmware(ha); | 2664 | rval = ha->isp_ops->restart_firmware(ha); |
2357 | ha->isp_ops->idc_lock(ha); | 2665 | ha->isp_ops->idc_lock(ha); |
2358 | 2666 | ||
@@ -2487,14 +2795,77 @@ static void qla4_82xx_set_idc_ver(struct scsi_qla_host *ha) | |||
2487 | } | 2795 | } |
2488 | } | 2796 | } |
2489 | 2797 | ||
2490 | static void qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha) | 2798 | static int qla4_83xx_set_idc_ver(struct scsi_qla_host *ha) |
2491 | { | 2799 | { |
2492 | if (!test_bit(AF_INIT_DONE, &ha->flags)) { | 2800 | int idc_ver; |
2493 | ha->isp_ops->idc_lock(ha); | 2801 | uint32_t drv_active; |
2494 | qla4_8xxx_set_drv_active(ha); | 2802 | int rval = QLA_SUCCESS; |
2803 | |||
2804 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); | ||
2805 | if (drv_active == (1 << ha->func_num)) { | ||
2806 | idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION); | ||
2807 | idc_ver &= (~0xFF); | ||
2808 | idc_ver |= QLA83XX_IDC_VER_MAJ_VALUE; | ||
2809 | qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION, idc_ver); | ||
2810 | ql4_printk(KERN_INFO, ha, | ||
2811 | "%s: IDC version updated to %d\n", __func__, | ||
2812 | QLA83XX_IDC_VER_MAJ_VALUE); | ||
2813 | } else { | ||
2814 | idc_ver = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_IDC_VERSION); | ||
2815 | idc_ver &= 0xFF; | ||
2816 | if (QLA83XX_IDC_VER_MAJ_VALUE != idc_ver) { | ||
2817 | ql4_printk(KERN_INFO, ha, | ||
2818 | "%s: qla4xxx driver IDC version %d is not compatible with IDC version %d of other drivers!\n", | ||
2819 | __func__, QLA83XX_IDC_VER_MAJ_VALUE, | ||
2820 | idc_ver); | ||
2821 | rval = QLA_ERROR; | ||
2822 | goto exit_set_idc_ver; | ||
2823 | } | ||
2824 | } | ||
2825 | |||
2826 | /* Update IDC_MINOR_VERSION */ | ||
2827 | idc_ver = qla4_83xx_rd_reg(ha, QLA83XX_CRB_IDC_VER_MINOR); | ||
2828 | idc_ver &= ~(0x03 << (ha->func_num * 2)); | ||
2829 | idc_ver |= (QLA83XX_IDC_VER_MIN_VALUE << (ha->func_num * 2)); | ||
2830 | qla4_83xx_wr_reg(ha, QLA83XX_CRB_IDC_VER_MINOR, idc_ver); | ||
2831 | |||
2832 | exit_set_idc_ver: | ||
2833 | return rval; | ||
2834 | } | ||
2835 | |||
2836 | static int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha) | ||
2837 | { | ||
2838 | uint32_t drv_active; | ||
2839 | int rval = QLA_SUCCESS; | ||
2840 | |||
2841 | if (test_bit(AF_INIT_DONE, &ha->flags)) | ||
2842 | goto exit_update_idc_reg; | ||
2843 | |||
2844 | ha->isp_ops->idc_lock(ha); | ||
2845 | qla4_8xxx_set_drv_active(ha); | ||
2846 | |||
2847 | /* | ||
2848 | * If we are the first driver to load and | ||
2849 | * ql4xdontresethba is not set, clear IDC_CTRL BIT0. | ||
2850 | */ | ||
2851 | if (is_qla8032(ha)) { | ||
2852 | drv_active = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DRV_ACTIVE); | ||
2853 | if ((drv_active == (1 << ha->func_num)) && !ql4xdontresethba) | ||
2854 | qla4_83xx_clear_idc_dontreset(ha); | ||
2855 | } | ||
2856 | |||
2857 | if (is_qla8022(ha)) { | ||
2495 | qla4_82xx_set_idc_ver(ha); | 2858 | qla4_82xx_set_idc_ver(ha); |
2496 | ha->isp_ops->idc_unlock(ha); | 2859 | } else if (is_qla8032(ha)) { |
2860 | rval = qla4_83xx_set_idc_ver(ha); | ||
2861 | if (rval == QLA_ERROR) | ||
2862 | qla4_8xxx_clear_drv_active(ha); | ||
2497 | } | 2863 | } |
2864 | |||
2865 | ha->isp_ops->idc_unlock(ha); | ||
2866 | |||
2867 | exit_update_idc_reg: | ||
2868 | return rval; | ||
2498 | } | 2869 | } |
2499 | 2870 | ||
2500 | /** | 2871 | /** |
@@ -2509,7 +2880,9 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
2509 | int rval = QLA_SUCCESS; | 2880 | int rval = QLA_SUCCESS; |
2510 | unsigned long dev_init_timeout; | 2881 | unsigned long dev_init_timeout; |
2511 | 2882 | ||
2512 | qla4_8xxx_update_idc_reg(ha); | 2883 | rval = qla4_8xxx_update_idc_reg(ha); |
2884 | if (rval == QLA_ERROR) | ||
2885 | goto exit_state_handler; | ||
2513 | 2886 | ||
2514 | dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); | 2887 | dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); |
2515 | DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", | 2888 | DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", |
@@ -2550,16 +2923,25 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
2550 | ha->isp_ops->idc_lock(ha); | 2923 | ha->isp_ops->idc_lock(ha); |
2551 | break; | 2924 | break; |
2552 | case QLA8XXX_DEV_NEED_RESET: | 2925 | case QLA8XXX_DEV_NEED_RESET: |
2553 | if (!ql4xdontresethba) { | 2926 | /* |
2554 | qla4_82xx_need_reset_handler(ha); | 2927 | * For ISP8324, if NEED_RESET is set by any driver, |
2555 | /* Update timeout value after need | 2928 | * it should be honored, irrespective of IDC_CTRL |
2556 | * reset handler */ | 2929 | * DONTRESET_BIT0 |
2557 | dev_init_timeout = jiffies + | 2930 | */ |
2558 | (ha->nx_dev_init_timeout * HZ); | 2931 | if (is_qla8032(ha)) { |
2559 | } else { | 2932 | qla4_83xx_need_reset_handler(ha); |
2560 | ha->isp_ops->idc_unlock(ha); | 2933 | } else if (is_qla8022(ha)) { |
2561 | msleep(1000); | 2934 | if (!ql4xdontresethba) { |
2562 | ha->isp_ops->idc_lock(ha); | 2935 | qla4_82xx_need_reset_handler(ha); |
2936 | /* Update timeout value after need | ||
2937 | * reset handler */ | ||
2938 | dev_init_timeout = jiffies + | ||
2939 | (ha->nx_dev_init_timeout * HZ); | ||
2940 | } else { | ||
2941 | ha->isp_ops->idc_unlock(ha); | ||
2942 | msleep(1000); | ||
2943 | ha->isp_ops->idc_lock(ha); | ||
2944 | } | ||
2563 | } | 2945 | } |
2564 | break; | 2946 | break; |
2565 | case QLA8XXX_DEV_NEED_QUIESCENT: | 2947 | case QLA8XXX_DEV_NEED_QUIESCENT: |
@@ -2587,6 +2969,7 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
2587 | } | 2969 | } |
2588 | exit: | 2970 | exit: |
2589 | ha->isp_ops->idc_unlock(ha); | 2971 | ha->isp_ops->idc_unlock(ha); |
2972 | exit_state_handler: | ||
2590 | return rval; | 2973 | return rval; |
2591 | } | 2974 | } |
2592 | 2975 | ||
@@ -2595,8 +2978,13 @@ int qla4_8xxx_load_risc(struct scsi_qla_host *ha) | |||
2595 | int retval; | 2978 | int retval; |
2596 | 2979 | ||
2597 | /* clear the interrupt */ | 2980 | /* clear the interrupt */ |
2598 | writel(0, &ha->qla4_82xx_reg->host_int); | 2981 | if (is_qla8032(ha)) { |
2599 | readl(&ha->qla4_82xx_reg->host_int); | 2982 | writel(0, &ha->qla4_83xx_reg->risc_intr); |
2983 | readl(&ha->qla4_83xx_reg->risc_intr); | ||
2984 | } else if (is_qla8022(ha)) { | ||
2985 | writel(0, &ha->qla4_82xx_reg->host_int); | ||
2986 | readl(&ha->qla4_82xx_reg->host_int); | ||
2987 | } | ||
2600 | 2988 | ||
2601 | retval = qla4_8xxx_device_state_handler(ha); | 2989 | retval = qla4_8xxx_device_state_handler(ha); |
2602 | 2990 | ||
@@ -2695,7 +3083,7 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) | |||
2695 | const char *loc, *locations[] = { "DEF", "FLT" }; | 3083 | const char *loc, *locations[] = { "DEF", "FLT" }; |
2696 | uint16_t *wptr; | 3084 | uint16_t *wptr; |
2697 | uint16_t cnt, chksum; | 3085 | uint16_t cnt, chksum; |
2698 | uint32_t start; | 3086 | uint32_t start, status; |
2699 | struct qla_flt_header *flt; | 3087 | struct qla_flt_header *flt; |
2700 | struct qla_flt_region *region; | 3088 | struct qla_flt_region *region; |
2701 | struct ql82xx_hw_data *hw = &ha->hw; | 3089 | struct ql82xx_hw_data *hw = &ha->hw; |
@@ -2704,8 +3092,18 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) | |||
2704 | wptr = (uint16_t *)ha->request_ring; | 3092 | wptr = (uint16_t *)ha->request_ring; |
2705 | flt = (struct qla_flt_header *)ha->request_ring; | 3093 | flt = (struct qla_flt_header *)ha->request_ring; |
2706 | region = (struct qla_flt_region *)&flt[1]; | 3094 | region = (struct qla_flt_region *)&flt[1]; |
2707 | qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring, | 3095 | |
2708 | flt_addr << 2, OPTROM_BURST_SIZE); | 3096 | if (is_qla8022(ha)) { |
3097 | qla4_82xx_read_optrom_data(ha, (uint8_t *)ha->request_ring, | ||
3098 | flt_addr << 2, OPTROM_BURST_SIZE); | ||
3099 | } else if (is_qla8032(ha)) { | ||
3100 | status = qla4_83xx_flash_read_u32(ha, flt_addr << 2, | ||
3101 | (uint8_t *)ha->request_ring, | ||
3102 | 0x400); | ||
3103 | if (status != QLA_SUCCESS) | ||
3104 | goto no_flash_data; | ||
3105 | } | ||
3106 | |||
2709 | if (*wptr == __constant_cpu_to_le16(0xffff)) | 3107 | if (*wptr == __constant_cpu_to_le16(0xffff)) |
2710 | goto no_flash_data; | 3108 | goto no_flash_data; |
2711 | if (flt->version != __constant_cpu_to_le16(1)) { | 3109 | if (flt->version != __constant_cpu_to_le16(1)) { |
@@ -2918,8 +3316,12 @@ qla4_8xxx_get_flash_info(struct scsi_qla_host *ha) | |||
2918 | return ret; | 3316 | return ret; |
2919 | 3317 | ||
2920 | qla4_8xxx_get_flt_info(ha, flt_addr); | 3318 | qla4_8xxx_get_flt_info(ha, flt_addr); |
2921 | qla4_82xx_get_fdt_info(ha); | 3319 | if (is_qla8022(ha)) { |
2922 | qla4_82xx_get_idc_param(ha); | 3320 | qla4_82xx_get_fdt_info(ha); |
3321 | qla4_82xx_get_idc_param(ha); | ||
3322 | } else if (is_qla8032(ha)) { | ||
3323 | qla4_83xx_get_idc_param(ha); | ||
3324 | } | ||
2923 | 3325 | ||
2924 | return QLA_SUCCESS; | 3326 | return QLA_SUCCESS; |
2925 | } | 3327 | } |
@@ -3063,8 +3465,7 @@ exit_validate_mac82: | |||
3063 | 3465 | ||
3064 | /* Interrupt handling helpers. */ | 3466 | /* Interrupt handling helpers. */ |
3065 | 3467 | ||
3066 | static int | 3468 | int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) |
3067 | qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) | ||
3068 | { | 3469 | { |
3069 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 3470 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
3070 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 3471 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
@@ -3085,8 +3486,7 @@ qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha) | |||
3085 | return QLA_SUCCESS; | 3486 | return QLA_SUCCESS; |
3086 | } | 3487 | } |
3087 | 3488 | ||
3088 | static int | 3489 | int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha) |
3089 | qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha) | ||
3090 | { | 3490 | { |
3091 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 3491 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
3092 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 3492 | uint32_t mbox_sts[MBOX_REG_COUNT]; |