aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-07-03 22:58:33 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-07-17 11:12:33 -0400
commitd4f2cecce138c34960c467d0ae38a6d4bcd6af7b (patch)
tree19a93bad8f6a56361b3b2f12beecae97be4d8ea0
parent0f1e54ae52b950ed79074ae794d027d6c97fd34e (diff)
sfc: Disable VF queues during register self-test
Currently VF queues and drivers may remain active during this test. This could cause memory corruption or spurious test failures. Therefore we reset the port/function before running these tests on Siena. On Falcon this doesn't work: we have to do some additional initialisation before some blocks will work again. So refactor the reset/register-test sequence into an efx_nic_type method so efx_selftest() doesn't have to consider such quirks. In the process, fix another minor bug: Siena does not have an 'invisible' reset and the self-test currently fails to push the PHY configuration after resetting. Passing RESET_TYPE_ALL to efx_reset_{down,up}() fixes this. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/falcon.c35
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h7
-rw-r--r--drivers/net/ethernet/sfc/nic.c3
-rw-r--r--drivers/net/ethernet/sfc/selftest.c62
-rw-r--r--drivers/net/ethernet/sfc/siena.c29
5 files changed, 76 insertions, 60 deletions
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 3a1ca2bd1548..12b573a8e82b 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -25,9 +25,12 @@
25#include "io.h" 25#include "io.h"
26#include "phy.h" 26#include "phy.h"
27#include "workarounds.h" 27#include "workarounds.h"
28#include "selftest.h"
28 29
29/* Hardware control for SFC4000 (aka Falcon). */ 30/* Hardware control for SFC4000 (aka Falcon). */
30 31
32static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
33
31static const unsigned int 34static const unsigned int
32/* "Large" EEPROM device: Atmel AT25640 or similar 35/* "Large" EEPROM device: Atmel AT25640 or similar
33 * 8 KB, 16-bit address, 32 B write block */ 36 * 8 KB, 16-bit address, 32 B write block */
@@ -1034,10 +1037,34 @@ static const struct efx_nic_register_test falcon_b0_register_tests[] = {
1034 EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) }, 1037 EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) },
1035}; 1038};
1036 1039
1037static int falcon_b0_test_registers(struct efx_nic *efx) 1040static int
1041falcon_b0_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
1038{ 1042{
1039 return efx_nic_test_registers(efx, falcon_b0_register_tests, 1043 enum reset_type reset_method = RESET_TYPE_INVISIBLE;
1040 ARRAY_SIZE(falcon_b0_register_tests)); 1044 int rc, rc2;
1045
1046 mutex_lock(&efx->mac_lock);
1047 if (efx->loopback_modes) {
1048 /* We need the 312 clock from the PHY to test the XMAC
1049 * registers, so move into XGMII loopback if available */
1050 if (efx->loopback_modes & (1 << LOOPBACK_XGMII))
1051 efx->loopback_mode = LOOPBACK_XGMII;
1052 else
1053 efx->loopback_mode = __ffs(efx->loopback_modes);
1054 }
1055 __efx_reconfigure_port(efx);
1056 mutex_unlock(&efx->mac_lock);
1057
1058 efx_reset_down(efx, reset_method);
1059
1060 tests->registers =
1061 efx_nic_test_registers(efx, falcon_b0_register_tests,
1062 ARRAY_SIZE(falcon_b0_register_tests))
1063 ? -1 : 1;
1064
1065 rc = falcon_reset_hw(efx, reset_method);
1066 rc2 = efx_reset_up(efx, reset_method, rc == 0);
1067 return rc ? rc : rc2;
1041} 1068}
1042 1069
1043/************************************************************************** 1070/**************************************************************************
@@ -1818,7 +1845,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
1818 .get_wol = falcon_get_wol, 1845 .get_wol = falcon_get_wol,
1819 .set_wol = falcon_set_wol, 1846 .set_wol = falcon_set_wol,
1820 .resume_wol = efx_port_dummy_op_void, 1847 .resume_wol = efx_port_dummy_op_void,
1821 .test_registers = falcon_b0_test_registers, 1848 .test_chip = falcon_b0_test_chip,
1822 .test_nvram = falcon_test_nvram, 1849 .test_nvram = falcon_test_nvram,
1823 1850
1824 .revision = EFX_REV_FALCON_B0, 1851 .revision = EFX_REV_FALCON_B0,
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 8a9f6d48214d..55be2fdb0e62 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -68,6 +68,8 @@
68#define EFX_TXQ_TYPES 4 68#define EFX_TXQ_TYPES 4
69#define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS) 69#define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
70 70
71struct efx_self_tests;
72
71/** 73/**
72 * struct efx_special_buffer - An Efx special buffer 74 * struct efx_special_buffer - An Efx special buffer
73 * @addr: CPU base address of the buffer 75 * @addr: CPU base address of the buffer
@@ -901,7 +903,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
901 * @get_wol: Get WoL configuration from driver state 903 * @get_wol: Get WoL configuration from driver state
902 * @set_wol: Push WoL configuration to the NIC 904 * @set_wol: Push WoL configuration to the NIC
903 * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) 905 * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume)
904 * @test_registers: Test read/write functionality of control registers 906 * @test_chip: Test registers. Should use efx_nic_test_registers(), and is
907 * expected to reset the NIC.
905 * @test_nvram: Test validity of NVRAM contents 908 * @test_nvram: Test validity of NVRAM contents
906 * @revision: Hardware architecture revision 909 * @revision: Hardware architecture revision
907 * @mem_map_size: Memory BAR mapped size 910 * @mem_map_size: Memory BAR mapped size
@@ -946,7 +949,7 @@ struct efx_nic_type {
946 void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); 949 void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol);
947 int (*set_wol)(struct efx_nic *efx, u32 type); 950 int (*set_wol)(struct efx_nic *efx, u32 type);
948 void (*resume_wol)(struct efx_nic *efx); 951 void (*resume_wol)(struct efx_nic *efx);
949 int (*test_registers)(struct efx_nic *efx); 952 int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests);
950 int (*test_nvram)(struct efx_nic *efx); 953 int (*test_nvram)(struct efx_nic *efx);
951 954
952 int revision; 955 int revision;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 287738db24e5..326d799762d6 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -124,9 +124,6 @@ int efx_nic_test_registers(struct efx_nic *efx,
124 unsigned address = 0, i, j; 124 unsigned address = 0, i, j;
125 efx_oword_t mask, imask, original, reg, buf; 125 efx_oword_t mask, imask, original, reg, buf;
126 126
127 /* Falcon should be in loopback to isolate the XMAC from the PHY */
128 WARN_ON(!LOOPBACK_INTERNAL(efx));
129
130 for (i = 0; i < n_regs; ++i) { 127 for (i = 0; i < n_regs; ++i) {
131 address = regs[i].address; 128 address = regs[i].address;
132 mask = imask = regs[i].mask; 129 mask = imask = regs[i].mask;
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index ccc428fc267b..96068d15b601 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -120,19 +120,6 @@ static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests)
120 return rc; 120 return rc;
121} 121}
122 122
123static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
124{
125 int rc = 0;
126
127 /* Test register access */
128 if (efx->type->test_registers) {
129 rc = efx->type->test_registers(efx);
130 tests->registers = rc ? -1 : 1;
131 }
132
133 return rc;
134}
135
136/************************************************************************** 123/**************************************************************************
137 * 124 *
138 * Interrupt and event queue testing 125 * Interrupt and event queue testing
@@ -699,8 +686,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
699{ 686{
700 enum efx_loopback_mode loopback_mode = efx->loopback_mode; 687 enum efx_loopback_mode loopback_mode = efx->loopback_mode;
701 int phy_mode = efx->phy_mode; 688 int phy_mode = efx->phy_mode;
702 enum reset_type reset_method = RESET_TYPE_INVISIBLE; 689 int rc_test = 0, rc_reset, rc;
703 int rc_test = 0, rc_reset = 0, rc;
704 690
705 efx_selftest_async_cancel(efx); 691 efx_selftest_async_cancel(efx);
706 692
@@ -737,44 +723,26 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
737 */ 723 */
738 netif_device_detach(efx->net_dev); 724 netif_device_detach(efx->net_dev);
739 725
740 mutex_lock(&efx->mac_lock); 726 if (efx->type->test_chip) {
741 if (efx->loopback_modes) { 727 rc_reset = efx->type->test_chip(efx, tests);
742 /* We need the 312 clock from the PHY to test the XMAC 728 if (rc_reset) {
743 * registers, so move into XGMII loopback if available */ 729 netif_err(efx, hw, efx->net_dev,
744 if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) 730 "Unable to recover from chip test\n");
745 efx->loopback_mode = LOOPBACK_XGMII; 731 efx_schedule_reset(efx, RESET_TYPE_DISABLE);
746 else 732 return rc_reset;
747 efx->loopback_mode = __ffs(efx->loopback_modes); 733 }
748 }
749
750 __efx_reconfigure_port(efx);
751 mutex_unlock(&efx->mac_lock);
752
753 /* free up all consumers of SRAM (including all the queues) */
754 efx_reset_down(efx, reset_method);
755
756 rc = efx_test_chip(efx, tests);
757 if (rc && !rc_test)
758 rc_test = rc;
759 734
760 /* reset the chip to recover from the register test */ 735 if ((tests->registers < 0) && !rc_test)
761 rc_reset = efx->type->reset(efx, reset_method); 736 rc_test = -EIO;
737 }
762 738
763 /* Ensure that the phy is powered and out of loopback 739 /* Ensure that the phy is powered and out of loopback
764 * for the bist and loopback tests */ 740 * for the bist and loopback tests */
741 mutex_lock(&efx->mac_lock);
765 efx->phy_mode &= ~PHY_MODE_LOW_POWER; 742 efx->phy_mode &= ~PHY_MODE_LOW_POWER;
766 efx->loopback_mode = LOOPBACK_NONE; 743 efx->loopback_mode = LOOPBACK_NONE;
767 744 __efx_reconfigure_port(efx);
768 rc = efx_reset_up(efx, reset_method, rc_reset == 0); 745 mutex_unlock(&efx->mac_lock);
769 if (rc && !rc_reset)
770 rc_reset = rc;
771
772 if (rc_reset) {
773 netif_err(efx, drv, efx->net_dev,
774 "Unable to recover from chip test\n");
775 efx_schedule_reset(efx, RESET_TYPE_DISABLE);
776 return rc_reset;
777 }
778 746
779 rc = efx_test_phy(efx, tests, flags); 747 rc = efx_test_phy(efx, tests, flags);
780 if (rc && !rc_test) 748 if (rc && !rc_test)
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 9f8d7cea3967..2354886293db 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -25,10 +25,12 @@
25#include "workarounds.h" 25#include "workarounds.h"
26#include "mcdi.h" 26#include "mcdi.h"
27#include "mcdi_pcol.h" 27#include "mcdi_pcol.h"
28#include "selftest.h"
28 29
29/* Hardware control for SFC9000 family including SFL9021 (aka Siena). */ 30/* Hardware control for SFC9000 family including SFL9021 (aka Siena). */
30 31
31static void siena_init_wol(struct efx_nic *efx); 32static void siena_init_wol(struct efx_nic *efx);
33static int siena_reset_hw(struct efx_nic *efx, enum reset_type method);
32 34
33 35
34static void siena_push_irq_moderation(struct efx_channel *channel) 36static void siena_push_irq_moderation(struct efx_channel *channel)
@@ -154,10 +156,29 @@ static const struct efx_nic_register_test siena_register_tests[] = {
154 EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000) }, 156 EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000) },
155}; 157};
156 158
157static int siena_test_registers(struct efx_nic *efx) 159static int siena_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
158{ 160{
159 return efx_nic_test_registers(efx, siena_register_tests, 161 enum reset_type reset_method = reset_method;
160 ARRAY_SIZE(siena_register_tests)); 162 int rc, rc2;
163
164 efx_reset_down(efx, reset_method);
165
166 /* Reset the chip immediately so that it is completely
167 * quiescent regardless of what any VF driver does.
168 */
169 rc = siena_reset_hw(efx, reset_method);
170 if (rc)
171 goto out;
172
173 tests->registers =
174 efx_nic_test_registers(efx, siena_register_tests,
175 ARRAY_SIZE(siena_register_tests))
176 ? -1 : 1;
177
178 rc = siena_reset_hw(efx, reset_method);
179out:
180 rc2 = efx_reset_up(efx, reset_method, rc == 0);
181 return rc ? rc : rc2;
161} 182}
162 183
163/************************************************************************** 184/**************************************************************************
@@ -649,7 +670,7 @@ const struct efx_nic_type siena_a0_nic_type = {
649 .get_wol = siena_get_wol, 670 .get_wol = siena_get_wol,
650 .set_wol = siena_set_wol, 671 .set_wol = siena_set_wol,
651 .resume_wol = siena_init_wol, 672 .resume_wol = siena_init_wol,
652 .test_registers = siena_test_registers, 673 .test_chip = siena_test_chip,
653 .test_nvram = efx_mcdi_nvram_test_all, 674 .test_nvram = efx_mcdi_nvram_test_all,
654 675
655 .revision = EFX_REV_SIENA_A0, 676 .revision = EFX_REV_SIENA_A0,