aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-09-06 11:52:31 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-11-30 19:26:09 -0500
commitd5e8cc6c946e0857826dcfbb3585068858445bfe (patch)
tree2867bb12190df7cea905afce3a698d41202953b1
parent3f978ef36cca9bb10c88a56baec1d9d1cb072b98 (diff)
sfc: Really disable flow control while flushing
Receiving pause frames can block TX queue flushes. Earlier changes work around this by reconfiguring the MAC during flushes for VFs, but during flushes for the PF we would only change the fc_disable counter. Unless the MAC is reconfigured for some other reason during the flush (which I would not expect to happen) this had no effect at all. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
-rw-r--r--drivers/net/ethernet/sfc/falcon.c2
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h2
-rw-r--r--drivers/net/ethernet/sfc/nic.c3
-rw-r--r--drivers/net/ethernet/sfc/nic.h2
-rw-r--r--drivers/net/ethernet/sfc/siena.c15
-rw-r--r--drivers/net/ethernet/sfc/siena_sriov.c6
6 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 12b573a8e82b..49bcd196e10d 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -1792,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
1792 .remove_port = falcon_remove_port, 1792 .remove_port = falcon_remove_port,
1793 .handle_global_event = falcon_handle_global_event, 1793 .handle_global_event = falcon_handle_global_event,
1794 .prepare_flush = falcon_prepare_flush, 1794 .prepare_flush = falcon_prepare_flush,
1795 .finish_flush = efx_port_dummy_op_void,
1795 .update_stats = falcon_update_nic_stats, 1796 .update_stats = falcon_update_nic_stats,
1796 .start_stats = falcon_start_nic_stats, 1797 .start_stats = falcon_start_nic_stats,
1797 .stop_stats = falcon_stop_nic_stats, 1798 .stop_stats = falcon_stop_nic_stats,
@@ -1834,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
1834 .remove_port = falcon_remove_port, 1835 .remove_port = falcon_remove_port,
1835 .handle_global_event = falcon_handle_global_event, 1836 .handle_global_event = falcon_handle_global_event,
1836 .prepare_flush = falcon_prepare_flush, 1837 .prepare_flush = falcon_prepare_flush,
1838 .finish_flush = efx_port_dummy_op_void,
1837 .update_stats = falcon_update_nic_stats, 1839 .update_stats = falcon_update_nic_stats,
1838 .start_stats = falcon_start_nic_stats, 1840 .start_stats = falcon_start_nic_stats,
1839 .stop_stats = falcon_stop_nic_stats, 1841 .stop_stats = falcon_stop_nic_stats,
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 2487f582ab04..1014556df0e7 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -907,6 +907,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
907 * @remove_port: Free resources allocated by probe_port() 907 * @remove_port: Free resources allocated by probe_port()
908 * @handle_global_event: Handle a "global" event (may be %NULL) 908 * @handle_global_event: Handle a "global" event (may be %NULL)
909 * @prepare_flush: Prepare the hardware for flushing the DMA queues 909 * @prepare_flush: Prepare the hardware for flushing the DMA queues
910 * @finish_flush: Clean up after flushing the DMA queues
910 * @update_stats: Update statistics not provided by event handling 911 * @update_stats: Update statistics not provided by event handling
911 * @start_stats: Start the regular fetching of statistics 912 * @start_stats: Start the regular fetching of statistics
912 * @stop_stats: Stop the regular fetching of statistics 913 * @stop_stats: Stop the regular fetching of statistics
@@ -954,6 +955,7 @@ struct efx_nic_type {
954 void (*remove_port)(struct efx_nic *efx); 955 void (*remove_port)(struct efx_nic *efx);
955 bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); 956 bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
956 void (*prepare_flush)(struct efx_nic *efx); 957 void (*prepare_flush)(struct efx_nic *efx);
958 void (*finish_flush)(struct efx_nic *efx);
957 void (*update_stats)(struct efx_nic *efx); 959 void (*update_stats)(struct efx_nic *efx);
958 void (*start_stats)(struct efx_nic *efx); 960 void (*start_stats)(struct efx_nic *efx);
959 void (*stop_stats)(struct efx_nic *efx); 961 void (*stop_stats)(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index aab7cacb2e34..e10b7ec046c3 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -680,7 +680,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
680 struct efx_tx_queue *tx_queue; 680 struct efx_tx_queue *tx_queue;
681 int rc = 0; 681 int rc = 0;
682 682
683 efx->fc_disable++;
684 efx->type->prepare_flush(efx); 683 efx->type->prepare_flush(efx);
685 684
686 efx_for_each_channel(channel, efx) { 685 efx_for_each_channel(channel, efx) {
@@ -742,7 +741,7 @@ int efx_nic_flush_queues(struct efx_nic *efx)
742 atomic_set(&efx->rxq_flush_outstanding, 0); 741 atomic_set(&efx->rxq_flush_outstanding, 0);
743 } 742 }
744 743
745 efx->fc_disable--; 744 efx->type->finish_flush(efx);
746 745
747 return rc; 746 return rc;
748} 747}
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 7a9647a3c565..1b0003323498 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -344,6 +344,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
344 344
345/* Global Resources */ 345/* Global Resources */
346extern int efx_nic_flush_queues(struct efx_nic *efx); 346extern int efx_nic_flush_queues(struct efx_nic *efx);
347extern void siena_prepare_flush(struct efx_nic *efx);
348extern void siena_finish_flush(struct efx_nic *efx);
347extern void falcon_start_nic_stats(struct efx_nic *efx); 349extern void falcon_start_nic_stats(struct efx_nic *efx);
348extern void falcon_stop_nic_stats(struct efx_nic *efx); 350extern void falcon_stop_nic_stats(struct efx_nic *efx);
349extern void falcon_setup_xaui(struct efx_nic *efx); 351extern void falcon_setup_xaui(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 84b41bf08a38..3553d77a3fdc 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -127,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx)
127 efx_nic_free_buffer(efx, &efx->stats_buffer); 127 efx_nic_free_buffer(efx, &efx->stats_buffer);
128} 128}
129 129
130void siena_prepare_flush(struct efx_nic *efx)
131{
132 if (efx->fc_disable++ == 0)
133 efx_mcdi_set_mac(efx);
134}
135
136void siena_finish_flush(struct efx_nic *efx)
137{
138 if (--efx->fc_disable == 0)
139 efx_mcdi_set_mac(efx);
140}
141
130static const struct efx_nic_register_test siena_register_tests[] = { 142static const struct efx_nic_register_test siena_register_tests[] = {
131 { FR_AZ_ADR_REGION, 143 { FR_AZ_ADR_REGION,
132 EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) }, 144 EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
@@ -659,7 +671,8 @@ const struct efx_nic_type siena_a0_nic_type = {
659 .reset = siena_reset_hw, 671 .reset = siena_reset_hw,
660 .probe_port = siena_probe_port, 672 .probe_port = siena_probe_port,
661 .remove_port = siena_remove_port, 673 .remove_port = siena_remove_port,
662 .prepare_flush = efx_port_dummy_op_void, 674 .prepare_flush = siena_prepare_flush,
675 .finish_flush = siena_finish_flush,
663 .update_stats = siena_update_nic_stats, 676 .update_stats = siena_update_nic_stats,
664 .start_stats = siena_start_nic_stats, 677 .start_stats = siena_start_nic_stats,
665 .stop_stats = siena_stop_nic_stats, 678 .stop_stats = siena_stop_nic_stats,
diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
index d49b53dc2a50..6e62a018ea32 100644
--- a/drivers/net/ethernet/sfc/siena_sriov.c
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -695,8 +695,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
695 return VFDI_RC_ENOMEM; 695 return VFDI_RC_ENOMEM;
696 696
697 rtnl_lock(); 697 rtnl_lock();
698 if (efx->fc_disable++ == 0) 698 siena_prepare_flush(efx);
699 efx_mcdi_set_mac(efx);
700 rtnl_unlock(); 699 rtnl_unlock();
701 700
702 /* Flush all the initialized queues */ 701 /* Flush all the initialized queues */
@@ -733,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
733 } 732 }
734 733
735 rtnl_lock(); 734 rtnl_lock();
736 if (--efx->fc_disable == 0) 735 siena_finish_flush(efx);
737 efx_mcdi_set_mac(efx);
738 rtnl_unlock(); 736 rtnl_unlock();
739 737
740 /* Irrespective of success/failure, fini the queues */ 738 /* Irrespective of success/failure, fini the queues */