aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/efx.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2009-11-28 22:43:15 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-29 19:46:29 -0500
commiteb9f6744cbfa97674c13263802259b5aa0034594 (patch)
treeae57310bc8fd9b7b21e6d6ca63853bcae002a5c2 /drivers/net/sfc/efx.c
parent89c758fa47b54d8ce10d2b39ed09de6da0ba4324 (diff)
sfc: Implement ethtool reset operation
Refactor efx_reset_down() and efx_reset_up() accordingly. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r--drivers/net/sfc/efx.c98
1 files changed, 48 insertions, 50 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index b016719d8f67..4b7168fc546a 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1754,58 +1754,49 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
1754 rc = efx->type->init(efx); 1754 rc = efx->type->init(efx);
1755 if (rc) { 1755 if (rc) {
1756 EFX_ERR(efx, "failed to initialise NIC\n"); 1756 EFX_ERR(efx, "failed to initialise NIC\n");
1757 ok = false; 1757 goto fail;
1758 } 1758 }
1759 1759
1760 if (!ok)
1761 goto fail;
1762
1760 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { 1763 if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
1761 if (ok) { 1764 rc = efx->phy_op->init(efx);
1762 rc = efx->phy_op->init(efx); 1765 if (rc)
1763 if (rc) 1766 goto fail;
1764 ok = false; 1767 if (efx->phy_op->reconfigure(efx))
1765 if (efx->phy_op->reconfigure(efx)) 1768 EFX_ERR(efx, "could not restore PHY settings\n");
1766 EFX_ERR(efx, "could not restore PHY settings\n");
1767 }
1768 if (!ok)
1769 efx->port_initialized = false;
1770 } 1769 }
1771 1770
1772 if (ok) { 1771 efx->mac_op->reconfigure(efx);
1773 efx->mac_op->reconfigure(efx);
1774 1772
1775 efx_init_channels(efx); 1773 efx_init_channels(efx);
1776 } 1774
1775 mutex_unlock(&efx->spi_lock);
1776 mutex_unlock(&efx->mac_lock);
1777
1778 efx_start_all(efx);
1779
1780 return 0;
1781
1782fail:
1783 efx->port_initialized = false;
1777 1784
1778 mutex_unlock(&efx->spi_lock); 1785 mutex_unlock(&efx->spi_lock);
1779 mutex_unlock(&efx->mac_lock); 1786 mutex_unlock(&efx->mac_lock);
1780 1787
1781 if (ok)
1782 efx_start_all(efx);
1783 return rc; 1788 return rc;
1784} 1789}
1785 1790
1786/* Reset the NIC as transparently as possible. Do not reset the PHY 1791/* Reset the NIC using the specified method. Note that the reset may
1787 * Note that the reset may fail, in which case the card will be left 1792 * fail, in which case the card will be left in an unusable state.
1788 * in a most-probably-unusable state.
1789 *
1790 * This function will sleep. You cannot reset from within an atomic
1791 * state; use efx_schedule_reset() instead.
1792 * 1793 *
1793 * Grabs the rtnl_lock. 1794 * Caller must hold the rtnl_lock.
1794 */ 1795 */
1795static int efx_reset(struct efx_nic *efx) 1796int efx_reset(struct efx_nic *efx, enum reset_type method)
1796{ 1797{
1797 enum reset_type method = efx->reset_pending; 1798 int rc, rc2;
1798 int rc = 0; 1799 bool disabled;
1799
1800 /* Serialise with kernel interfaces */
1801 rtnl_lock();
1802
1803 /* If we're not RUNNING then don't reset. Leave the reset_pending
1804 * flag set so that efx_pci_probe_main will be retried */
1805 if (efx->state != STATE_RUNNING) {
1806 EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
1807 goto out_unlock;
1808 }
1809 1800
1810 EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method)); 1801 EFX_INFO(efx, "resetting (%s)\n", RESET_TYPE(method));
1811 1802
@@ -1814,7 +1805,7 @@ static int efx_reset(struct efx_nic *efx)
1814 rc = efx->type->reset(efx, method); 1805 rc = efx->type->reset(efx, method);
1815 if (rc) { 1806 if (rc) {
1816 EFX_ERR(efx, "failed to reset hardware\n"); 1807 EFX_ERR(efx, "failed to reset hardware\n");
1817 goto out_disable; 1808 goto out;
1818 } 1809 }
1819 1810
1820 /* Allow resets to be rescheduled. */ 1811 /* Allow resets to be rescheduled. */
@@ -1826,25 +1817,22 @@ static int efx_reset(struct efx_nic *efx)
1826 * can respond to requests. */ 1817 * can respond to requests. */
1827 pci_set_master(efx->pci_dev); 1818 pci_set_master(efx->pci_dev);
1828 1819
1820out:
1829 /* Leave device stopped if necessary */ 1821 /* Leave device stopped if necessary */
1830 if (method == RESET_TYPE_DISABLE) { 1822 disabled = rc || method == RESET_TYPE_DISABLE;
1831 efx_reset_up(efx, method, false); 1823 rc2 = efx_reset_up(efx, method, !disabled);
1832 rc = -EIO; 1824 if (rc2) {
1833 } else { 1825 disabled = true;
1834 rc = efx_reset_up(efx, method, true); 1826 if (!rc)
1827 rc = rc2;
1835 } 1828 }
1836 1829
1837out_disable: 1830 if (disabled) {
1838 if (rc) {
1839 EFX_ERR(efx, "has been disabled\n"); 1831 EFX_ERR(efx, "has been disabled\n");
1840 efx->state = STATE_DISABLED; 1832 efx->state = STATE_DISABLED;
1841 dev_close(efx->net_dev);
1842 } else { 1833 } else {
1843 EFX_LOG(efx, "reset complete\n"); 1834 EFX_LOG(efx, "reset complete\n");
1844 } 1835 }
1845
1846out_unlock:
1847 rtnl_unlock();
1848 return rc; 1836 return rc;
1849} 1837}
1850 1838
@@ -1853,9 +1841,19 @@ out_unlock:
1853 */ 1841 */
1854static void efx_reset_work(struct work_struct *data) 1842static void efx_reset_work(struct work_struct *data)
1855{ 1843{
1856 struct efx_nic *nic = container_of(data, struct efx_nic, reset_work); 1844 struct efx_nic *efx = container_of(data, struct efx_nic, reset_work);
1857 1845
1858 efx_reset(nic); 1846 /* If we're not RUNNING then don't reset. Leave the reset_pending
1847 * flag set so that efx_pci_probe_main will be retried */
1848 if (efx->state != STATE_RUNNING) {
1849 EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
1850 return;
1851 }
1852
1853 rtnl_lock();
1854 if (efx_reset(efx, efx->reset_pending))
1855 dev_close(efx->net_dev);
1856 rtnl_unlock();
1859} 1857}
1860 1858
1861void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) 1859void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)