diff options
-rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index febe2a9e6211..dc330b9d9168 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c | |||
@@ -25,6 +25,16 @@ | |||
25 | #include "selftest.h" | 25 | #include "selftest.h" |
26 | #include "workarounds.h" | 26 | #include "workarounds.h" |
27 | 27 | ||
28 | /* IRQ latency can be enormous because: | ||
29 | * - All IRQs may be disabled on a CPU for a *long* time by e.g. a | ||
30 | * slow serial console or an old IDE driver doing error recovery | ||
31 | * - The PREEMPT_RT patches mostly deal with this, but also allow a | ||
32 | * tasklet or normal task to be given higher priority than our IRQ | ||
33 | * threads | ||
34 | * Try to avoid blaming the hardware for this. | ||
35 | */ | ||
36 | #define IRQ_TIMEOUT HZ | ||
37 | |||
28 | /* | 38 | /* |
29 | * Loopback test packet structure | 39 | * Loopback test packet structure |
30 | * | 40 | * |
@@ -77,6 +87,9 @@ struct efx_loopback_state { | |||
77 | struct efx_loopback_payload payload; | 87 | struct efx_loopback_payload payload; |
78 | }; | 88 | }; |
79 | 89 | ||
90 | /* How long to wait for all the packets to arrive (in ms) */ | ||
91 | #define LOOPBACK_TIMEOUT_MS 1000 | ||
92 | |||
80 | /************************************************************************** | 93 | /************************************************************************** |
81 | * | 94 | * |
82 | * MII, NVRAM and register tests | 95 | * MII, NVRAM and register tests |
@@ -130,6 +143,7 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) | |||
130 | static int efx_test_interrupts(struct efx_nic *efx, | 143 | static int efx_test_interrupts(struct efx_nic *efx, |
131 | struct efx_self_tests *tests) | 144 | struct efx_self_tests *tests) |
132 | { | 145 | { |
146 | unsigned long timeout, wait; | ||
133 | int cpu; | 147 | int cpu; |
134 | 148 | ||
135 | netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); | 149 | netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); |
@@ -140,13 +154,18 @@ static int efx_test_interrupts(struct efx_nic *efx, | |||
140 | smp_wmb(); | 154 | smp_wmb(); |
141 | 155 | ||
142 | efx_nic_generate_interrupt(efx); | 156 | efx_nic_generate_interrupt(efx); |
157 | timeout = jiffies + IRQ_TIMEOUT; | ||
158 | wait = 1; | ||
143 | 159 | ||
144 | /* Wait for arrival of test interrupt. */ | 160 | /* Wait for arrival of test interrupt. */ |
145 | netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); | 161 | netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); |
146 | schedule_timeout_uninterruptible(HZ / 10); | 162 | do { |
147 | cpu = ACCESS_ONCE(efx->last_irq_cpu); | 163 | schedule_timeout_uninterruptible(wait); |
148 | if (cpu >= 0) | 164 | cpu = ACCESS_ONCE(efx->last_irq_cpu); |
149 | goto success; | 165 | if (cpu >= 0) |
166 | goto success; | ||
167 | wait *= 2; | ||
168 | } while (time_before(jiffies, timeout)); | ||
150 | 169 | ||
151 | netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); | 170 | netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); |
152 | return -ETIMEDOUT; | 171 | return -ETIMEDOUT; |
@@ -165,29 +184,37 @@ static int efx_test_eventq_irq(struct efx_channel *channel, | |||
165 | struct efx_nic *efx = channel->efx; | 184 | struct efx_nic *efx = channel->efx; |
166 | unsigned int read_ptr; | 185 | unsigned int read_ptr; |
167 | bool napi_ran, dma_seen, int_seen; | 186 | bool napi_ran, dma_seen, int_seen; |
187 | unsigned long timeout, wait; | ||
168 | 188 | ||
169 | read_ptr = channel->eventq_read_ptr; | 189 | read_ptr = channel->eventq_read_ptr; |
170 | channel->last_irq_cpu = -1; | 190 | channel->last_irq_cpu = -1; |
171 | smp_wmb(); | 191 | smp_wmb(); |
172 | 192 | ||
173 | efx_nic_generate_test_event(channel); | 193 | efx_nic_generate_test_event(channel); |
194 | timeout = jiffies + IRQ_TIMEOUT; | ||
195 | wait = 1; | ||
174 | 196 | ||
175 | /* Wait for arrival of interrupt. NAPI processing may or may | 197 | /* Wait for arrival of interrupt. NAPI processing may or may |
176 | * not complete in time, but we can cope in any case. | 198 | * not complete in time, but we can cope in any case. |
177 | */ | 199 | */ |
178 | msleep(10); | 200 | do { |
179 | napi_disable(&channel->napi_str); | 201 | schedule_timeout_uninterruptible(wait); |
180 | if (channel->eventq_read_ptr != read_ptr) { | 202 | |
181 | napi_ran = true; | 203 | napi_disable(&channel->napi_str); |
182 | dma_seen = true; | 204 | if (channel->eventq_read_ptr != read_ptr) { |
183 | int_seen = true; | 205 | napi_ran = true; |
184 | } else { | 206 | dma_seen = true; |
185 | napi_ran = false; | 207 | int_seen = true; |
186 | dma_seen = efx_nic_event_present(channel); | 208 | } else { |
187 | int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0; | 209 | napi_ran = false; |
188 | } | 210 | dma_seen = efx_nic_event_present(channel); |
189 | napi_enable(&channel->napi_str); | 211 | int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0; |
190 | efx_nic_eventq_read_ack(channel); | 212 | } |
213 | napi_enable(&channel->napi_str); | ||
214 | efx_nic_eventq_read_ack(channel); | ||
215 | |||
216 | wait *= 2; | ||
217 | } while (!(dma_seen && int_seen) && time_before(jiffies, timeout)); | ||
191 | 218 | ||
192 | tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1; | 219 | tests->eventq_dma[channel->channel] = dma_seen ? 1 : -1; |
193 | tests->eventq_int[channel->channel] = int_seen ? 1 : -1; | 220 | tests->eventq_int[channel->channel] = int_seen ? 1 : -1; |
@@ -516,10 +543,10 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, | |||
516 | begin_rc = efx_begin_loopback(tx_queue); | 543 | begin_rc = efx_begin_loopback(tx_queue); |
517 | 544 | ||
518 | /* This will normally complete very quickly, but be | 545 | /* This will normally complete very quickly, but be |
519 | * prepared to wait up to 100 ms. */ | 546 | * prepared to wait much longer. */ |
520 | msleep(1); | 547 | msleep(1); |
521 | if (!efx_poll_loopback(efx)) { | 548 | if (!efx_poll_loopback(efx)) { |
522 | msleep(100); | 549 | msleep(LOOPBACK_TIMEOUT_MS); |
523 | efx_poll_loopback(efx); | 550 | efx_poll_loopback(efx); |
524 | } | 551 | } |
525 | 552 | ||