diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2012-02-28 18:40:21 -0500 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2012-03-06 13:14:15 -0500 |
commit | dd40781e3a4e9d3177a548c389232ee9496dae8e (patch) | |
tree | 6308028fab5fa47ec105eb77888e3cc8a59b4323 /drivers/net/ethernet/sfc/selftest.c | |
parent | eee6f6a9e0c83811de77a137989d4a3289e297cc (diff) |
sfc: Run event/IRQ self-test asynchronously when interface is brought up
Generate a test event on each event queue whenever the interface is
brought up, then after 1 second check that we have either handled a
test event or handled another IRQ for each event queue.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/selftest.c')
-rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index aa4ab53cac57..de4c0069f5b2 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c | |||
@@ -702,6 +702,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
702 | enum reset_type reset_method = RESET_TYPE_INVISIBLE; | 702 | enum reset_type reset_method = RESET_TYPE_INVISIBLE; |
703 | int rc_test = 0, rc_reset = 0, rc; | 703 | int rc_test = 0, rc_reset = 0, rc; |
704 | 704 | ||
705 | efx_selftest_async_cancel(efx); | ||
706 | |||
705 | /* Online (i.e. non-disruptive) testing | 707 | /* Online (i.e. non-disruptive) testing |
706 | * This checks interrupt generation, event delivery and PHY presence. */ | 708 | * This checks interrupt generation, event delivery and PHY presence. */ |
707 | 709 | ||
@@ -794,3 +796,36 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, | |||
794 | return rc_test; | 796 | return rc_test; |
795 | } | 797 | } |
796 | 798 | ||
799 | void efx_selftest_async_start(struct efx_nic *efx) | ||
800 | { | ||
801 | struct efx_channel *channel; | ||
802 | |||
803 | efx_for_each_channel(channel, efx) | ||
804 | efx_nic_event_test_start(channel); | ||
805 | schedule_delayed_work(&efx->selftest_work, IRQ_TIMEOUT); | ||
806 | } | ||
807 | |||
808 | void efx_selftest_async_cancel(struct efx_nic *efx) | ||
809 | { | ||
810 | cancel_delayed_work_sync(&efx->selftest_work); | ||
811 | } | ||
812 | |||
813 | void efx_selftest_async_work(struct work_struct *data) | ||
814 | { | ||
815 | struct efx_nic *efx = container_of(data, struct efx_nic, | ||
816 | selftest_work.work); | ||
817 | struct efx_channel *channel; | ||
818 | int cpu; | ||
819 | |||
820 | efx_for_each_channel(channel, efx) { | ||
821 | cpu = efx_nic_event_test_irq_cpu(channel); | ||
822 | if (cpu < 0) | ||
823 | netif_err(efx, ifup, efx->net_dev, | ||
824 | "channel %d failed to trigger an interrupt\n", | ||
825 | channel->channel); | ||
826 | else | ||
827 | netif_dbg(efx, ifup, efx->net_dev, | ||
828 | "channel %d triggered interrupt on CPU %d\n", | ||
829 | channel->channel, cpu); | ||
830 | } | ||
831 | } | ||