aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2014-09-20 19:50:27 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-09-23 06:59:19 -0400
commit19ae1b3fb99c2d5a5a7540c296c4cb4df3e7f552 (patch)
tree2e65b54e0d55d4aede7c5749dbf612b7468cd889 /drivers/net/ethernet
parent82dd0f7ee9a3b6e5d861a7c550c738ec308d37c5 (diff)
fm10k: Add support for PCI power management and error handling
Add PCI power management and error handling to allow the device to support suspend/resume and recovery of any PCIe errors. The fm10k devices do not support wake on LAN, and there is no plan to add this as a feature. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 229c7e491251..b54c9e18cbdf 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -19,6 +19,7 @@
19 */ 19 */
20 20
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/aer.h>
22 23
23#include "fm10k.h" 24#include "fm10k.h"
24 25
@@ -1535,6 +1536,8 @@ static int fm10k_probe(struct pci_dev *pdev,
1535 goto err_pci_reg; 1536 goto err_pci_reg;
1536 } 1537 }
1537 1538
1539 pci_enable_pcie_error_reporting(pdev);
1540
1538 pci_set_master(pdev); 1541 pci_set_master(pdev);
1539 pci_save_state(pdev); 1542 pci_save_state(pdev);
1540 1543
@@ -1661,14 +1664,232 @@ static void fm10k_remove(struct pci_dev *pdev)
1661 pci_release_selected_regions(pdev, 1664 pci_release_selected_regions(pdev,
1662 pci_select_bars(pdev, IORESOURCE_MEM)); 1665 pci_select_bars(pdev, IORESOURCE_MEM));
1663 1666
1667 pci_disable_pcie_error_reporting(pdev);
1668
1664 pci_disable_device(pdev); 1669 pci_disable_device(pdev);
1665} 1670}
1666 1671
1672#ifdef CONFIG_PM
1673/**
1674 * fm10k_resume - Restore device to pre-sleep state
1675 * @pdev: PCI device information struct
1676 *
1677 * fm10k_resume is called after the system has powered back up from a sleep
1678 * state and is ready to resume operation. This function is meant to restore
1679 * the device back to its pre-sleep state.
1680 **/
1681static int fm10k_resume(struct pci_dev *pdev)
1682{
1683 struct fm10k_intfc *interface = pci_get_drvdata(pdev);
1684 struct net_device *netdev = interface->netdev;
1685 struct fm10k_hw *hw = &interface->hw;
1686 u32 err;
1687
1688 pci_set_power_state(pdev, PCI_D0);
1689 pci_restore_state(pdev);
1690
1691 /* pci_restore_state clears dev->state_saved so call
1692 * pci_save_state to restore it.
1693 */
1694 pci_save_state(pdev);
1695
1696 err = pci_enable_device_mem(pdev);
1697 if (err) {
1698 dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n");
1699 return err;
1700 }
1701 pci_set_master(pdev);
1702
1703 pci_wake_from_d3(pdev, false);
1704
1705 /* refresh hw_addr in case it was dropped */
1706 hw->hw_addr = interface->uc_addr;
1707
1708 /* reset hardware to known state */
1709 err = hw->mac.ops.init_hw(&interface->hw);
1710 if (err)
1711 return err;
1712
1713 /* reset statistics starting values */
1714 hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
1715
1716 rtnl_lock();
1717
1718 err = fm10k_init_queueing_scheme(interface);
1719 if (!err) {
1720 fm10k_mbx_request_irq(interface);
1721 if (netif_running(netdev))
1722 err = fm10k_open(netdev);
1723 }
1724
1725 rtnl_unlock();
1726
1727 if (err)
1728 return err;
1729
1730 netif_device_attach(netdev);
1731
1732 return 0;
1733}
1734
1735/**
1736 * fm10k_suspend - Prepare the device for a system sleep state
1737 * @pdev: PCI device information struct
1738 *
1739 * fm10k_suspend is meant to shutdown the device prior to the system entering
1740 * a sleep state. The fm10k hardware does not support wake on lan so the
1741 * driver simply needs to shut down the device so it is in a low power state.
1742 **/
1743static int fm10k_suspend(struct pci_dev *pdev, pm_message_t state)
1744{
1745 struct fm10k_intfc *interface = pci_get_drvdata(pdev);
1746 struct net_device *netdev = interface->netdev;
1747 int err = 0;
1748
1749 netif_device_detach(netdev);
1750
1751 rtnl_lock();
1752
1753 if (netif_running(netdev))
1754 fm10k_close(netdev);
1755
1756 fm10k_mbx_free_irq(interface);
1757
1758 fm10k_clear_queueing_scheme(interface);
1759
1760 rtnl_unlock();
1761
1762 err = pci_save_state(pdev);
1763 if (err)
1764 return err;
1765
1766 pci_disable_device(pdev);
1767 pci_wake_from_d3(pdev, false);
1768 pci_set_power_state(pdev, PCI_D3hot);
1769
1770 return 0;
1771}
1772
1773#endif /* CONFIG_PM */
1774/**
1775 * fm10k_io_error_detected - called when PCI error is detected
1776 * @pdev: Pointer to PCI device
1777 * @state: The current pci connection state
1778 *
1779 * This function is called after a PCI bus error affecting
1780 * this device has been detected.
1781 */
1782static pci_ers_result_t fm10k_io_error_detected(struct pci_dev *pdev,
1783 pci_channel_state_t state)
1784{
1785 struct fm10k_intfc *interface = pci_get_drvdata(pdev);
1786 struct net_device *netdev = interface->netdev;
1787
1788 netif_device_detach(netdev);
1789
1790 if (state == pci_channel_io_perm_failure)
1791 return PCI_ERS_RESULT_DISCONNECT;
1792
1793 if (netif_running(netdev))
1794 fm10k_close(netdev);
1795
1796 fm10k_mbx_free_irq(interface);
1797
1798 pci_disable_device(pdev);
1799
1800 /* Request a slot reset. */
1801 return PCI_ERS_RESULT_NEED_RESET;
1802}
1803
1804/**
1805 * fm10k_io_slot_reset - called after the pci bus has been reset.
1806 * @pdev: Pointer to PCI device
1807 *
1808 * Restart the card from scratch, as if from a cold-boot.
1809 */
1810static pci_ers_result_t fm10k_io_slot_reset(struct pci_dev *pdev)
1811{
1812 struct fm10k_intfc *interface = pci_get_drvdata(pdev);
1813 pci_ers_result_t result;
1814
1815 if (pci_enable_device_mem(pdev)) {
1816 dev_err(&pdev->dev,
1817 "Cannot re-enable PCI device after reset.\n");
1818 result = PCI_ERS_RESULT_DISCONNECT;
1819 } else {
1820 pci_set_master(pdev);
1821 pci_restore_state(pdev);
1822
1823 /* After second error pci->state_saved is false, this
1824 * resets it so EEH doesn't break.
1825 */
1826 pci_save_state(pdev);
1827
1828 pci_wake_from_d3(pdev, false);
1829
1830 /* refresh hw_addr in case it was dropped */
1831 interface->hw.hw_addr = interface->uc_addr;
1832
1833 interface->flags |= FM10K_FLAG_RESET_REQUESTED;
1834 fm10k_service_event_schedule(interface);
1835
1836 result = PCI_ERS_RESULT_RECOVERED;
1837 }
1838
1839 pci_cleanup_aer_uncorrect_error_status(pdev);
1840
1841 return result;
1842}
1843
1844/**
1845 * fm10k_io_resume - called when traffic can start flowing again.
1846 * @pdev: Pointer to PCI device
1847 *
1848 * This callback is called when the error recovery driver tells us that
1849 * its OK to resume normal operation.
1850 */
1851static void fm10k_io_resume(struct pci_dev *pdev)
1852{
1853 struct fm10k_intfc *interface = pci_get_drvdata(pdev);
1854 struct net_device *netdev = interface->netdev;
1855 struct fm10k_hw *hw = &interface->hw;
1856 int err = 0;
1857
1858 /* reset hardware to known state */
1859 hw->mac.ops.init_hw(&interface->hw);
1860
1861 /* reset statistics starting values */
1862 hw->mac.ops.rebind_hw_stats(hw, &interface->stats);
1863
1864 /* reassociate interrupts */
1865 fm10k_mbx_request_irq(interface);
1866
1867 if (netif_running(netdev))
1868 err = fm10k_open(netdev);
1869
1870 /* final check of hardware state before registering the interface */
1871 err = err ? : fm10k_hw_ready(interface);
1872
1873 if (!err)
1874 netif_device_attach(netdev);
1875}
1876
1877static const struct pci_error_handlers fm10k_err_handler = {
1878 .error_detected = fm10k_io_error_detected,
1879 .slot_reset = fm10k_io_slot_reset,
1880 .resume = fm10k_io_resume,
1881};
1882
1667static struct pci_driver fm10k_driver = { 1883static struct pci_driver fm10k_driver = {
1668 .name = fm10k_driver_name, 1884 .name = fm10k_driver_name,
1669 .id_table = fm10k_pci_tbl, 1885 .id_table = fm10k_pci_tbl,
1670 .probe = fm10k_probe, 1886 .probe = fm10k_probe,
1671 .remove = fm10k_remove, 1887 .remove = fm10k_remove,
1888#ifdef CONFIG_PM
1889 .suspend = fm10k_suspend,
1890 .resume = fm10k_resume,
1891#endif
1892 .err_handler = &fm10k_err_handler
1672}; 1893};
1673 1894
1674/** 1895/**