diff options
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.h | 44 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 335 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.h | 3 |
3 files changed, 382 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h index a0de6e25ea5a..775fdf9fcc87 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.h +++ b/drivers/scsi/qla4xxx/ql4_83xx.h | |||
@@ -254,6 +254,50 @@ struct qla83xx_minidump_entry_pollrd { | |||
254 | uint32_t rsvd_1; | 254 | uint32_t rsvd_1; |
255 | }; | 255 | }; |
256 | 256 | ||
257 | struct qla8044_minidump_entry_rddfe { | ||
258 | struct qla8xxx_minidump_entry_hdr h; | ||
259 | uint32_t addr_1; | ||
260 | uint32_t value; | ||
261 | uint8_t stride; | ||
262 | uint8_t stride2; | ||
263 | uint16_t count; | ||
264 | uint32_t poll; | ||
265 | uint32_t mask; | ||
266 | uint32_t modify_mask; | ||
267 | uint32_t data_size; | ||
268 | uint32_t rsvd; | ||
269 | |||
270 | } __packed; | ||
271 | |||
272 | struct qla8044_minidump_entry_rdmdio { | ||
273 | struct qla8xxx_minidump_entry_hdr h; | ||
274 | |||
275 | uint32_t addr_1; | ||
276 | uint32_t addr_2; | ||
277 | uint32_t value_1; | ||
278 | uint8_t stride_1; | ||
279 | uint8_t stride_2; | ||
280 | uint16_t count; | ||
281 | uint32_t poll; | ||
282 | uint32_t mask; | ||
283 | uint32_t value_2; | ||
284 | uint32_t data_size; | ||
285 | |||
286 | } __packed; | ||
287 | |||
288 | struct qla8044_minidump_entry_pollwr { | ||
289 | struct qla8xxx_minidump_entry_hdr h; | ||
290 | uint32_t addr_1; | ||
291 | uint32_t addr_2; | ||
292 | uint32_t value_1; | ||
293 | uint32_t value_2; | ||
294 | uint32_t poll; | ||
295 | uint32_t mask; | ||
296 | uint32_t data_size; | ||
297 | uint32_t rsvd; | ||
298 | |||
299 | } __packed; | ||
300 | |||
257 | /* RDMUX2 Entry */ | 301 | /* RDMUX2 Entry */ |
258 | struct qla83xx_minidump_entry_rdmux2 { | 302 | struct qla83xx_minidump_entry_rdmux2 { |
259 | struct qla8xxx_minidump_entry_hdr h; | 303 | struct qla8xxx_minidump_entry_hdr h; |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 63328c812b70..bdc3b9563688 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm-generic/io-64-nonatomic-lo-hi.h> | 15 | #include <asm-generic/io-64-nonatomic-lo-hi.h> |
16 | 16 | ||
17 | #define TIMEOUT_100_MS 100 | ||
17 | #define MASK(n) DMA_BIT_MASK(n) | 18 | #define MASK(n) DMA_BIT_MASK(n) |
18 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) | 19 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) |
19 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) | 20 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) |
@@ -1714,6 +1715,101 @@ void qla4_82xx_rom_lock_recovery(struct scsi_qla_host *ha) | |||
1714 | qla4_82xx_rom_unlock(ha); | 1715 | qla4_82xx_rom_unlock(ha); |
1715 | } | 1716 | } |
1716 | 1717 | ||
1718 | static uint32_t ql4_84xx_poll_wait_for_ready(struct scsi_qla_host *ha, | ||
1719 | uint32_t addr1, uint32_t mask) | ||
1720 | { | ||
1721 | unsigned long timeout; | ||
1722 | uint32_t rval = QLA_SUCCESS; | ||
1723 | uint32_t temp; | ||
1724 | |||
1725 | timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS); | ||
1726 | do { | ||
1727 | ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); | ||
1728 | if ((temp & mask) != 0) | ||
1729 | break; | ||
1730 | |||
1731 | if (time_after_eq(jiffies, timeout)) { | ||
1732 | ql4_printk(KERN_INFO, ha, "Error in processing rdmdio entry\n"); | ||
1733 | return QLA_ERROR; | ||
1734 | } | ||
1735 | } while (1); | ||
1736 | |||
1737 | return rval; | ||
1738 | } | ||
1739 | |||
1740 | uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1, | ||
1741 | uint32_t addr3, uint32_t mask, uint32_t addr, | ||
1742 | uint32_t *data_ptr) | ||
1743 | { | ||
1744 | int rval = QLA_SUCCESS; | ||
1745 | uint32_t temp; | ||
1746 | uint32_t data; | ||
1747 | |||
1748 | rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); | ||
1749 | if (rval) | ||
1750 | goto exit_ipmdio_rd_reg; | ||
1751 | |||
1752 | temp = (0x40000000 | addr); | ||
1753 | ha->isp_ops->wr_reg_indirect(ha, addr1, temp); | ||
1754 | |||
1755 | rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); | ||
1756 | if (rval) | ||
1757 | goto exit_ipmdio_rd_reg; | ||
1758 | |||
1759 | ha->isp_ops->rd_reg_indirect(ha, addr3, &data); | ||
1760 | *data_ptr = data; | ||
1761 | |||
1762 | exit_ipmdio_rd_reg: | ||
1763 | return rval; | ||
1764 | } | ||
1765 | |||
1766 | |||
1767 | static uint32_t ql4_84xx_poll_wait_ipmdio_bus_idle(struct scsi_qla_host *ha, | ||
1768 | uint32_t addr1, | ||
1769 | uint32_t addr2, | ||
1770 | uint32_t addr3, | ||
1771 | uint32_t mask) | ||
1772 | { | ||
1773 | unsigned long timeout; | ||
1774 | uint32_t temp; | ||
1775 | uint32_t rval = QLA_SUCCESS; | ||
1776 | |||
1777 | timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS); | ||
1778 | do { | ||
1779 | ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3, mask, addr2, &temp); | ||
1780 | if ((temp & 0x1) != 1) | ||
1781 | break; | ||
1782 | if (time_after_eq(jiffies, timeout)) { | ||
1783 | ql4_printk(KERN_INFO, ha, "Error in processing mdiobus idle\n"); | ||
1784 | return QLA_ERROR; | ||
1785 | } | ||
1786 | } while (1); | ||
1787 | |||
1788 | return rval; | ||
1789 | } | ||
1790 | |||
1791 | static int ql4_84xx_ipmdio_wr_reg(struct scsi_qla_host *ha, | ||
1792 | uint32_t addr1, uint32_t addr3, | ||
1793 | uint32_t mask, uint32_t addr, | ||
1794 | uint32_t value) | ||
1795 | { | ||
1796 | int rval = QLA_SUCCESS; | ||
1797 | |||
1798 | rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); | ||
1799 | if (rval) | ||
1800 | goto exit_ipmdio_wr_reg; | ||
1801 | |||
1802 | ha->isp_ops->wr_reg_indirect(ha, addr3, value); | ||
1803 | ha->isp_ops->wr_reg_indirect(ha, addr1, addr); | ||
1804 | |||
1805 | rval = ql4_84xx_poll_wait_for_ready(ha, addr1, mask); | ||
1806 | if (rval) | ||
1807 | goto exit_ipmdio_wr_reg; | ||
1808 | |||
1809 | exit_ipmdio_wr_reg: | ||
1810 | return rval; | ||
1811 | } | ||
1812 | |||
1717 | static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, | 1813 | static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, |
1718 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | 1814 | struct qla8xxx_minidump_entry_hdr *entry_hdr, |
1719 | uint32_t **d_ptr) | 1815 | uint32_t **d_ptr) |
@@ -2440,6 +2536,227 @@ exit_process_pollrd: | |||
2440 | return rval; | 2536 | return rval; |
2441 | } | 2537 | } |
2442 | 2538 | ||
2539 | static uint32_t qla4_84xx_minidump_process_rddfe(struct scsi_qla_host *ha, | ||
2540 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2541 | uint32_t **d_ptr) | ||
2542 | { | ||
2543 | int loop_cnt; | ||
2544 | uint32_t addr1, addr2, value, data, temp, wrval; | ||
2545 | uint8_t stride, stride2; | ||
2546 | uint16_t count; | ||
2547 | uint32_t poll, mask, data_size, modify_mask; | ||
2548 | uint32_t wait_count = 0; | ||
2549 | uint32_t *data_ptr = *d_ptr; | ||
2550 | struct qla8044_minidump_entry_rddfe *rddfe; | ||
2551 | uint32_t rval = QLA_SUCCESS; | ||
2552 | |||
2553 | rddfe = (struct qla8044_minidump_entry_rddfe *)entry_hdr; | ||
2554 | addr1 = le32_to_cpu(rddfe->addr_1); | ||
2555 | value = le32_to_cpu(rddfe->value); | ||
2556 | stride = le32_to_cpu(rddfe->stride); | ||
2557 | stride2 = le32_to_cpu(rddfe->stride2); | ||
2558 | count = le32_to_cpu(rddfe->count); | ||
2559 | |||
2560 | poll = le32_to_cpu(rddfe->poll); | ||
2561 | mask = le32_to_cpu(rddfe->mask); | ||
2562 | modify_mask = le32_to_cpu(rddfe->modify_mask); | ||
2563 | data_size = le32_to_cpu(rddfe->data_size); | ||
2564 | |||
2565 | addr2 = addr1 + stride; | ||
2566 | |||
2567 | for (loop_cnt = 0x0; loop_cnt < count; loop_cnt++) { | ||
2568 | ha->isp_ops->wr_reg_indirect(ha, addr1, (0x40000000 | value)); | ||
2569 | |||
2570 | wait_count = 0; | ||
2571 | while (wait_count < poll) { | ||
2572 | ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); | ||
2573 | if ((temp & mask) != 0) | ||
2574 | break; | ||
2575 | wait_count++; | ||
2576 | } | ||
2577 | |||
2578 | if (wait_count == poll) { | ||
2579 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__); | ||
2580 | rval = QLA_ERROR; | ||
2581 | goto exit_process_rddfe; | ||
2582 | } else { | ||
2583 | ha->isp_ops->rd_reg_indirect(ha, addr2, &temp); | ||
2584 | temp = temp & modify_mask; | ||
2585 | temp = (temp | ((loop_cnt << 16) | loop_cnt)); | ||
2586 | wrval = ((temp << 16) | temp); | ||
2587 | |||
2588 | ha->isp_ops->wr_reg_indirect(ha, addr2, wrval); | ||
2589 | ha->isp_ops->wr_reg_indirect(ha, addr1, value); | ||
2590 | |||
2591 | wait_count = 0; | ||
2592 | while (wait_count < poll) { | ||
2593 | ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); | ||
2594 | if ((temp & mask) != 0) | ||
2595 | break; | ||
2596 | wait_count++; | ||
2597 | } | ||
2598 | if (wait_count == poll) { | ||
2599 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", | ||
2600 | __func__); | ||
2601 | rval = QLA_ERROR; | ||
2602 | goto exit_process_rddfe; | ||
2603 | } | ||
2604 | |||
2605 | ha->isp_ops->wr_reg_indirect(ha, addr1, | ||
2606 | ((0x40000000 | value) + | ||
2607 | stride2)); | ||
2608 | wait_count = 0; | ||
2609 | while (wait_count < poll) { | ||
2610 | ha->isp_ops->rd_reg_indirect(ha, addr1, &temp); | ||
2611 | if ((temp & mask) != 0) | ||
2612 | break; | ||
2613 | wait_count++; | ||
2614 | } | ||
2615 | |||
2616 | if (wait_count == poll) { | ||
2617 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", | ||
2618 | __func__); | ||
2619 | rval = QLA_ERROR; | ||
2620 | goto exit_process_rddfe; | ||
2621 | } | ||
2622 | |||
2623 | ha->isp_ops->rd_reg_indirect(ha, addr2, &data); | ||
2624 | |||
2625 | *data_ptr++ = cpu_to_le32(wrval); | ||
2626 | *data_ptr++ = cpu_to_le32(data); | ||
2627 | } | ||
2628 | } | ||
2629 | |||
2630 | *d_ptr = data_ptr; | ||
2631 | exit_process_rddfe: | ||
2632 | return rval; | ||
2633 | } | ||
2634 | |||
2635 | static uint32_t qla4_84xx_minidump_process_rdmdio(struct scsi_qla_host *ha, | ||
2636 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2637 | uint32_t **d_ptr) | ||
2638 | { | ||
2639 | int rval = QLA_SUCCESS; | ||
2640 | uint32_t addr1, addr2, value1, value2, data, selval; | ||
2641 | uint8_t stride1, stride2; | ||
2642 | uint32_t addr3, addr4, addr5, addr6, addr7; | ||
2643 | uint16_t count, loop_cnt; | ||
2644 | uint32_t poll, mask; | ||
2645 | uint32_t *data_ptr = *d_ptr; | ||
2646 | struct qla8044_minidump_entry_rdmdio *rdmdio; | ||
2647 | |||
2648 | rdmdio = (struct qla8044_minidump_entry_rdmdio *)entry_hdr; | ||
2649 | addr1 = le32_to_cpu(rdmdio->addr_1); | ||
2650 | addr2 = le32_to_cpu(rdmdio->addr_2); | ||
2651 | value1 = le32_to_cpu(rdmdio->value_1); | ||
2652 | stride1 = le32_to_cpu(rdmdio->stride_1); | ||
2653 | stride2 = le32_to_cpu(rdmdio->stride_2); | ||
2654 | count = le32_to_cpu(rdmdio->count); | ||
2655 | |||
2656 | poll = le32_to_cpu(rdmdio->poll); | ||
2657 | mask = le32_to_cpu(rdmdio->mask); | ||
2658 | value2 = le32_to_cpu(rdmdio->value_2); | ||
2659 | |||
2660 | addr3 = addr1 + stride1; | ||
2661 | |||
2662 | for (loop_cnt = 0; loop_cnt < count; loop_cnt++) { | ||
2663 | rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2, | ||
2664 | addr3, mask); | ||
2665 | if (rval) | ||
2666 | goto exit_process_rdmdio; | ||
2667 | |||
2668 | addr4 = addr2 - stride1; | ||
2669 | rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr4, | ||
2670 | value2); | ||
2671 | if (rval) | ||
2672 | goto exit_process_rdmdio; | ||
2673 | |||
2674 | addr5 = addr2 - (2 * stride1); | ||
2675 | rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, addr5, | ||
2676 | value1); | ||
2677 | if (rval) | ||
2678 | goto exit_process_rdmdio; | ||
2679 | |||
2680 | addr6 = addr2 - (3 * stride1); | ||
2681 | rval = ql4_84xx_ipmdio_wr_reg(ha, addr1, addr3, mask, | ||
2682 | addr6, 0x2); | ||
2683 | if (rval) | ||
2684 | goto exit_process_rdmdio; | ||
2685 | |||
2686 | rval = ql4_84xx_poll_wait_ipmdio_bus_idle(ha, addr1, addr2, | ||
2687 | addr3, mask); | ||
2688 | if (rval) | ||
2689 | goto exit_process_rdmdio; | ||
2690 | |||
2691 | addr7 = addr2 - (4 * stride1); | ||
2692 | rval = ql4_84xx_ipmdio_rd_reg(ha, addr1, addr3, | ||
2693 | mask, addr7, &data); | ||
2694 | if (rval) | ||
2695 | goto exit_process_rdmdio; | ||
2696 | |||
2697 | selval = (value2 << 18) | (value1 << 2) | 2; | ||
2698 | |||
2699 | stride2 = le32_to_cpu(rdmdio->stride_2); | ||
2700 | *data_ptr++ = cpu_to_le32(selval); | ||
2701 | *data_ptr++ = cpu_to_le32(data); | ||
2702 | |||
2703 | value1 = value1 + stride2; | ||
2704 | *d_ptr = data_ptr; | ||
2705 | } | ||
2706 | |||
2707 | exit_process_rdmdio: | ||
2708 | return rval; | ||
2709 | } | ||
2710 | |||
2711 | static uint32_t qla4_84xx_minidump_process_pollwr(struct scsi_qla_host *ha, | ||
2712 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2713 | uint32_t **d_ptr) | ||
2714 | { | ||
2715 | uint32_t addr1, addr2, value1, value2, poll, mask, r_value; | ||
2716 | struct qla8044_minidump_entry_pollwr *pollwr_hdr; | ||
2717 | uint32_t wait_count = 0; | ||
2718 | uint32_t rval = QLA_SUCCESS; | ||
2719 | |||
2720 | pollwr_hdr = (struct qla8044_minidump_entry_pollwr *)entry_hdr; | ||
2721 | addr1 = le32_to_cpu(pollwr_hdr->addr_1); | ||
2722 | addr2 = le32_to_cpu(pollwr_hdr->addr_2); | ||
2723 | value1 = le32_to_cpu(pollwr_hdr->value_1); | ||
2724 | value2 = le32_to_cpu(pollwr_hdr->value_2); | ||
2725 | |||
2726 | poll = le32_to_cpu(pollwr_hdr->poll); | ||
2727 | mask = le32_to_cpu(pollwr_hdr->mask); | ||
2728 | |||
2729 | while (wait_count < poll) { | ||
2730 | ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value); | ||
2731 | |||
2732 | if ((r_value & poll) != 0) | ||
2733 | break; | ||
2734 | |||
2735 | wait_count++; | ||
2736 | } | ||
2737 | |||
2738 | if (wait_count == poll) { | ||
2739 | ql4_printk(KERN_ERR, ha, "%s: TIMEOUT\n", __func__); | ||
2740 | rval = QLA_ERROR; | ||
2741 | goto exit_process_pollwr; | ||
2742 | } | ||
2743 | |||
2744 | ha->isp_ops->wr_reg_indirect(ha, addr2, value2); | ||
2745 | ha->isp_ops->wr_reg_indirect(ha, addr1, value1); | ||
2746 | |||
2747 | wait_count = 0; | ||
2748 | while (wait_count < poll) { | ||
2749 | ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value); | ||
2750 | |||
2751 | if ((r_value & poll) != 0) | ||
2752 | break; | ||
2753 | wait_count++; | ||
2754 | } | ||
2755 | |||
2756 | exit_process_pollwr: | ||
2757 | return rval; | ||
2758 | } | ||
2759 | |||
2443 | static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha, | 2760 | static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha, |
2444 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | 2761 | struct qla8xxx_minidump_entry_hdr *entry_hdr, |
2445 | uint32_t **d_ptr) | 2762 | uint32_t **d_ptr) |
@@ -2753,6 +3070,24 @@ static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | |||
2753 | if (rval != QLA_SUCCESS) | 3070 | if (rval != QLA_SUCCESS) |
2754 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | 3071 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); |
2755 | break; | 3072 | break; |
3073 | case QLA8044_RDDFE: | ||
3074 | rval = qla4_84xx_minidump_process_rddfe(ha, entry_hdr, | ||
3075 | &data_ptr); | ||
3076 | if (rval != QLA_SUCCESS) | ||
3077 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
3078 | break; | ||
3079 | case QLA8044_RDMDIO: | ||
3080 | rval = qla4_84xx_minidump_process_rdmdio(ha, entry_hdr, | ||
3081 | &data_ptr); | ||
3082 | if (rval != QLA_SUCCESS) | ||
3083 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
3084 | break; | ||
3085 | case QLA8044_POLLWR: | ||
3086 | rval = qla4_84xx_minidump_process_pollwr(ha, entry_hdr, | ||
3087 | &data_ptr); | ||
3088 | if (rval != QLA_SUCCESS) | ||
3089 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
3090 | break; | ||
2756 | case QLA8XXX_RDNOP: | 3091 | case QLA8XXX_RDNOP: |
2757 | default: | 3092 | default: |
2758 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | 3093 | qla4_8xxx_mark_entry_skipped(ha, entry_hdr, i); |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h index 14500a0f62cc..337d9fcf6417 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.h +++ b/drivers/scsi/qla4xxx/ql4_nx.h | |||
@@ -858,6 +858,9 @@ struct crb_addr_pair { | |||
858 | #define QLA83XX_POLLRD 35 | 858 | #define QLA83XX_POLLRD 35 |
859 | #define QLA83XX_RDMUX2 36 | 859 | #define QLA83XX_RDMUX2 36 |
860 | #define QLA83XX_POLLRDMWR 37 | 860 | #define QLA83XX_POLLRDMWR 37 |
861 | #define QLA8044_RDDFE 38 | ||
862 | #define QLA8044_RDMDIO 39 | ||
863 | #define QLA8044_POLLWR 40 | ||
861 | #define QLA8XXX_RDROM 71 | 864 | #define QLA8XXX_RDROM 71 |
862 | #define QLA8XXX_RDMEM 72 | 865 | #define QLA8XXX_RDMEM 72 |
863 | #define QLA8XXX_CNTRL 98 | 866 | #define QLA8XXX_CNTRL 98 |