sfc: Really disable flow control while flushing
authorBen Hutchings <bhutchings@solarflare.com>
Thu, 6 Sep 2012 15:52:31 +0000 (16:52 +0100)
committerBen Hutchings <bhutchings@solarflare.com>
Sat, 1 Dec 2012 00:26:09 +0000 (00:26 +0000)
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>
drivers/net/ethernet/sfc/falcon.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/siena.c
drivers/net/ethernet/sfc/siena_sriov.c

index 12b573a8e82b6a083da1bd86c714a37792624c1f..49bcd196e10d04b4bac011ba20e652756833c543 100644 (file)
@@ -1792,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
        .remove_port = falcon_remove_port,
        .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
+       .finish_flush = efx_port_dummy_op_void,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,
        .stop_stats = falcon_stop_nic_stats,
@@ -1834,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
        .remove_port = falcon_remove_port,
        .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
+       .finish_flush = efx_port_dummy_op_void,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,
        .stop_stats = falcon_stop_nic_stats,
index 2487f582ab047dc27601a499d788b7701ebbb321..1014556df0e7156060a605bb6594855d732afaa2 100644 (file)
@@ -907,6 +907,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
  * @remove_port: Free resources allocated by probe_port()
  * @handle_global_event: Handle a "global" event (may be %NULL)
  * @prepare_flush: Prepare the hardware for flushing the DMA queues
+ * @finish_flush: Clean up after flushing the DMA queues
  * @update_stats: Update statistics not provided by event handling
  * @start_stats: Start the regular fetching of statistics
  * @stop_stats: Stop the regular fetching of statistics
@@ -954,6 +955,7 @@ struct efx_nic_type {
        void (*remove_port)(struct efx_nic *efx);
        bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
        void (*prepare_flush)(struct efx_nic *efx);
+       void (*finish_flush)(struct efx_nic *efx);
        void (*update_stats)(struct efx_nic *efx);
        void (*start_stats)(struct efx_nic *efx);
        void (*stop_stats)(struct efx_nic *efx);
index aab7cacb2e34a87203d199be8df72c20020b0e0b..e10b7ec046c397819f492a393d535f0ec3135545 100644 (file)
@@ -680,7 +680,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
        struct efx_tx_queue *tx_queue;
        int rc = 0;
 
-       efx->fc_disable++;
        efx->type->prepare_flush(efx);
 
        efx_for_each_channel(channel, efx) {
@@ -742,7 +741,7 @@ int efx_nic_flush_queues(struct efx_nic *efx)
                atomic_set(&efx->rxq_flush_outstanding, 0);
        }
 
-       efx->fc_disable--;
+       efx->type->finish_flush(efx);
 
        return rc;
 }
index 7a9647a3c565442ba02017ff40d2605f9b785552..1b0003323498502741f2c36d5437586a8e8176f6 100644 (file)
@@ -344,6 +344,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
 
 /* Global Resources */
 extern int efx_nic_flush_queues(struct efx_nic *efx);
+extern void siena_prepare_flush(struct efx_nic *efx);
+extern void siena_finish_flush(struct efx_nic *efx);
 extern void falcon_start_nic_stats(struct efx_nic *efx);
 extern void falcon_stop_nic_stats(struct efx_nic *efx);
 extern void falcon_setup_xaui(struct efx_nic *efx);
index 84b41bf08a38a22ad8e9f0954ec32631628b4ad7..3553d77a3fdc3fa47219e771291a307aec830c16 100644 (file)
@@ -127,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx)
        efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
+void siena_prepare_flush(struct efx_nic *efx)
+{
+       if (efx->fc_disable++ == 0)
+               efx_mcdi_set_mac(efx);
+}
+
+void siena_finish_flush(struct efx_nic *efx)
+{
+       if (--efx->fc_disable == 0)
+               efx_mcdi_set_mac(efx);
+}
+
 static const struct efx_nic_register_test siena_register_tests[] = {
        { FR_AZ_ADR_REGION,
          EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
@@ -659,7 +671,8 @@ const struct efx_nic_type siena_a0_nic_type = {
        .reset = siena_reset_hw,
        .probe_port = siena_probe_port,
        .remove_port = siena_remove_port,
-       .prepare_flush = efx_port_dummy_op_void,
+       .prepare_flush = siena_prepare_flush,
+       .finish_flush = siena_finish_flush,
        .update_stats = siena_update_nic_stats,
        .start_stats = siena_start_nic_stats,
        .stop_stats = siena_stop_nic_stats,
index d49b53dc2a500a2602093a2df63daba5c5ad2538..6e62a018ea323239d7b2de7bd7ba505751ccffae 100644 (file)
@@ -695,8 +695,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
                return VFDI_RC_ENOMEM;
 
        rtnl_lock();
-       if (efx->fc_disable++ == 0)
-               efx_mcdi_set_mac(efx);
+       siena_prepare_flush(efx);
        rtnl_unlock();
 
        /* Flush all the initialized queues */
@@ -733,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
        }
 
        rtnl_lock();
-       if (--efx->fc_disable == 0)
-               efx_mcdi_set_mac(efx);
+       siena_finish_flush(efx);
        rtnl_unlock();
 
        /* Irrespective of success/failure, fini the queues */