aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/qla4xxx/ql4_83xx.h44
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c335
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.h3
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
257struct 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
272struct 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
288struct 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 */
258struct qla83xx_minidump_entry_rdmux2 { 302struct 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
1718static 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
1740uint32_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
1762exit_ipmdio_rd_reg:
1763 return rval;
1764}
1765
1766
1767static 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
1791static 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
1809exit_ipmdio_wr_reg:
1810 return rval;
1811}
1812
1717static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, 1813static 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
2539static 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;
2631exit_process_rddfe:
2632 return rval;
2633}
2634
2635static 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
2707exit_process_rdmdio:
2708 return rval;
2709}
2710
2711static 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
2756exit_process_pollwr:
2757 return rval;
2758}
2759
2443static void qla83xx_minidump_process_rdmux2(struct scsi_qla_host *ha, 2760static 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