diff options
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 2e44191d4b42..2280818476e2 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -728,39 +728,65 @@ err_setup: | |||
728 | return err; | 728 | return err; |
729 | } | 729 | } |
730 | 730 | ||
731 | #define REG_PATTERN_TEST(R, M, W) \ | 731 | static bool reg_pattern_test(struct e1000_adapter *adapter, uint64_t *data, |
732 | { \ | 732 | int reg, uint32_t mask, uint32_t write) |
733 | uint32_t pat, val; \ | 733 | { |
734 | const uint32_t test[] = \ | 734 | static const uint32_t test[] = |
735 | {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ | 735 | {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; |
736 | for (pat = 0; pat < ARRAY_SIZE(test); pat++) { \ | 736 | uint8_t __iomem *address = adapter->hw.hw_addr + reg; |
737 | E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \ | 737 | uint32_t read; |
738 | val = E1000_READ_REG(&adapter->hw, R); \ | 738 | int i; |
739 | if (val != (test[pat] & W & M)) { \ | 739 | |
740 | DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \ | 740 | for (i = 0; i < ARRAY_SIZE(test); i++) { |
741 | "0x%08X expected 0x%08X\n", \ | 741 | writel(write & test[i], address); |
742 | E1000_##R, val, (test[pat] & W & M)); \ | 742 | read = readl(address); |
743 | *data = (adapter->hw.mac_type < e1000_82543) ? \ | 743 | if (read != (write & test[i] & mask)) { |
744 | E1000_82542_##R : E1000_##R; \ | 744 | DPRINTK(DRV, ERR, "pattern test reg %04X failed: " |
745 | return 1; \ | 745 | "got 0x%08X expected 0x%08X\n", |
746 | } \ | 746 | reg, read, (write & test[i] & mask)); |
747 | } \ | 747 | *data = reg; |
748 | return true; | ||
749 | } | ||
750 | } | ||
751 | return false; | ||
748 | } | 752 | } |
749 | 753 | ||
750 | #define REG_SET_AND_CHECK(R, M, W) \ | 754 | static bool reg_set_and_check(struct e1000_adapter *adapter, uint64_t *data, |
751 | { \ | 755 | int reg, uint32_t mask, uint32_t write) |
752 | uint32_t val; \ | 756 | { |
753 | E1000_WRITE_REG(&adapter->hw, R, W & M); \ | 757 | uint8_t __iomem *address = adapter->hw.hw_addr + reg; |
754 | val = E1000_READ_REG(&adapter->hw, R); \ | 758 | uint32_t read; |
755 | if ((W & M) != (val & M)) { \ | 759 | |
756 | DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\ | 760 | writel(write & mask, address); |
757 | "expected 0x%08X\n", E1000_##R, (val & M), (W & M)); \ | 761 | read = readl(address); |
758 | *data = (adapter->hw.mac_type < e1000_82543) ? \ | 762 | if ((read & mask) != (write & mask)) { |
759 | E1000_82542_##R : E1000_##R; \ | 763 | DPRINTK(DRV, ERR, "set/check reg %04X test failed: " |
760 | return 1; \ | 764 | "got 0x%08X expected 0x%08X\n", |
761 | } \ | 765 | reg, (read & mask), (write & mask)); |
766 | *data = reg; | ||
767 | return true; | ||
768 | } | ||
769 | return false; | ||
762 | } | 770 | } |
763 | 771 | ||
772 | #define REG_PATTERN_TEST(reg, mask, write) \ | ||
773 | do { \ | ||
774 | if (reg_pattern_test(adapter, data, \ | ||
775 | (adapter->hw.mac_type >= e1000_82543) \ | ||
776 | ? E1000_##reg : E1000_82542_##reg, \ | ||
777 | mask, write)) \ | ||
778 | return 1; \ | ||
779 | } while (0) | ||
780 | |||
781 | #define REG_SET_AND_CHECK(reg, mask, write) \ | ||
782 | do { \ | ||
783 | if (reg_set_and_check(adapter, data, \ | ||
784 | (adapter->hw.mac_type >= e1000_82543) \ | ||
785 | ? E1000_##reg : E1000_82542_##reg, \ | ||
786 | mask, write)) \ | ||
787 | return 1; \ | ||
788 | } while (0) | ||
789 | |||
764 | static int | 790 | static int |
765 | e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) | 791 | e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) |
766 | { | 792 | { |