aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-05-27 11:52:54 -0400
committerBen Hutchings <bhutchings@solarflare.com>2013-08-21 14:49:23 -0400
commite42c3d85af629697699c89aecba481527a1da898 (patch)
tree7431ccaddc601beb668969d26cb1d07f6d72a264 /drivers/net/ethernet/sfc
parent501a248cf6995286a4da0c2aa93c0fa9c5941453 (diff)
sfc: Refactor queue teardown sequence to allow for EF10 flush behaviour
Currently efx_stop_datapath() will try to flush our DMA queues (if DMA is enabled), then finalise software and hardware state for each queue. However, for EF10 we must ask the MC to finalise each queue, which implicitly starts flushing it, and then wait for the flush events. We therefore need to delegate more of this to the NIC type. Combine all the hardware operations into a new NIC-type operation efx_nic_type::fini_dmaq, and call this before tearing down the software state and buffers for all the DMA queues. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/efx.c40
-rw-r--r--drivers/net/ethernet/sfc/efx.h1
-rw-r--r--drivers/net/ethernet/sfc/falcon.c2
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h6
-rw-r--r--drivers/net/ethernet/sfc/nic.c31
-rw-r--r--drivers/net/ethernet/sfc/nic.h4
-rw-r--r--drivers/net/ethernet/sfc/rx.c1
-rw-r--r--drivers/net/ethernet/sfc/siena.c1
-rw-r--r--drivers/net/ethernet/sfc/tx.c21
9 files changed, 59 insertions, 48 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 0c3c0c19b455..9c6555c12acf 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -640,7 +640,6 @@ static void efx_stop_datapath(struct efx_nic *efx)
640 struct efx_channel *channel; 640 struct efx_channel *channel;
641 struct efx_tx_queue *tx_queue; 641 struct efx_tx_queue *tx_queue;
642 struct efx_rx_queue *rx_queue; 642 struct efx_rx_queue *rx_queue;
643 struct pci_dev *dev = efx->pci_dev;
644 int rc; 643 int rc;
645 644
646 EFX_ASSERT_RESET_SERIALISED(efx); 645 EFX_ASSERT_RESET_SERIALISED(efx);
@@ -652,26 +651,6 @@ static void efx_stop_datapath(struct efx_nic *efx)
652 rx_queue->refill_enabled = false; 651 rx_queue->refill_enabled = false;
653 } 652 }
654 653
655 /* Only perform flush if dma is enabled */
656 if (dev->is_busmaster && efx->state != STATE_RECOVERY) {
657 rc = efx_nic_flush_queues(efx);
658
659 if (rc && EFX_WORKAROUND_7803(efx)) {
660 /* Schedule a reset to recover from the flush failure. The
661 * descriptor caches reference memory we're about to free,
662 * but falcon_reconfigure_mac_wrapper() won't reconnect
663 * the MACs because of the pending reset. */
664 netif_err(efx, drv, efx->net_dev,
665 "Resetting to recover from flush failure\n");
666 efx_schedule_reset(efx, RESET_TYPE_ALL);
667 } else if (rc) {
668 netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
669 } else {
670 netif_dbg(efx, drv, efx->net_dev,
671 "successfully flushed all queues\n");
672 }
673 }
674
675 efx_for_each_channel(channel, efx) { 654 efx_for_each_channel(channel, efx) {
676 /* RX packet processing is pipelined, so wait for the 655 /* RX packet processing is pipelined, so wait for the
677 * NAPI handler to complete. At least event queue 0 656 * NAPI handler to complete. At least event queue 0
@@ -683,7 +662,26 @@ static void efx_stop_datapath(struct efx_nic *efx)
683 efx_stop_eventq(channel); 662 efx_stop_eventq(channel);
684 efx_start_eventq(channel); 663 efx_start_eventq(channel);
685 } 664 }
665 }
686 666
667 rc = efx->type->fini_dmaq(efx);
668 if (rc && EFX_WORKAROUND_7803(efx)) {
669 /* Schedule a reset to recover from the flush failure. The
670 * descriptor caches reference memory we're about to free,
671 * but falcon_reconfigure_mac_wrapper() won't reconnect
672 * the MACs because of the pending reset.
673 */
674 netif_err(efx, drv, efx->net_dev,
675 "Resetting to recover from flush failure\n");
676 efx_schedule_reset(efx, RESET_TYPE_ALL);
677 } else if (rc) {
678 netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
679 } else {
680 netif_dbg(efx, drv, efx->net_dev,
681 "successfully flushed all queues\n");
682 }
683
684 efx_for_each_channel(channel, efx) {
687 efx_for_each_channel_rx_queue(rx_queue, channel) 685 efx_for_each_channel_rx_queue(rx_queue, channel)
688 efx_fini_rx_queue(rx_queue); 686 efx_fini_rx_queue(rx_queue);
689 efx_for_each_possible_channel_tx_queue(tx_queue, channel) 687 efx_for_each_possible_channel_tx_queue(tx_queue, channel)
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 09e633ac8687..45de5b9fedbe 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -23,7 +23,6 @@ extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
23extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue); 23extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
24extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue); 24extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
25extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue); 25extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
26extern void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
27extern netdev_tx_t 26extern netdev_tx_t
28efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev); 27efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
29extern netdev_tx_t 28extern netdev_tx_t
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 4492129cc8f9..c8efcb0efded 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2351,6 +2351,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
2351 .probe_port = falcon_probe_port, 2351 .probe_port = falcon_probe_port,
2352 .remove_port = falcon_remove_port, 2352 .remove_port = falcon_remove_port,
2353 .handle_global_event = falcon_handle_global_event, 2353 .handle_global_event = falcon_handle_global_event,
2354 .fini_dmaq = efx_farch_fini_dmaq,
2354 .prepare_flush = falcon_prepare_flush, 2355 .prepare_flush = falcon_prepare_flush,
2355 .finish_flush = efx_port_dummy_op_void, 2356 .finish_flush = efx_port_dummy_op_void,
2356 .update_stats = falcon_update_nic_stats, 2357 .update_stats = falcon_update_nic_stats,
@@ -2396,6 +2397,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
2396 .probe_port = falcon_probe_port, 2397 .probe_port = falcon_probe_port,
2397 .remove_port = falcon_remove_port, 2398 .remove_port = falcon_remove_port,
2398 .handle_global_event = falcon_handle_global_event, 2399 .handle_global_event = falcon_handle_global_event,
2400 .fini_dmaq = efx_farch_fini_dmaq,
2399 .prepare_flush = falcon_prepare_flush, 2401 .prepare_flush = falcon_prepare_flush,
2400 .finish_flush = efx_port_dummy_op_void, 2402 .finish_flush = efx_port_dummy_op_void,
2401 .update_stats = falcon_update_nic_stats, 2403 .update_stats = falcon_update_nic_stats,
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index c9f798913f39..b382895901b1 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -953,8 +953,11 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
953 * @probe_port: Probe the MAC and PHY 953 * @probe_port: Probe the MAC and PHY
954 * @remove_port: Free resources allocated by probe_port() 954 * @remove_port: Free resources allocated by probe_port()
955 * @handle_global_event: Handle a "global" event (may be %NULL) 955 * @handle_global_event: Handle a "global" event (may be %NULL)
956 * @fini_dmaq: Flush and finalise DMA queues (RX and TX queues)
956 * @prepare_flush: Prepare the hardware for flushing the DMA queues 957 * @prepare_flush: Prepare the hardware for flushing the DMA queues
957 * @finish_flush: Clean up after flushing the DMA queues 958 * (for Falcon architecture)
959 * @finish_flush: Clean up after flushing the DMA queues (for Falcon
960 * architecture)
958 * @update_stats: Update statistics not provided by event handling 961 * @update_stats: Update statistics not provided by event handling
959 * @start_stats: Start the regular fetching of statistics 962 * @start_stats: Start the regular fetching of statistics
960 * @stop_stats: Stop the regular fetching of statistics 963 * @stop_stats: Stop the regular fetching of statistics
@@ -1014,6 +1017,7 @@ struct efx_nic_type {
1014 int (*probe_port)(struct efx_nic *efx); 1017 int (*probe_port)(struct efx_nic *efx);
1015 void (*remove_port)(struct efx_nic *efx); 1018 void (*remove_port)(struct efx_nic *efx);
1016 bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); 1019 bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
1020 int (*fini_dmaq)(struct efx_nic *efx);
1017 void (*prepare_flush)(struct efx_nic *efx); 1021 void (*prepare_flush)(struct efx_nic *efx);
1018 void (*finish_flush)(struct efx_nic *efx); 1022 void (*finish_flush)(struct efx_nic *efx);
1019 void (*update_stats)(struct efx_nic *efx); 1023 void (*update_stats)(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index deb0ee04fe70..7c52691e9d26 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -721,7 +721,7 @@ static bool efx_check_tx_flush_complete(struct efx_nic *efx)
721/* Flush all the transmit queues, and continue flushing receive queues until 721/* Flush all the transmit queues, and continue flushing receive queues until
722 * they're all flushed. Wait for the DRAIN events to be recieved so that there 722 * they're all flushed. Wait for the DRAIN events to be recieved so that there
723 * are no more RX and TX events left on any channel. */ 723 * are no more RX and TX events left on any channel. */
724int efx_nic_flush_queues(struct efx_nic *efx) 724static int efx_farch_do_flush(struct efx_nic *efx)
725{ 725{
726 unsigned timeout = msecs_to_jiffies(5000); /* 5s for all flushes and drains */ 726 unsigned timeout = msecs_to_jiffies(5000); /* 5s for all flushes and drains */
727 struct efx_channel *channel; 727 struct efx_channel *channel;
@@ -729,8 +729,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
729 struct efx_tx_queue *tx_queue; 729 struct efx_tx_queue *tx_queue;
730 int rc = 0; 730 int rc = 0;
731 731
732 efx->type->prepare_flush(efx);
733
734 efx_for_each_channel(channel, efx) { 732 efx_for_each_channel(channel, efx) {
735 efx_for_each_channel_tx_queue(tx_queue, channel) { 733 efx_for_each_channel_tx_queue(tx_queue, channel) {
736 atomic_inc(&efx->drain_pending); 734 atomic_inc(&efx->drain_pending);
@@ -791,7 +789,32 @@ int efx_nic_flush_queues(struct efx_nic *efx)
791 atomic_set(&efx->rxq_flush_outstanding, 0); 789 atomic_set(&efx->rxq_flush_outstanding, 0);
792 } 790 }
793 791
794 efx->type->finish_flush(efx); 792 return rc;
793}
794
795int efx_farch_fini_dmaq(struct efx_nic *efx)
796{
797 struct efx_channel *channel;
798 struct efx_tx_queue *tx_queue;
799 struct efx_rx_queue *rx_queue;
800 int rc = 0;
801
802 /* Do not attempt to write to the NIC during EEH recovery */
803 if (efx->state != STATE_RECOVERY) {
804 /* Only perform flush if DMA is enabled */
805 if (efx->pci_dev->is_busmaster) {
806 efx->type->prepare_flush(efx);
807 rc = efx_farch_do_flush(efx);
808 efx->type->finish_flush(efx);
809 }
810
811 efx_for_each_channel(channel, efx) {
812 efx_for_each_channel_rx_queue(rx_queue, channel)
813 efx_nic_fini_rx(rx_queue);
814 efx_for_each_channel_tx_queue(tx_queue, channel)
815 efx_nic_fini_tx(tx_queue);
816 }
817 }
795 818
796 return rc; 819 return rc;
797} 820}
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 33aa120e3248..21f662cc39a4 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -260,14 +260,12 @@ extern int falcon_probe_board(struct efx_nic *efx, u16 revision_info);
260/* TX data path */ 260/* TX data path */
261extern int efx_nic_probe_tx(struct efx_tx_queue *tx_queue); 261extern int efx_nic_probe_tx(struct efx_tx_queue *tx_queue);
262extern void efx_nic_init_tx(struct efx_tx_queue *tx_queue); 262extern void efx_nic_init_tx(struct efx_tx_queue *tx_queue);
263extern void efx_nic_fini_tx(struct efx_tx_queue *tx_queue);
264extern void efx_nic_remove_tx(struct efx_tx_queue *tx_queue); 263extern void efx_nic_remove_tx(struct efx_tx_queue *tx_queue);
265extern void efx_nic_push_buffers(struct efx_tx_queue *tx_queue); 264extern void efx_nic_push_buffers(struct efx_tx_queue *tx_queue);
266 265
267/* RX data path */ 266/* RX data path */
268extern int efx_nic_probe_rx(struct efx_rx_queue *rx_queue); 267extern int efx_nic_probe_rx(struct efx_rx_queue *rx_queue);
269extern void efx_nic_init_rx(struct efx_rx_queue *rx_queue); 268extern void efx_nic_init_rx(struct efx_rx_queue *rx_queue);
270extern void efx_nic_fini_rx(struct efx_rx_queue *rx_queue);
271extern void efx_nic_remove_rx(struct efx_rx_queue *rx_queue); 269extern void efx_nic_remove_rx(struct efx_rx_queue *rx_queue);
272extern void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue); 270extern void efx_nic_notify_rx_desc(struct efx_rx_queue *rx_queue);
273extern void efx_nic_generate_fill_event(struct efx_rx_queue *rx_queue); 271extern void efx_nic_generate_fill_event(struct efx_rx_queue *rx_queue);
@@ -319,7 +317,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
319} 317}
320 318
321/* Global Resources */ 319/* Global Resources */
322extern int efx_nic_flush_queues(struct efx_nic *efx); 320extern int efx_farch_fini_dmaq(struct efx_nic *efx);
323extern void siena_prepare_flush(struct efx_nic *efx); 321extern void siena_prepare_flush(struct efx_nic *efx);
324extern void siena_finish_flush(struct efx_nic *efx); 322extern void siena_finish_flush(struct efx_nic *efx);
325extern void falcon_start_nic_stats(struct efx_nic *efx); 323extern void falcon_start_nic_stats(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 8b482dee4eb0..f2b78cd2baf8 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -757,7 +757,6 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
757 "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue)); 757 "shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
758 758
759 del_timer_sync(&rx_queue->slow_fill); 759 del_timer_sync(&rx_queue->slow_fill);
760 efx_nic_fini_rx(rx_queue);
761 760
762 /* Release RX buffers from the current read ptr to the write ptr */ 761 /* Release RX buffers from the current read ptr to the write ptr */
763 if (rx_queue->buffer) { 762 if (rx_queue->buffer) {
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index d0eeb03a9bb7..b4c1d4310afe 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -685,6 +685,7 @@ const struct efx_nic_type siena_a0_nic_type = {
685 .reset = efx_mcdi_reset, 685 .reset = efx_mcdi_reset,
686 .probe_port = efx_mcdi_port_probe, 686 .probe_port = efx_mcdi_port_probe,
687 .remove_port = efx_mcdi_port_remove, 687 .remove_port = efx_mcdi_port_remove,
688 .fini_dmaq = efx_farch_fini_dmaq,
688 .prepare_flush = siena_prepare_flush, 689 .prepare_flush = siena_prepare_flush,
689 .finish_flush = siena_finish_flush, 690 .finish_flush = siena_finish_flush,
690 .update_stats = siena_update_nic_stats, 691 .update_stats = siena_update_nic_stats,
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index c0d40403db23..4903c4f7f292 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -543,10 +543,13 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
543 tx_queue->initialised = true; 543 tx_queue->initialised = true;
544} 544}
545 545
546void efx_release_tx_buffers(struct efx_tx_queue *tx_queue) 546void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
547{ 547{
548 struct efx_tx_buffer *buffer; 548 struct efx_tx_buffer *buffer;
549 549
550 netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
551 "shutting down TX queue %d\n", tx_queue->queue);
552
550 if (!tx_queue->buffer) 553 if (!tx_queue->buffer)
551 return; 554 return;
552 555
@@ -561,22 +564,6 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
561 netdev_tx_reset_queue(tx_queue->core_txq); 564 netdev_tx_reset_queue(tx_queue->core_txq);
562} 565}
563 566
564void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
565{
566 if (!tx_queue->initialised)
567 return;
568
569 netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
570 "shutting down TX queue %d\n", tx_queue->queue);
571
572 tx_queue->initialised = false;
573
574 /* Flush TX queue, remove descriptor ring */
575 efx_nic_fini_tx(tx_queue);
576
577 efx_release_tx_buffers(tx_queue);
578}
579
580void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) 567void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
581{ 568{
582 int i; 569 int i;