diff options
-rw-r--r-- | drivers/net/igb/igb_ethtool.c | 87 |
1 files changed, 61 insertions, 26 deletions
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index d7bdc6c16d0e..33c23a117fe6 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c | |||
@@ -855,23 +855,26 @@ static struct igb_reg_test reg_test_82576[] = { | |||
855 | { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | 855 | { E1000_RDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, |
856 | { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | 856 | { E1000_RDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
857 | { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, | 857 | { E1000_RDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, |
858 | { E1000_RDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | 858 | { E1000_RDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, |
859 | { E1000_RDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | 859 | { E1000_RDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
860 | { E1000_RDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, | 860 | { E1000_RDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, |
861 | /* Enable all four RX queues before testing. */ | 861 | /* Enable all RX queues before testing. */ |
862 | { E1000_RXDCTL(0), 0x100, 1, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, | 862 | { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, |
863 | { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, E1000_RXDCTL_QUEUE_ENABLE }, | ||
863 | /* RDH is read-only for 82576, only test RDT. */ | 864 | /* RDH is read-only for 82576, only test RDT. */ |
864 | { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | 865 | { E1000_RDT(0), 0x100, 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, |
866 | { E1000_RDT(4), 0x40, 12, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | ||
865 | { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, | 867 | { E1000_RXDCTL(0), 0x100, 4, WRITE_NO_TEST, 0, 0 }, |
868 | { E1000_RXDCTL(4), 0x40, 12, WRITE_NO_TEST, 0, 0 }, | ||
866 | { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, | 869 | { E1000_FCRTH, 0x100, 1, PATTERN_TEST, 0x0000FFF0, 0x0000FFF0 }, |
867 | { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, | 870 | { E1000_FCTTV, 0x100, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, |
868 | { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, | 871 | { E1000_TIPG, 0x100, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF }, |
869 | { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | 872 | { E1000_TDBAL(0), 0x100, 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, |
870 | { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | 873 | { E1000_TDBAH(0), 0x100, 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
871 | { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, | 874 | { E1000_TDLEN(0), 0x100, 4, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, |
872 | { E1000_TDBAL(4), 0x40, 8, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, | 875 | { E1000_TDBAL(4), 0x40, 12, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, |
873 | { E1000_TDBAH(4), 0x40, 8, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | 876 | { E1000_TDBAH(4), 0x40, 12, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
874 | { E1000_TDLEN(4), 0x40, 8, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, | 877 | { E1000_TDLEN(4), 0x40, 12, PATTERN_TEST, 0x000FFFF0, 0x000FFFFF }, |
875 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, | 878 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 }, |
876 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, | 879 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0x003FFFFB }, |
877 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, | 880 | { E1000_RCTL, 0x100, 1, SET_READ_TEST, 0x04CFB0FE, 0xFFFFFFFF }, |
@@ -918,12 +921,13 @@ static struct igb_reg_test reg_test_82575[] = { | |||
918 | static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, | 921 | static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, |
919 | int reg, u32 mask, u32 write) | 922 | int reg, u32 mask, u32 write) |
920 | { | 923 | { |
924 | struct e1000_hw *hw = &adapter->hw; | ||
921 | u32 pat, val; | 925 | u32 pat, val; |
922 | u32 _test[] = | 926 | u32 _test[] = |
923 | {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; | 927 | {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; |
924 | for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { | 928 | for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { |
925 | writel((_test[pat] & write), (adapter->hw.hw_addr + reg)); | 929 | wr32(reg, (_test[pat] & write)); |
926 | val = readl(adapter->hw.hw_addr + reg); | 930 | val = rd32(reg); |
927 | if (val != (_test[pat] & write & mask)) { | 931 | if (val != (_test[pat] & write & mask)) { |
928 | dev_err(&adapter->pdev->dev, "pattern test reg %04X " | 932 | dev_err(&adapter->pdev->dev, "pattern test reg %04X " |
929 | "failed: got 0x%08X expected 0x%08X\n", | 933 | "failed: got 0x%08X expected 0x%08X\n", |
@@ -938,9 +942,10 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data, | |||
938 | static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, | 942 | static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data, |
939 | int reg, u32 mask, u32 write) | 943 | int reg, u32 mask, u32 write) |
940 | { | 944 | { |
945 | struct e1000_hw *hw = &adapter->hw; | ||
941 | u32 val; | 946 | u32 val; |
942 | writel((write & mask), (adapter->hw.hw_addr + reg)); | 947 | wr32(reg, write & mask); |
943 | val = readl(adapter->hw.hw_addr + reg); | 948 | val = rd32(reg); |
944 | if ((write & mask) != (val & mask)) { | 949 | if ((write & mask) != (val & mask)) { |
945 | dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" | 950 | dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" |
946 | " got 0x%08X expected 0x%08X\n", reg, | 951 | " got 0x%08X expected 0x%08X\n", reg, |
@@ -1006,12 +1011,14 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data) | |||
1006 | for (i = 0; i < test->array_len; i++) { | 1011 | for (i = 0; i < test->array_len; i++) { |
1007 | switch (test->test_type) { | 1012 | switch (test->test_type) { |
1008 | case PATTERN_TEST: | 1013 | case PATTERN_TEST: |
1009 | REG_PATTERN_TEST(test->reg + (i * test->reg_offset), | 1014 | REG_PATTERN_TEST(test->reg + |
1015 | (i * test->reg_offset), | ||
1010 | test->mask, | 1016 | test->mask, |
1011 | test->write); | 1017 | test->write); |
1012 | break; | 1018 | break; |
1013 | case SET_READ_TEST: | 1019 | case SET_READ_TEST: |
1014 | REG_SET_AND_CHECK(test->reg + (i * test->reg_offset), | 1020 | REG_SET_AND_CHECK(test->reg + |
1021 | (i * test->reg_offset), | ||
1015 | test->mask, | 1022 | test->mask, |
1016 | test->write); | 1023 | test->write); |
1017 | break; | 1024 | break; |
@@ -1083,16 +1090,17 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1083 | { | 1090 | { |
1084 | struct e1000_hw *hw = &adapter->hw; | 1091 | struct e1000_hw *hw = &adapter->hw; |
1085 | struct net_device *netdev = adapter->netdev; | 1092 | struct net_device *netdev = adapter->netdev; |
1086 | u32 mask, i = 0, shared_int = true; | 1093 | u32 mask, ics_mask, i = 0, shared_int = true; |
1087 | u32 irq = adapter->pdev->irq; | 1094 | u32 irq = adapter->pdev->irq; |
1088 | 1095 | ||
1089 | *data = 0; | 1096 | *data = 0; |
1090 | 1097 | ||
1091 | /* Hook up test interrupt handler just for this test */ | 1098 | /* Hook up test interrupt handler just for this test */ |
1092 | if (adapter->msix_entries) { | 1099 | if (adapter->msix_entries) |
1093 | /* NOTE: we don't test MSI-X interrupts here, yet */ | 1100 | /* NOTE: we don't test MSI-X interrupts here, yet */ |
1094 | return 0; | 1101 | return 0; |
1095 | } else if (adapter->flags & IGB_FLAG_HAS_MSI) { | 1102 | |
1103 | if (adapter->flags & IGB_FLAG_HAS_MSI) { | ||
1096 | shared_int = false; | 1104 | shared_int = false; |
1097 | if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) { | 1105 | if (request_irq(irq, &igb_test_intr, 0, netdev->name, netdev)) { |
1098 | *data = 1; | 1106 | *data = 1; |
@@ -1108,16 +1116,31 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1108 | } | 1116 | } |
1109 | dev_info(&adapter->pdev->dev, "testing %s interrupt\n", | 1117 | dev_info(&adapter->pdev->dev, "testing %s interrupt\n", |
1110 | (shared_int ? "shared" : "unshared")); | 1118 | (shared_int ? "shared" : "unshared")); |
1111 | |||
1112 | /* Disable all the interrupts */ | 1119 | /* Disable all the interrupts */ |
1113 | wr32(E1000_IMC, 0xFFFFFFFF); | 1120 | wr32(E1000_IMC, 0xFFFFFFFF); |
1114 | msleep(10); | 1121 | msleep(10); |
1115 | 1122 | ||
1123 | /* Define all writable bits for ICS */ | ||
1124 | switch(hw->mac.type) { | ||
1125 | case e1000_82575: | ||
1126 | ics_mask = 0x37F47EDD; | ||
1127 | break; | ||
1128 | case e1000_82576: | ||
1129 | ics_mask = 0x77D4FBFD; | ||
1130 | break; | ||
1131 | default: | ||
1132 | ics_mask = 0x7FFFFFFF; | ||
1133 | break; | ||
1134 | } | ||
1135 | |||
1116 | /* Test each interrupt */ | 1136 | /* Test each interrupt */ |
1117 | for (; i < 10; i++) { | 1137 | for (; i < 31; i++) { |
1118 | /* Interrupt to test */ | 1138 | /* Interrupt to test */ |
1119 | mask = 1 << i; | 1139 | mask = 1 << i; |
1120 | 1140 | ||
1141 | if (!(mask & ics_mask)) | ||
1142 | continue; | ||
1143 | |||
1121 | if (!shared_int) { | 1144 | if (!shared_int) { |
1122 | /* Disable the interrupt to be reported in | 1145 | /* Disable the interrupt to be reported in |
1123 | * the cause register and then force the same | 1146 | * the cause register and then force the same |
@@ -1126,8 +1149,12 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1126 | * test failed. | 1149 | * test failed. |
1127 | */ | 1150 | */ |
1128 | adapter->test_icr = 0; | 1151 | adapter->test_icr = 0; |
1129 | wr32(E1000_IMC, ~mask & 0x00007FFF); | 1152 | |
1130 | wr32(E1000_ICS, ~mask & 0x00007FFF); | 1153 | /* Flush any pending interrupts */ |
1154 | wr32(E1000_ICR, ~0); | ||
1155 | |||
1156 | wr32(E1000_IMC, mask); | ||
1157 | wr32(E1000_ICS, mask); | ||
1131 | msleep(10); | 1158 | msleep(10); |
1132 | 1159 | ||
1133 | if (adapter->test_icr & mask) { | 1160 | if (adapter->test_icr & mask) { |
@@ -1143,6 +1170,10 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1143 | * test failed. | 1170 | * test failed. |
1144 | */ | 1171 | */ |
1145 | adapter->test_icr = 0; | 1172 | adapter->test_icr = 0; |
1173 | |||
1174 | /* Flush any pending interrupts */ | ||
1175 | wr32(E1000_ICR, ~0); | ||
1176 | |||
1146 | wr32(E1000_IMS, mask); | 1177 | wr32(E1000_IMS, mask); |
1147 | wr32(E1000_ICS, mask); | 1178 | wr32(E1000_ICS, mask); |
1148 | msleep(10); | 1179 | msleep(10); |
@@ -1160,11 +1191,15 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1160 | * test failed. | 1191 | * test failed. |
1161 | */ | 1192 | */ |
1162 | adapter->test_icr = 0; | 1193 | adapter->test_icr = 0; |
1163 | wr32(E1000_IMC, ~mask & 0x00007FFF); | 1194 | |
1164 | wr32(E1000_ICS, ~mask & 0x00007FFF); | 1195 | /* Flush any pending interrupts */ |
1196 | wr32(E1000_ICR, ~0); | ||
1197 | |||
1198 | wr32(E1000_IMC, ~mask); | ||
1199 | wr32(E1000_ICS, ~mask); | ||
1165 | msleep(10); | 1200 | msleep(10); |
1166 | 1201 | ||
1167 | if (adapter->test_icr) { | 1202 | if (adapter->test_icr & mask) { |
1168 | *data = 5; | 1203 | *data = 5; |
1169 | break; | 1204 | break; |
1170 | } | 1205 | } |
@@ -1172,7 +1207,7 @@ static int igb_intr_test(struct igb_adapter *adapter, u64 *data) | |||
1172 | } | 1207 | } |
1173 | 1208 | ||
1174 | /* Disable all the interrupts */ | 1209 | /* Disable all the interrupts */ |
1175 | wr32(E1000_IMC, 0xFFFFFFFF); | 1210 | wr32(E1000_IMC, ~0); |
1176 | msleep(10); | 1211 | msleep(10); |
1177 | 1212 | ||
1178 | /* Unhook test interrupt handler */ | 1213 | /* Unhook test interrupt handler */ |
@@ -1450,7 +1485,7 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter) | |||
1450 | E1000_CTRL_TFCE | | 1485 | E1000_CTRL_TFCE | |
1451 | E1000_CTRL_LRST); | 1486 | E1000_CTRL_LRST); |
1452 | reg |= E1000_CTRL_SLU | | 1487 | reg |= E1000_CTRL_SLU | |
1453 | E1000_CTRL_FD; | 1488 | E1000_CTRL_FD; |
1454 | wr32(E1000_CTRL, reg); | 1489 | wr32(E1000_CTRL, reg); |
1455 | 1490 | ||
1456 | /* Unset switch control to serdes energy detect */ | 1491 | /* Unset switch control to serdes energy detect */ |