aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kravkov <dmitry@broadcom.com>2013-04-21 23:48:09 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-22 15:34:40 -0400
commitedb944d27b15c08063fdb62eaae6c377e7865e6d (patch)
treec74b4d43fb89c320288755d756b8bdb680a19441
parentf1691dc6159489e8928300cf674fb859f5b5dd12 (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.h7
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c201
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
2598struct 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
2620static 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
2649static 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
2669static 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
2681static 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
2715static 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
2733struct crc_pair {
2734 int offset;
2735 int size;
2736};
2737
2738static 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
2600static int bnx2x_test_nvram(struct bnx2x *bp) 2757static 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
2661test_nvram_exit: 2822test_nvram_exit:
2662 kfree(buf); 2823 kfree(buf);
2663 return rc; 2824 return rc;