diff options
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 69 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/efx.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/net_driver.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/selftest.c | 11 |
4 files changed, 3 insertions, 81 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index c72968840f1a..2b2dba1a0676 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -255,23 +255,6 @@ static int efx_process_channel(struct efx_channel *channel, int budget) | |||
255 | return spent; | 255 | return spent; |
256 | } | 256 | } |
257 | 257 | ||
258 | /* Mark channel as finished processing | ||
259 | * | ||
260 | * Note that since we will not receive further interrupts for this | ||
261 | * channel before we finish processing and call the eventq_read_ack() | ||
262 | * method, there is no need to use the interrupt hold-off timers. | ||
263 | */ | ||
264 | static inline void efx_channel_processed(struct efx_channel *channel) | ||
265 | { | ||
266 | /* The interrupt handler for this channel may set work_pending | ||
267 | * as soon as we acknowledge the events we've seen. Make sure | ||
268 | * it's cleared before then. */ | ||
269 | channel->work_pending = false; | ||
270 | smp_wmb(); | ||
271 | |||
272 | efx_nic_eventq_read_ack(channel); | ||
273 | } | ||
274 | |||
275 | /* NAPI poll handler | 258 | /* NAPI poll handler |
276 | * | 259 | * |
277 | * NAPI guarantees serialisation of polls of the same device, which | 260 | * NAPI guarantees serialisation of polls of the same device, which |
@@ -316,58 +299,16 @@ static int efx_poll(struct napi_struct *napi, int budget) | |||
316 | 299 | ||
317 | /* There is no race here; although napi_disable() will | 300 | /* There is no race here; although napi_disable() will |
318 | * only wait for napi_complete(), this isn't a problem | 301 | * only wait for napi_complete(), this isn't a problem |
319 | * since efx_channel_processed() will have no effect if | 302 | * since efx_nic_eventq_read_ack() will have no effect if |
320 | * interrupts have already been disabled. | 303 | * interrupts have already been disabled. |
321 | */ | 304 | */ |
322 | napi_complete(napi); | 305 | napi_complete(napi); |
323 | efx_channel_processed(channel); | 306 | efx_nic_eventq_read_ack(channel); |
324 | } | 307 | } |
325 | 308 | ||
326 | return spent; | 309 | return spent; |
327 | } | 310 | } |
328 | 311 | ||
329 | /* Process the eventq of the specified channel immediately on this CPU | ||
330 | * | ||
331 | * Disable hardware generated interrupts, wait for any existing | ||
332 | * processing to finish, then directly poll (and ack ) the eventq. | ||
333 | * Finally reenable NAPI and interrupts. | ||
334 | * | ||
335 | * This is for use only during a loopback self-test. It must not | ||
336 | * deliver any packets up the stack as this can result in deadlock. | ||
337 | */ | ||
338 | void efx_process_channel_now(struct efx_channel *channel) | ||
339 | { | ||
340 | struct efx_nic *efx = channel->efx; | ||
341 | |||
342 | BUG_ON(channel->channel >= efx->n_channels); | ||
343 | BUG_ON(!channel->enabled); | ||
344 | BUG_ON(!efx->loopback_selftest); | ||
345 | |||
346 | /* Disable interrupts and wait for ISRs to complete */ | ||
347 | efx_nic_disable_interrupts(efx); | ||
348 | if (efx->legacy_irq) { | ||
349 | synchronize_irq(efx->legacy_irq); | ||
350 | efx->legacy_irq_enabled = false; | ||
351 | } | ||
352 | if (channel->irq) | ||
353 | synchronize_irq(channel->irq); | ||
354 | |||
355 | /* Wait for any NAPI processing to complete */ | ||
356 | napi_disable(&channel->napi_str); | ||
357 | |||
358 | /* Poll the channel */ | ||
359 | efx_process_channel(channel, channel->eventq_mask + 1); | ||
360 | |||
361 | /* Ack the eventq. This may cause an interrupt to be generated | ||
362 | * when they are reenabled */ | ||
363 | efx_channel_processed(channel); | ||
364 | |||
365 | napi_enable(&channel->napi_str); | ||
366 | if (efx->legacy_irq) | ||
367 | efx->legacy_irq_enabled = true; | ||
368 | efx_nic_enable_interrupts(efx); | ||
369 | } | ||
370 | |||
371 | /* Create event queue | 312 | /* Create event queue |
372 | * Event queue memory allocations are done only once. If the channel | 313 | * Event queue memory allocations are done only once. If the channel |
373 | * is reset, the memory buffer will be reused; this guards against | 314 | * is reset, the memory buffer will be reused; this guards against |
@@ -407,11 +348,7 @@ static void efx_start_eventq(struct efx_channel *channel) | |||
407 | netif_dbg(channel->efx, ifup, channel->efx->net_dev, | 348 | netif_dbg(channel->efx, ifup, channel->efx->net_dev, |
408 | "chan %d start event queue\n", channel->channel); | 349 | "chan %d start event queue\n", channel->channel); |
409 | 350 | ||
410 | /* The interrupt handler for this channel may set work_pending | 351 | /* Make sure the NAPI handler sees the enabled flag set */ |
411 | * as soon as we enable it. Make sure it's cleared before | ||
412 | * then. Similarly, make sure it sees the enabled flag set. | ||
413 | */ | ||
414 | channel->work_pending = false; | ||
415 | channel->enabled = true; | 352 | channel->enabled = true; |
416 | smp_wmb(); | 353 | smp_wmb(); |
417 | 354 | ||
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index bdb30bbb0c97..09e633ac8687 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h | |||
@@ -109,7 +109,6 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {} | |||
109 | /* Channels */ | 109 | /* Channels */ |
110 | extern int efx_channel_dummy_op_int(struct efx_channel *channel); | 110 | extern int efx_channel_dummy_op_int(struct efx_channel *channel); |
111 | extern void efx_channel_dummy_op_void(struct efx_channel *channel); | 111 | extern void efx_channel_dummy_op_void(struct efx_channel *channel); |
112 | extern void efx_process_channel_now(struct efx_channel *channel); | ||
113 | extern int | 112 | extern int |
114 | efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries); | 113 | efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries); |
115 | 114 | ||
@@ -155,7 +154,6 @@ static inline void efx_schedule_channel(struct efx_channel *channel) | |||
155 | netif_vdbg(channel->efx, intr, channel->efx->net_dev, | 154 | netif_vdbg(channel->efx, intr, channel->efx->net_dev, |
156 | "channel %d scheduling NAPI poll on CPU%d\n", | 155 | "channel %d scheduling NAPI poll on CPU%d\n", |
157 | channel->channel, raw_smp_processor_id()); | 156 | channel->channel, raw_smp_processor_id()); |
158 | channel->work_pending = true; | ||
159 | 157 | ||
160 | napi_schedule(&channel->napi_str); | 158 | napi_schedule(&channel->napi_str); |
161 | } | 159 | } |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index ea64cd8aa6fa..ad89d7d990f5 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -361,7 +361,6 @@ enum efx_rx_alloc_method { | |||
361 | * @irq_moderation: IRQ moderation value (in hardware ticks) | 361 | * @irq_moderation: IRQ moderation value (in hardware ticks) |
362 | * @napi_dev: Net device used with NAPI | 362 | * @napi_dev: Net device used with NAPI |
363 | * @napi_str: NAPI control structure | 363 | * @napi_str: NAPI control structure |
364 | * @work_pending: Is work pending via NAPI? | ||
365 | * @eventq: Event queue buffer | 364 | * @eventq: Event queue buffer |
366 | * @eventq_mask: Event queue pointer mask | 365 | * @eventq_mask: Event queue pointer mask |
367 | * @eventq_read_ptr: Event queue read pointer | 366 | * @eventq_read_ptr: Event queue read pointer |
@@ -393,7 +392,6 @@ struct efx_channel { | |||
393 | unsigned int irq_moderation; | 392 | unsigned int irq_moderation; |
394 | struct net_device *napi_dev; | 393 | struct net_device *napi_dev; |
395 | struct napi_struct napi_str; | 394 | struct napi_struct napi_str; |
396 | bool work_pending; | ||
397 | struct efx_special_buffer eventq; | 395 | struct efx_special_buffer eventq; |
398 | unsigned int eventq_mask; | 396 | unsigned int eventq_mask; |
399 | unsigned int eventq_read_ptr; | 397 | unsigned int eventq_read_ptr; |
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 2069f51b2aa9..716cff9d0160 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c | |||
@@ -447,14 +447,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) | |||
447 | static int efx_poll_loopback(struct efx_nic *efx) | 447 | static int efx_poll_loopback(struct efx_nic *efx) |
448 | { | 448 | { |
449 | struct efx_loopback_state *state = efx->loopback_selftest; | 449 | struct efx_loopback_state *state = efx->loopback_selftest; |
450 | struct efx_channel *channel; | ||
451 | 450 | ||
452 | /* NAPI polling is not enabled, so process channels | ||
453 | * synchronously */ | ||
454 | efx_for_each_channel(channel, efx) { | ||
455 | if (channel->work_pending) | ||
456 | efx_process_channel_now(channel); | ||
457 | } | ||
458 | return atomic_read(&state->rx_good) == state->packet_count; | 451 | return atomic_read(&state->rx_good) == state->packet_count; |
459 | } | 452 | } |
460 | 453 | ||
@@ -586,10 +579,6 @@ static int efx_wait_for_link(struct efx_nic *efx) | |||
586 | mutex_lock(&efx->mac_lock); | 579 | mutex_lock(&efx->mac_lock); |
587 | efx->type->monitor(efx); | 580 | efx->type->monitor(efx); |
588 | mutex_unlock(&efx->mac_lock); | 581 | mutex_unlock(&efx->mac_lock); |
589 | } else { | ||
590 | struct efx_channel *channel = efx_get_channel(efx, 0); | ||
591 | if (channel->work_pending) | ||
592 | efx_process_channel_now(channel); | ||
593 | } | 582 | } |
594 | 583 | ||
595 | mutex_lock(&efx->mac_lock); | 584 | mutex_lock(&efx->mac_lock); |