diff options
author | Dmitry Kravkov <dmitry@broadcom.com> | 2013-04-21 23:48:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-22 15:34:40 -0400 |
commit | edb944d27b15c08063fdb62eaae6c377e7865e6d (patch) | |
tree | c74b4d43fb89c320288755d756b8bdb680a19441 | |
parent | f1691dc6159489e8928300cf674fb859f5b5dd12 (diff) |
bnx2x: add additional regions for CRC memory test
a. Common tree of `dir` structures.
b. Multi-port devices structures.
CC: Francious Romieu <romieu@fz.zoreil.com>
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 201 |
2 files changed, 185 insertions, 23 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index c6303428f9e9..87629fdffb0f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -850,6 +850,9 @@ struct bnx2x_common { | |||
850 | #define CHIP_IS_57840_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_VF) | 850 | #define CHIP_IS_57840_VF(bp) (CHIP_NUM(bp) == CHIP_NUM_57840_VF) |
851 | #define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \ | 851 | #define CHIP_IS_E1H(bp) (CHIP_IS_57711(bp) || \ |
852 | CHIP_IS_57711E(bp)) | 852 | CHIP_IS_57711E(bp)) |
853 | #define CHIP_IS_57811xx(bp) (CHIP_IS_57811(bp) || \ | ||
854 | CHIP_IS_57811_MF(bp) || \ | ||
855 | CHIP_IS_57811_VF(bp)) | ||
853 | #define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \ | 856 | #define CHIP_IS_E2(bp) (CHIP_IS_57712(bp) || \ |
854 | CHIP_IS_57712_MF(bp) || \ | 857 | CHIP_IS_57712_MF(bp) || \ |
855 | CHIP_IS_57712_VF(bp)) | 858 | CHIP_IS_57712_VF(bp)) |
@@ -859,9 +862,7 @@ struct bnx2x_common { | |||
859 | CHIP_IS_57810(bp) || \ | 862 | CHIP_IS_57810(bp) || \ |
860 | CHIP_IS_57810_MF(bp) || \ | 863 | CHIP_IS_57810_MF(bp) || \ |
861 | CHIP_IS_57810_VF(bp) || \ | 864 | CHIP_IS_57810_VF(bp) || \ |
862 | CHIP_IS_57811(bp) || \ | 865 | CHIP_IS_57811xx(bp) || \ |
863 | CHIP_IS_57811_MF(bp) || \ | ||
864 | CHIP_IS_57811_VF(bp) || \ | ||
865 | CHIP_IS_57840(bp) || \ | 866 | CHIP_IS_57840(bp) || \ |
866 | CHIP_IS_57840_MF(bp) || \ | 867 | CHIP_IS_57840_MF(bp) || \ |
867 | CHIP_IS_57840_VF(bp)) | 868 | CHIP_IS_57840_VF(bp)) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 8d5c21e98ef4..f07021bcb85e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
@@ -2595,14 +2595,168 @@ static int bnx2x_test_ext_loopback(struct bnx2x *bp) | |||
2595 | return rc; | 2595 | return rc; |
2596 | } | 2596 | } |
2597 | 2597 | ||
2598 | struct code_entry { | ||
2599 | u32 sram_start_addr; | ||
2600 | u32 code_attribute; | ||
2601 | #define CODE_IMAGE_TYPE_MASK 0xf0800003 | ||
2602 | #define CODE_IMAGE_VNTAG_PROFILES_DATA 0xd0000003 | ||
2603 | #define CODE_IMAGE_LENGTH_MASK 0x007ffffc | ||
2604 | #define CODE_IMAGE_TYPE_EXTENDED_DIR 0xe0000000 | ||
2605 | u32 nvm_start_addr; | ||
2606 | }; | ||
2607 | |||
2608 | #define CODE_ENTRY_MAX 16 | ||
2609 | #define CODE_ENTRY_EXTENDED_DIR_IDX 15 | ||
2610 | #define MAX_IMAGES_IN_EXTENDED_DIR 64 | ||
2611 | #define NVRAM_DIR_OFFSET 0x14 | ||
2612 | |||
2613 | #define EXTENDED_DIR_EXISTS(code) \ | ||
2614 | ((code & CODE_IMAGE_TYPE_MASK) == CODE_IMAGE_TYPE_EXTENDED_DIR && \ | ||
2615 | (code & CODE_IMAGE_LENGTH_MASK) != 0) | ||
2616 | |||
2598 | #define CRC32_RESIDUAL 0xdebb20e3 | 2617 | #define CRC32_RESIDUAL 0xdebb20e3 |
2618 | #define CRC_BUFF_SIZE 256 | ||
2619 | |||
2620 | static int bnx2x_nvram_crc(struct bnx2x *bp, | ||
2621 | int offset, | ||
2622 | int size, | ||
2623 | u8 *buff) | ||
2624 | { | ||
2625 | u32 crc = ~0; | ||
2626 | int rc = 0, done = 0; | ||
2627 | |||
2628 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, | ||
2629 | "NVRAM CRC from 0x%08x to 0x%08x\n", offset, offset + size); | ||
2630 | |||
2631 | while (done < size) { | ||
2632 | int count = min_t(int, size - done, CRC_BUFF_SIZE); | ||
2633 | |||
2634 | rc = bnx2x_nvram_read(bp, offset + done, buff, count); | ||
2635 | |||
2636 | if (rc) | ||
2637 | return rc; | ||
2638 | |||
2639 | crc = crc32_le(crc, buff, count); | ||
2640 | done += count; | ||
2641 | } | ||
2642 | |||
2643 | if (crc != CRC32_RESIDUAL) | ||
2644 | rc = -EINVAL; | ||
2645 | |||
2646 | return rc; | ||
2647 | } | ||
2648 | |||
2649 | static int bnx2x_test_nvram_dir(struct bnx2x *bp, | ||
2650 | struct code_entry *entry, | ||
2651 | u8 *buff) | ||
2652 | { | ||
2653 | size_t size = entry->code_attribute & CODE_IMAGE_LENGTH_MASK; | ||
2654 | u32 type = entry->code_attribute & CODE_IMAGE_TYPE_MASK; | ||
2655 | int rc; | ||
2656 | |||
2657 | /* Zero-length images and AFEX profiles do not have CRC */ | ||
2658 | if (size == 0 || type == CODE_IMAGE_VNTAG_PROFILES_DATA) | ||
2659 | return 0; | ||
2660 | |||
2661 | rc = bnx2x_nvram_crc(bp, entry->nvm_start_addr, size, buff); | ||
2662 | if (rc) | ||
2663 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, | ||
2664 | "image %x has failed crc test (rc %d)\n", type, rc); | ||
2665 | |||
2666 | return rc; | ||
2667 | } | ||
2668 | |||
2669 | static int bnx2x_test_dir_entry(struct bnx2x *bp, u32 addr, u8 *buff) | ||
2670 | { | ||
2671 | int rc; | ||
2672 | struct code_entry entry; | ||
2673 | |||
2674 | rc = bnx2x_nvram_read32(bp, addr, (u32 *)&entry, sizeof(entry)); | ||
2675 | if (rc) | ||
2676 | return rc; | ||
2677 | |||
2678 | return bnx2x_test_nvram_dir(bp, &entry, buff); | ||
2679 | } | ||
2680 | |||
2681 | static int bnx2x_test_nvram_ext_dirs(struct bnx2x *bp, u8 *buff) | ||
2682 | { | ||
2683 | u32 rc, cnt, dir_offset = NVRAM_DIR_OFFSET; | ||
2684 | struct code_entry entry; | ||
2685 | int i; | ||
2686 | |||
2687 | rc = bnx2x_nvram_read32(bp, | ||
2688 | dir_offset + | ||
2689 | sizeof(entry) * CODE_ENTRY_EXTENDED_DIR_IDX, | ||
2690 | (u32 *)&entry, sizeof(entry)); | ||
2691 | if (rc) | ||
2692 | return rc; | ||
2693 | |||
2694 | if (!EXTENDED_DIR_EXISTS(entry.code_attribute)) | ||
2695 | return 0; | ||
2696 | |||
2697 | rc = bnx2x_nvram_read32(bp, entry.nvm_start_addr, | ||
2698 | &cnt, sizeof(u32)); | ||
2699 | if (rc) | ||
2700 | return rc; | ||
2701 | |||
2702 | dir_offset = entry.nvm_start_addr + 8; | ||
2703 | |||
2704 | for (i = 0; i < cnt && i < MAX_IMAGES_IN_EXTENDED_DIR; i++) { | ||
2705 | rc = bnx2x_test_dir_entry(bp, dir_offset + | ||
2706 | sizeof(struct code_entry) * i, | ||
2707 | buff); | ||
2708 | if (rc) | ||
2709 | return rc; | ||
2710 | } | ||
2711 | |||
2712 | return 0; | ||
2713 | } | ||
2714 | |||
2715 | static int bnx2x_test_nvram_dirs(struct bnx2x *bp, u8 *buff) | ||
2716 | { | ||
2717 | u32 rc, dir_offset = NVRAM_DIR_OFFSET; | ||
2718 | int i; | ||
2719 | |||
2720 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "NVRAM DIRS CRC test-set\n"); | ||
2721 | |||
2722 | for (i = 0; i < CODE_ENTRY_EXTENDED_DIR_IDX; i++) { | ||
2723 | rc = bnx2x_test_dir_entry(bp, dir_offset + | ||
2724 | sizeof(struct code_entry) * i, | ||
2725 | buff); | ||
2726 | if (rc) | ||
2727 | return rc; | ||
2728 | } | ||
2729 | |||
2730 | return bnx2x_test_nvram_ext_dirs(bp, buff); | ||
2731 | } | ||
2732 | |||
2733 | struct crc_pair { | ||
2734 | int offset; | ||
2735 | int size; | ||
2736 | }; | ||
2737 | |||
2738 | static int bnx2x_test_nvram_tbl(struct bnx2x *bp, | ||
2739 | const struct crc_pair *nvram_tbl, u8 *buf) | ||
2740 | { | ||
2741 | int i; | ||
2742 | |||
2743 | for (i = 0; nvram_tbl[i].size; i++) { | ||
2744 | int rc = bnx2x_nvram_crc(bp, nvram_tbl[i].offset, | ||
2745 | nvram_tbl[i].size, buf); | ||
2746 | if (rc) { | ||
2747 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, | ||
2748 | "nvram_tbl[%d] has failed crc test (rc %d)\n", | ||
2749 | i, rc); | ||
2750 | return rc; | ||
2751 | } | ||
2752 | } | ||
2753 | |||
2754 | return 0; | ||
2755 | } | ||
2599 | 2756 | ||
2600 | static int bnx2x_test_nvram(struct bnx2x *bp) | 2757 | static int bnx2x_test_nvram(struct bnx2x *bp) |
2601 | { | 2758 | { |
2602 | static const struct { | 2759 | const struct crc_pair nvram_tbl[] = { |
2603 | int offset; | ||
2604 | int size; | ||
2605 | } nvram_tbl[] = { | ||
2606 | { 0, 0x14 }, /* bootstrap */ | 2760 | { 0, 0x14 }, /* bootstrap */ |
2607 | { 0x14, 0xec }, /* dir */ | 2761 | { 0x14, 0xec }, /* dir */ |
2608 | { 0x100, 0x350 }, /* manuf_info */ | 2762 | { 0x100, 0x350 }, /* manuf_info */ |
@@ -2611,14 +2765,20 @@ static int bnx2x_test_nvram(struct bnx2x *bp) | |||
2611 | { 0x708, 0x70 }, /* manuf_key_info */ | 2765 | { 0x708, 0x70 }, /* manuf_key_info */ |
2612 | { 0, 0 } | 2766 | { 0, 0 } |
2613 | }; | 2767 | }; |
2768 | const struct crc_pair nvram_tbl2[] = { | ||
2769 | { 0x7e8, 0x350 }, /* manuf_info2 */ | ||
2770 | { 0xb38, 0xf0 }, /* feature_info */ | ||
2771 | { 0, 0 } | ||
2772 | }; | ||
2773 | |||
2614 | u8 *buf; | 2774 | u8 *buf; |
2615 | int i, rc; | 2775 | int rc; |
2616 | u32 magic, crc; | 2776 | u32 magic; |
2617 | 2777 | ||
2618 | if (BP_NOMCP(bp)) | 2778 | if (BP_NOMCP(bp)) |
2619 | return 0; | 2779 | return 0; |
2620 | 2780 | ||
2621 | buf = kmalloc(0x350, GFP_KERNEL); | 2781 | buf = kmalloc(CRC_BUFF_SIZE, GFP_KERNEL); |
2622 | if (!buf) { | 2782 | if (!buf) { |
2623 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "kmalloc failed\n"); | 2783 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "kmalloc failed\n"); |
2624 | rc = -ENOMEM; | 2784 | rc = -ENOMEM; |
@@ -2639,25 +2799,26 @@ static int bnx2x_test_nvram(struct bnx2x *bp) | |||
2639 | goto test_nvram_exit; | 2799 | goto test_nvram_exit; |
2640 | } | 2800 | } |
2641 | 2801 | ||
2642 | for (i = 0; nvram_tbl[i].size; i++) { | 2802 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "Port 0 CRC test-set\n"); |
2803 | rc = bnx2x_test_nvram_tbl(bp, nvram_tbl, buf); | ||
2804 | if (rc) | ||
2805 | goto test_nvram_exit; | ||
2643 | 2806 | ||
2644 | rc = bnx2x_nvram_read(bp, nvram_tbl[i].offset, buf, | 2807 | if (!CHIP_IS_E1x(bp) && !CHIP_IS_57811xx(bp)) { |
2645 | nvram_tbl[i].size); | 2808 | u32 hide = SHMEM_RD(bp, dev_info.shared_hw_config.config2) & |
2646 | if (rc) { | 2809 | SHARED_HW_CFG_HIDE_PORT1; |
2647 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, | ||
2648 | "nvram_tbl[%d] read data (rc %d)\n", i, rc); | ||
2649 | goto test_nvram_exit; | ||
2650 | } | ||
2651 | 2810 | ||
2652 | crc = ether_crc_le(nvram_tbl[i].size, buf); | 2811 | if (!hide) { |
2653 | if (crc != CRC32_RESIDUAL) { | ||
2654 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, | 2812 | DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, |
2655 | "nvram_tbl[%d] wrong crc value (0x%08x)\n", i, crc); | 2813 | "Port 1 CRC test-set\n"); |
2656 | rc = -ENODEV; | 2814 | rc = bnx2x_test_nvram_tbl(bp, nvram_tbl2, buf); |
2657 | goto test_nvram_exit; | 2815 | if (rc) |
2816 | goto test_nvram_exit; | ||
2658 | } | 2817 | } |
2659 | } | 2818 | } |
2660 | 2819 | ||
2820 | rc = bnx2x_test_nvram_dirs(bp, buf); | ||
2821 | |||
2661 | test_nvram_exit: | 2822 | test_nvram_exit: |
2662 | kfree(buf); | 2823 | kfree(buf); |
2663 | return rc; | 2824 | return rc; |