Commit 1796721a authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

sfc: Add support for multiple PHY self-tests

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2ef3068e
...@@ -345,7 +345,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, ...@@ -345,7 +345,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
u64 *data) u64 *data)
{ {
struct efx_channel *channel; struct efx_channel *channel;
unsigned int n = 0; unsigned int n = 0, i;
enum efx_loopback_mode mode; enum efx_loopback_mode mode;
efx_fill_test(n++, strings, data, &tests->mii, efx_fill_test(n++, strings, data, &tests->mii,
...@@ -373,8 +373,10 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, ...@@ -373,8 +373,10 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
efx_fill_test(n++, strings, data, &tests->registers, efx_fill_test(n++, strings, data, &tests->registers,
"core", 0, "registers", NULL); "core", 0, "registers", NULL);
efx_fill_test(n++, strings, data, &tests->phy,
"phy", 0, "bist", NULL); for (i = 0; i < efx->phy_op->num_tests; i++)
efx_fill_test(n++, strings, data, &tests->phy[i],
"phy", 0, efx->phy_op->test_names[i], NULL);
/* Loopback tests */ /* Loopback tests */
for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
......
...@@ -568,6 +568,10 @@ struct efx_mac_operations { ...@@ -568,6 +568,10 @@ struct efx_mac_operations {
* @set_settings: Set ethtool settings. Serialised by the mac_lock. * @set_settings: Set ethtool settings. Serialised by the mac_lock.
* @set_xnp_advertise: Set abilities advertised in Extended Next Page * @set_xnp_advertise: Set abilities advertised in Extended Next Page
* (only needed where AN bit is set in mmds) * (only needed where AN bit is set in mmds)
* @num_tests: Number of PHY-specific tests/results
* @test_names: Names of the tests/results
* @run_tests: Run tests and record results as appropriate.
* Flags are the ethtool tests flags.
* @mmds: MMD presence mask * @mmds: MMD presence mask
* @loopbacks: Supported loopback modes mask * @loopbacks: Supported loopback modes mask
*/ */
...@@ -578,12 +582,14 @@ struct efx_phy_operations { ...@@ -578,12 +582,14 @@ struct efx_phy_operations {
void (*reconfigure) (struct efx_nic *efx); void (*reconfigure) (struct efx_nic *efx);
void (*clear_interrupt) (struct efx_nic *efx); void (*clear_interrupt) (struct efx_nic *efx);
void (*poll) (struct efx_nic *efx); void (*poll) (struct efx_nic *efx);
int (*test) (struct efx_nic *efx);
void (*get_settings) (struct efx_nic *efx, void (*get_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd); struct ethtool_cmd *ecmd);
int (*set_settings) (struct efx_nic *efx, int (*set_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd); struct ethtool_cmd *ecmd);
bool (*set_xnp_advertise) (struct efx_nic *efx, u32); bool (*set_xnp_advertise) (struct efx_nic *efx, u32);
u32 num_tests;
const char *const *test_names;
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
int mmds; int mmds;
unsigned loopbacks; unsigned loopbacks;
}; };
......
...@@ -247,17 +247,20 @@ static int efx_test_eventq_irq(struct efx_channel *channel, ...@@ -247,17 +247,20 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
return 0; return 0;
} }
static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
unsigned flags)
{ {
int rc; int rc;
if (!efx->phy_op->test) if (!efx->phy_op->run_tests)
return 0; return 0;
EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 ||
efx->phy_op->num_tests > EFX_MAX_PHY_TESTS);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
rc = efx->phy_op->test(efx); rc = efx->phy_op->run_tests(efx, tests->phy, flags);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
tests->phy = rc ? -1 : 1;
return rc; return rc;
} }
...@@ -691,7 +694,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -691,7 +694,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
return rc_test; return rc_test;
if (!(flags & ETH_TEST_FL_OFFLINE)) if (!(flags & ETH_TEST_FL_OFFLINE))
return 0; return efx_test_phy(efx, tests, flags);
/* Offline (i.e. disruptive) testing /* Offline (i.e. disruptive) testing
* This checks MAC and PHY loopback on the specified port. */ * This checks MAC and PHY loopback on the specified port. */
...@@ -739,7 +742,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, ...@@ -739,7 +742,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
return rc_reset; return rc_reset;
} }
rc = efx_test_phy(efx, tests); rc = efx_test_phy(efx, tests, flags);
if (rc && !rc_test) if (rc && !rc_test)
rc_test = rc; rc_test = rc;
......
...@@ -24,6 +24,8 @@ struct efx_loopback_self_tests { ...@@ -24,6 +24,8 @@ struct efx_loopback_self_tests {
int rx_bad; int rx_bad;
}; };
#define EFX_MAX_PHY_TESTS 20
/* Efx self test results /* Efx self test results
* For fields which are not counters, 1 indicates success and -1 * For fields which are not counters, 1 indicates success and -1
* indicates failure. * indicates failure.
...@@ -38,7 +40,7 @@ struct efx_self_tests { ...@@ -38,7 +40,7 @@ struct efx_self_tests {
int eventq_poll[EFX_MAX_CHANNELS]; int eventq_poll[EFX_MAX_CHANNELS];
/* offline tests */ /* offline tests */
int registers; int registers;
int phy; int phy[EFX_MAX_PHY_TESTS];
struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
}; };
......
...@@ -654,10 +654,22 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink) ...@@ -654,10 +654,22 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
PMA_PMD_LED_OVERR_REG, reg); PMA_PMD_LED_OVERR_REG, reg);
} }
static int tenxpress_phy_test(struct efx_nic *efx) static const char *const tenxpress_test_names[] = {
"bist"
};
static int
tenxpress_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{ {
int rc;
if (!(flags & ETH_TEST_FL_OFFLINE))
return 0;
/* BIST is automatically run after a special software reset */ /* BIST is automatically run after a special software reset */
return tenxpress_special_reset(efx); rc = tenxpress_special_reset(efx);
results[0] = rc ? -1 : 1;
return rc;
} }
static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx)
...@@ -770,9 +782,11 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { ...@@ -770,9 +782,11 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.poll = tenxpress_phy_poll, .poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini, .fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void,
.test = tenxpress_phy_test,
.get_settings = sfx7101_get_settings, .get_settings = sfx7101_get_settings,
.set_settings = mdio_clause45_set_settings, .set_settings = mdio_clause45_set_settings,
.num_tests = ARRAY_SIZE(tenxpress_test_names),
.test_names = tenxpress_test_names,
.run_tests = tenxpress_run_tests,
.mmds = TENXPRESS_REQUIRED_DEVS, .mmds = TENXPRESS_REQUIRED_DEVS,
.loopbacks = SFX7101_LOOPBACKS, .loopbacks = SFX7101_LOOPBACKS,
}; };
...@@ -784,10 +798,12 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { ...@@ -784,10 +798,12 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
.poll = tenxpress_phy_poll, .poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini, .fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void,
.test = tenxpress_phy_test,
.get_settings = sft9001_get_settings, .get_settings = sft9001_get_settings,
.set_settings = sft9001_set_settings, .set_settings = sft9001_set_settings,
.set_xnp_advertise = sft9001_set_xnp_advertise, .set_xnp_advertise = sft9001_set_xnp_advertise,
.num_tests = ARRAY_SIZE(tenxpress_test_names),
.test_names = tenxpress_test_names,
.run_tests = tenxpress_run_tests,
.mmds = TENXPRESS_REQUIRED_DEVS, .mmds = TENXPRESS_REQUIRED_DEVS,
.loopbacks = SFT9001_LOOPBACKS, .loopbacks = SFT9001_LOOPBACKS,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment