aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2011-11-04 19:06:04 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-01-26 19:10:51 -0500
commit0fb53faa2e6fe67a76b8cfc6eb70a88d9d623648 (patch)
tree7e764db050defe7bec474e4266c5d3dd45a45766
parentcc180b69c009ec52f67a56d96b9073b9f774b323 (diff)
sfc: Remove dependence on NAPI polling in efx_test_eventq_irq()
We cannot safely assume that the NAPI handler will complete within the 20 ms that we allow for the event self-test. The handler may be deferred for longer than this, particularly on realtime kernels. Instead, check whether either an event has been handled or (as in the old failure path) whether an interrupt has been received and an event has been delivered but not yet handled. Use napi_disable() to synchronize with the NAPI handler before checking, since it will clear events before updating eventq_read_ptr. Remove the test result chan.N.eventq.poll, since it is not an error if the NAPI handler does not run during the test. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c4
-rw-r--r--drivers/net/ethernet/sfc/selftest.c79
-rw-r--r--drivers/net/ethernet/sfc/selftest.h1
3 files changed, 40 insertions, 44 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 1a7f7ba27bea..ba9011678013 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -404,10 +404,6 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
404 &tests->eventq_int[channel->channel], 404 &tests->eventq_int[channel->channel],
405 EFX_CHANNEL_NAME(channel), 405 EFX_CHANNEL_NAME(channel),
406 "eventq.int", NULL); 406 "eventq.int", NULL);
407 efx_fill_test(n++, strings, data,
408 &tests->eventq_poll[channel->channel],
409 EFX_CHANNEL_NAME(channel),
410 "eventq.poll", NULL);
411 } 407 }
412 408
413 efx_fill_test(n++, strings, data, &tests->registers, 409 efx_fill_test(n++, strings, data, &tests->registers,
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 7718287ad0bc..0f8478924475 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -161,11 +161,8 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
161 struct efx_self_tests *tests) 161 struct efx_self_tests *tests)
162{ 162{
163 struct efx_nic *efx = channel->efx; 163 struct efx_nic *efx = channel->efx;
164 unsigned int read_ptr, count; 164 unsigned int read_ptr;
165 165 bool napi_ran, dma_seen, int_seen;
166 tests->eventq_dma[channel->channel] = -1;
167 tests->eventq_int[channel->channel] = -1;
168 tests->eventq_poll[channel->channel] = -1;
169 166
170 read_ptr = channel->eventq_read_ptr; 167 read_ptr = channel->eventq_read_ptr;
171 channel->efx->last_irq_cpu = -1; 168 channel->efx->last_irq_cpu = -1;
@@ -173,44 +170,48 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
173 170
174 efx_nic_generate_test_event(channel); 171 efx_nic_generate_test_event(channel);
175 172
176 /* Wait for arrival of interrupt */ 173 /* Wait for arrival of interrupt. NAPI processing may or may
177 count = 0; 174 * not complete in time, but we can cope in any case.
178 do { 175 */
179 schedule_timeout_uninterruptible(HZ / 100); 176 msleep(10);
180 177 napi_disable(&channel->napi_str);
181 if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr) 178 if (channel->eventq_read_ptr != read_ptr) {
182 goto eventq_ok; 179 napi_ran = true;
183 } while (++count < 2); 180 dma_seen = true;
184 181 int_seen = true;
185 netif_err(efx, drv, efx->net_dev, 182 } else {
186 "channel %d timed out waiting for event queue\n", 183 napi_ran = false;
187 channel->channel); 184 dma_seen = efx_nic_event_present(channel);
188 185 int_seen = efx->last_irq_cpu >= 0;
189 /* See if interrupt arrived */
190 if (channel->efx->last_irq_cpu >= 0) {
191 netif_err(efx, drv, efx->net_dev,
192 "channel %d saw interrupt on CPU%d "
193 "during event queue test\n", channel->channel,
194 raw_smp_processor_id());
195 tests->eventq_int[channel->channel] = 1;
196 } 186 }
187 napi_enable(&channel->napi_str);
188 efx_nic_eventq_read_ack(channel);
189
190 tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1;
191 tests->eventq_int[channel->channel] = int_seen ? 1 : -1;
197 192
198 /* Check to see if event was received even if interrupt wasn't */ 193 if (dma_seen && int_seen) {
199 if (efx_nic_event_present(channel)) { 194 netif_dbg(efx, drv, efx->net_dev,
195 "channel %d event queue passed (with%s NAPI)\n",
196 channel->channel, napi_ran ? "" : "out");
197 return 0;
198 } else {
199 /* Report failure and whether either interrupt or DMA worked */
200 netif_err(efx, drv, efx->net_dev, 200 netif_err(efx, drv, efx->net_dev,
201 "channel %d event was generated, but " 201 "channel %d timed out waiting for event queue\n",
202 "failed to trigger an interrupt\n", channel->channel); 202 channel->channel);
203 tests->eventq_dma[channel->channel] = 1; 203 if (int_seen)
204 netif_err(efx, drv, efx->net_dev,
205 "channel %d saw interrupt "
206 "during event queue test\n",
207 channel->channel);
208 if (dma_seen)
209 netif_err(efx, drv, efx->net_dev,
210 "channel %d event was generated, but "
211 "failed to trigger an interrupt\n",
212 channel->channel);
213 return -ETIMEDOUT;
204 } 214 }
205
206 return -ETIMEDOUT;
207 eventq_ok:
208 netif_dbg(efx, drv, efx->net_dev, "channel %d event queue passed\n",
209 channel->channel);
210 tests->eventq_dma[channel->channel] = 1;
211 tests->eventq_int[channel->channel] = 1;
212 tests->eventq_poll[channel->channel] = 1;
213 return 0;
214} 215}
215 216
216static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, 217static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h
index dba5456e70f3..87abe2a53846 100644
--- a/drivers/net/ethernet/sfc/selftest.h
+++ b/drivers/net/ethernet/sfc/selftest.h
@@ -37,7 +37,6 @@ struct efx_self_tests {
37 int interrupt; 37 int interrupt;
38 int eventq_dma[EFX_MAX_CHANNELS]; 38 int eventq_dma[EFX_MAX_CHANNELS];
39 int eventq_int[EFX_MAX_CHANNELS]; 39 int eventq_int[EFX_MAX_CHANNELS];
40 int eventq_poll[EFX_MAX_CHANNELS];
41 /* offline tests */ 40 /* offline tests */
42 int registers; 41 int registers;
43 int phy_ext[EFX_MAX_PHY_TESTS]; 42 int phy_ext[EFX_MAX_PHY_TESTS];