sfc: Cleanup reset code
[linux-2.6-block.git] / drivers / net / sfc / efx.c
index be9382faf19df7371b90afe3a5bf2418b9a03402..f34dbf2c5b69376dbbe752de27c9b68888eb556b 100644 (file)
@@ -282,13 +282,13 @@ static int efx_probe_eventq(struct efx_channel *channel)
 }
 
 /* Prepare channel's event queue */
-static int efx_init_eventq(struct efx_channel *channel)
+static void efx_init_eventq(struct efx_channel *channel)
 {
        EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel);
 
        channel->eventq_read_ptr = 0;
 
-       return falcon_init_eventq(channel);
+       falcon_init_eventq(channel);
 }
 
 static void efx_fini_eventq(struct efx_channel *channel)
@@ -354,12 +354,11 @@ static int efx_probe_channel(struct efx_channel *channel)
  * to propagate configuration changes (mtu, checksum offload), or
  * to clear hardware error conditions
  */
-static int efx_init_channels(struct efx_nic *efx)
+static void efx_init_channels(struct efx_nic *efx)
 {
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
        struct efx_channel *channel;
-       int rc = 0;
 
        /* Calculate the rx buffer allocation parameters required to
         * support the current MTU, including padding for header
@@ -374,36 +373,20 @@ static int efx_init_channels(struct efx_nic *efx)
        efx_for_each_channel(channel, efx) {
                EFX_LOG(channel->efx, "init chan %d\n", channel->channel);
 
-               rc = efx_init_eventq(channel);
-               if (rc)
-                       goto err;
+               efx_init_eventq(channel);
 
-               efx_for_each_channel_tx_queue(tx_queue, channel) {
-                       rc = efx_init_tx_queue(tx_queue);
-                       if (rc)
-                               goto err;
-               }
+               efx_for_each_channel_tx_queue(tx_queue, channel)
+                       efx_init_tx_queue(tx_queue);
 
                /* The rx buffer allocation strategy is MTU dependent */
                efx_rx_strategy(channel);
 
-               efx_for_each_channel_rx_queue(rx_queue, channel) {
-                       rc = efx_init_rx_queue(rx_queue);
-                       if (rc)
-                               goto err;
-               }
+               efx_for_each_channel_rx_queue(rx_queue, channel)
+                       efx_init_rx_queue(rx_queue);
 
                WARN_ON(channel->rx_pkt != NULL);
                efx_rx_strategy(channel);
        }
-
-       return 0;
-
- err:
-       EFX_ERR(efx, "failed to initialise channel %d\n",
-               channel ? channel->channel : -1);
-       efx_fini_channels(efx);
-       return rc;
 }
 
 /* This enables event queue processing and packet transmission.
@@ -1121,24 +1104,16 @@ static void efx_remove_all(struct efx_nic *efx)
 }
 
 /* A convinience function to safely flush all the queues */
-int efx_flush_queues(struct efx_nic *efx)
+void efx_flush_queues(struct efx_nic *efx)
 {
-       int rc;
-
        EFX_ASSERT_RESET_SERIALISED(efx);
 
        efx_stop_all(efx);
 
        efx_fini_channels(efx);
-       rc = efx_init_channels(efx);
-       if (rc) {
-               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
-               return rc;
-       }
+       efx_init_channels(efx);
 
        efx_start_all(efx);
-
-       return 0;
 }
 
 /**************************************************************************
@@ -1311,7 +1286,6 @@ static int efx_net_open(struct net_device *net_dev)
 static int efx_net_stop(struct net_device *net_dev)
 {
        struct efx_nic *efx = netdev_priv(net_dev);
-       int rc;
 
        EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
                raw_smp_processor_id());
@@ -1319,9 +1293,7 @@ static int efx_net_stop(struct net_device *net_dev)
        /* Stop the device and flush all the channels */
        efx_stop_all(efx);
        efx_fini_channels(efx);
-       rc = efx_init_channels(efx);
-       if (rc)
-               efx_schedule_reset(efx, RESET_TYPE_DISABLE);
+       efx_init_channels(efx);
 
        return 0;
 }
@@ -1404,16 +1376,10 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
 
        efx_fini_channels(efx);
        net_dev->mtu = new_mtu;
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail;
+       efx_init_channels(efx);
 
        efx_start_all(efx);
        return rc;
-
- fail:
-       efx_schedule_reset(efx, RESET_TYPE_DISABLE);
-       return rc;
 }
 
 static int efx_set_mac_address(struct net_device *net_dev, void *data)
@@ -1561,49 +1527,58 @@ static void efx_unregister_netdev(struct efx_nic *efx)
  *
  **************************************************************************/
 
-/* The final hardware and software finalisation before reset. */
-static int efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* Tears down the entire software state and most of the hardware state
+ * before reset.  */
+static void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
 {
        int rc;
 
        EFX_ASSERT_RESET_SERIALISED(efx);
 
+       /* The net_dev->get_stats handler is quite slow, and will fail
+        * if a fetch is pending over reset. Serialise against it. */
+       spin_lock(&efx->stats_lock);
+       spin_unlock(&efx->stats_lock);
+
+       efx_stop_all(efx);
+       mutex_lock(&efx->mac_lock);
+
        rc = falcon_xmac_get_settings(efx, ecmd);
-       if (rc) {
+       if (rc)
                EFX_ERR(efx, "could not back up PHY settings\n");
-               goto fail;
-       }
 
        efx_fini_channels(efx);
-       return 0;
-
- fail:
-       return rc;
 }
 
-/* The first part of software initialisation after a hardware reset
- * This function does not handle serialisation with the kernel, it
- * assumes the caller has done this */
-static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+/* This function will always ensure that the locks acquired in
+ * efx_reset_down() are released. A failure return code indicates
+ * that we were unable to reinitialise the hardware, and the
+ * driver should be disabled. If ok is false, then the rx and tx
+ * engines are not restarted, pending a RESET_DISABLE. */
+static int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd,
+                       bool ok)
 {
        int rc;
 
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail1;
+       EFX_ASSERT_RESET_SERIALISED(efx);
 
-       /* Restore MAC and PHY settings. */
-       rc = falcon_xmac_set_settings(efx, ecmd);
+       rc = falcon_init_nic(efx);
        if (rc) {
-               EFX_ERR(efx, "could not restore PHY settings\n");
-               goto fail2;
+               EFX_ERR(efx, "failed to initialise NIC\n");
+               ok = false;
        }
 
-       return 0;
+       if (ok) {
+               efx_init_channels(efx);
 
- fail2:
-       efx_fini_channels(efx);
- fail1:
+               if (falcon_xmac_set_settings(efx, ecmd))
+                       EFX_ERR(efx, "could not restore PHY settings\n");
+       }
+
+       mutex_unlock(&efx->mac_lock);
+
+       if (ok)
+               efx_start_all(efx);
        return rc;
 }
 
@@ -1635,22 +1610,12 @@ static int efx_reset(struct efx_nic *efx)
        efx->state = STATE_RESETTING;
        EFX_INFO(efx, "resetting (%d)\n", method);
 
-       /* The net_dev->get_stats handler is quite slow, and will fail
-        * if a fetch is pending over reset. Serialise against it. */
-       spin_lock(&efx->stats_lock);
-       spin_unlock(&efx->stats_lock);
-
-       efx_stop_all(efx);
-       mutex_lock(&efx->mac_lock);
-
-       rc = efx_reset_down(efx, &ecmd);
-       if (rc)
-               goto fail1;
+       efx_reset_down(efx, &ecmd);
 
        rc = falcon_reset_hw(efx, method);
        if (rc) {
                EFX_ERR(efx, "failed to reset hardware\n");
-               goto fail2;
+               goto fail;
        }
 
        /* Allow resets to be rescheduled. */
@@ -1662,46 +1627,28 @@ static int efx_reset(struct efx_nic *efx)
         * can respond to requests. */
        pci_set_master(efx->pci_dev);
 
-       /* Reinitialise device. This is appropriate in the RESET_TYPE_DISABLE
-        * case so the driver can talk to external SRAM */
-       rc = falcon_init_nic(efx);
-       if (rc) {
-               EFX_ERR(efx, "failed to initialise NIC\n");
-               goto fail3;
-       }
-
        /* Leave device stopped if necessary */
        if (method == RESET_TYPE_DISABLE) {
-               /* Reinitialise the device anyway so the driver unload sequence
-                * can talk to the external SRAM */
-               falcon_init_nic(efx);
                rc = -EIO;
-               goto fail4;
+               goto fail;
        }
 
-       rc = efx_reset_up(efx, &ecmd);
+       rc = efx_reset_up(efx, &ecmd, true);
        if (rc)
-               goto fail5;
+               goto disable;
 
-       mutex_unlock(&efx->mac_lock);
        EFX_LOG(efx, "reset complete\n");
-
        efx->state = STATE_RUNNING;
-       efx_start_all(efx);
-
  unlock_rtnl:
        rtnl_unlock();
        return 0;
 
- fail5:
- fail4:
- fail3:
- fail2:
- fail1:
+ fail:
+       efx_reset_up(efx, &ecmd, false);
+ disable:
        EFX_ERR(efx, "has been disabled\n");
        efx->state = STATE_DISABLED;
 
-       mutex_unlock(&efx->mac_lock);
        rtnl_unlock();
        efx_unregister_netdev(efx);
        efx_fini_port(efx);
@@ -1774,7 +1721,7 @@ static struct pci_device_id efx_pci_table[] __devinitdata = {
  *
  * Dummy PHY/MAC/Board operations
  *
- * Can be used where the MAC does not implement this operation
+ * Can be used for some unimplemented operations
  * Needed so all function pointers are valid and do not have to be tested
  * before use
  *
@@ -1795,17 +1742,12 @@ static struct efx_phy_operations efx_dummy_phy_operations = {
        .reset_xaui      = efx_port_dummy_op_void,
 };
 
-/* Dummy board operations */
-static int efx_nic_dummy_op_int(struct efx_nic *nic)
-{
-       return 0;
-}
-
 static struct efx_board efx_dummy_board_info = {
-       .init    = efx_nic_dummy_op_int,
-       .init_leds = efx_port_dummy_op_int,
-       .set_fault_led = efx_port_dummy_op_blink,
-       .fini   = efx_port_dummy_op_void,
+       .init           = efx_port_dummy_op_int,
+       .init_leds      = efx_port_dummy_op_int,
+       .set_fault_led  = efx_port_dummy_op_blink,
+       .blink          = efx_port_dummy_op_blink,
+       .fini           = efx_port_dummy_op_void,
 };
 
 /**************************************************************************
@@ -2028,19 +1970,16 @@ static int efx_pci_probe_main(struct efx_nic *efx)
                goto fail5;
        }
 
-       rc = efx_init_channels(efx);
-       if (rc)
-               goto fail6;
+       efx_init_channels(efx);
 
        rc = falcon_init_interrupt(efx);
        if (rc)
-               goto fail7;
+               goto fail6;
 
        return 0;
 
- fail7:
-       efx_fini_channels(efx);
  fail6:
+       efx_fini_channels(efx);
        efx_fini_port(efx);
  fail5:
  fail4:
@@ -2079,7 +2018,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
                net_dev->features |= NETIF_F_LRO;
        /* Mask for features that also apply to VLAN devices */
        net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG |
-                                  NETIF_F_HIGHDMA);
+                                  NETIF_F_HIGHDMA | NETIF_F_TSO);
        efx = netdev_priv(net_dev);
        pci_set_drvdata(pci_dev, efx);
        rc = efx_init_struct(efx, type, pci_dev, net_dev);