diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2011-07-15 03:29:55 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-09-16 00:32:04 -0400 |
commit | 2c4af694fe1723501e19426d0d891bdae9194c71 (patch) | |
tree | 09b99448a6d22b2b9fa517be4594afb2879103c6 | |
parent | 8e34d1aacc942586f39f91c0707d5bc7bc2532bb (diff) |
ixgbe: Correctly name and handle MSI-X other interrupt
It was possible to inadvertently add additional interrupt causes to the
MSI-X other interrupt. This occurred when things such as RX buffer overrun
events were being triggered at the same time as an event such as a Flow
Director table reinit request. In order to avoid this we should be
explicitly programming only the interrupts that we want enabled. In
addition I am renaming the ixgbe_msix_lsc function and interrupt to drop
any implied meaning of this being a link status only interrupt.
Unfortunately the patch is a bit ugly due to the fact that ixgbe_irq_enable
needed to be moved up before ixgbe_msix_other in order to have things
defined in the correct order.
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 191 |
2 files changed, 97 insertions, 95 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 3f5a744f7099..bfdd42b7f985 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
@@ -491,7 +491,6 @@ struct ixgbe_adapter { | |||
491 | int node; | 491 | int node; |
492 | u32 led_reg; | 492 | u32 led_reg; |
493 | u32 interrupt_event; | 493 | u32 interrupt_event; |
494 | char lsc_int_name[IFNAMSIZ + 9]; | ||
495 | 494 | ||
496 | /* SR-IOV */ | 495 | /* SR-IOV */ |
497 | DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); | 496 | DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 0ee7d094ff89..6026ab0798e9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -1828,7 +1828,98 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) | |||
1828 | } | 1828 | } |
1829 | } | 1829 | } |
1830 | 1830 | ||
1831 | static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | 1831 | static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, |
1832 | u64 qmask) | ||
1833 | { | ||
1834 | u32 mask; | ||
1835 | struct ixgbe_hw *hw = &adapter->hw; | ||
1836 | |||
1837 | switch (hw->mac.type) { | ||
1838 | case ixgbe_mac_82598EB: | ||
1839 | mask = (IXGBE_EIMS_RTX_QUEUE & qmask); | ||
1840 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | ||
1841 | break; | ||
1842 | case ixgbe_mac_82599EB: | ||
1843 | case ixgbe_mac_X540: | ||
1844 | mask = (qmask & 0xFFFFFFFF); | ||
1845 | if (mask) | ||
1846 | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); | ||
1847 | mask = (qmask >> 32); | ||
1848 | if (mask) | ||
1849 | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); | ||
1850 | break; | ||
1851 | default: | ||
1852 | break; | ||
1853 | } | ||
1854 | /* skip the flush */ | ||
1855 | } | ||
1856 | |||
1857 | static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, | ||
1858 | u64 qmask) | ||
1859 | { | ||
1860 | u32 mask; | ||
1861 | struct ixgbe_hw *hw = &adapter->hw; | ||
1862 | |||
1863 | switch (hw->mac.type) { | ||
1864 | case ixgbe_mac_82598EB: | ||
1865 | mask = (IXGBE_EIMS_RTX_QUEUE & qmask); | ||
1866 | IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); | ||
1867 | break; | ||
1868 | case ixgbe_mac_82599EB: | ||
1869 | case ixgbe_mac_X540: | ||
1870 | mask = (qmask & 0xFFFFFFFF); | ||
1871 | if (mask) | ||
1872 | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); | ||
1873 | mask = (qmask >> 32); | ||
1874 | if (mask) | ||
1875 | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); | ||
1876 | break; | ||
1877 | default: | ||
1878 | break; | ||
1879 | } | ||
1880 | /* skip the flush */ | ||
1881 | } | ||
1882 | |||
1883 | /** | ||
1884 | * ixgbe_irq_enable - Enable default interrupt generation settings | ||
1885 | * @adapter: board private structure | ||
1886 | **/ | ||
1887 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, | ||
1888 | bool flush) | ||
1889 | { | ||
1890 | u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | ||
1891 | |||
1892 | /* don't reenable LSC while waiting for link */ | ||
1893 | if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) | ||
1894 | mask &= ~IXGBE_EIMS_LSC; | ||
1895 | |||
1896 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) | ||
1897 | mask |= IXGBE_EIMS_GPI_SDP0; | ||
1898 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) | ||
1899 | mask |= IXGBE_EIMS_GPI_SDP1; | ||
1900 | switch (adapter->hw.mac.type) { | ||
1901 | case ixgbe_mac_82599EB: | ||
1902 | case ixgbe_mac_X540: | ||
1903 | mask |= IXGBE_EIMS_ECC; | ||
1904 | mask |= IXGBE_EIMS_GPI_SDP1; | ||
1905 | mask |= IXGBE_EIMS_GPI_SDP2; | ||
1906 | mask |= IXGBE_EIMS_MAILBOX; | ||
1907 | break; | ||
1908 | default: | ||
1909 | break; | ||
1910 | } | ||
1911 | if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && | ||
1912 | !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) | ||
1913 | mask |= IXGBE_EIMS_FLOW_DIR; | ||
1914 | |||
1915 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); | ||
1916 | if (queues) | ||
1917 | ixgbe_irq_enable_queues(adapter, ~0); | ||
1918 | if (flush) | ||
1919 | IXGBE_WRITE_FLUSH(&adapter->hw); | ||
1920 | } | ||
1921 | |||
1922 | static irqreturn_t ixgbe_msix_other(int irq, void *data) | ||
1832 | { | 1923 | { |
1833 | struct ixgbe_adapter *adapter = data; | 1924 | struct ixgbe_adapter *adapter = data; |
1834 | struct ixgbe_hw *hw = &adapter->hw; | 1925 | struct ixgbe_hw *hw = &adapter->hw; |
@@ -1852,6 +1943,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
1852 | switch (hw->mac.type) { | 1943 | switch (hw->mac.type) { |
1853 | case ixgbe_mac_82599EB: | 1944 | case ixgbe_mac_82599EB: |
1854 | case ixgbe_mac_X540: | 1945 | case ixgbe_mac_X540: |
1946 | if (eicr & IXGBE_EICR_ECC) | ||
1947 | e_info(link, "Received unrecoverable ECC Err, please " | ||
1948 | "reboot\n"); | ||
1855 | /* Handle Flow Director Full threshold interrupt */ | 1949 | /* Handle Flow Director Full threshold interrupt */ |
1856 | if (eicr & IXGBE_EICR_FLOW_DIR) { | 1950 | if (eicr & IXGBE_EICR_FLOW_DIR) { |
1857 | int reinit_count = 0; | 1951 | int reinit_count = 0; |
@@ -1865,7 +1959,6 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
1865 | if (reinit_count) { | 1959 | if (reinit_count) { |
1866 | /* no more flow director interrupts until after init */ | 1960 | /* no more flow director interrupts until after init */ |
1867 | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR); | 1961 | IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR); |
1868 | eicr &= ~IXGBE_EICR_FLOW_DIR; | ||
1869 | adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT; | 1962 | adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT; |
1870 | ixgbe_service_event_schedule(adapter); | 1963 | ixgbe_service_event_schedule(adapter); |
1871 | } | 1964 | } |
@@ -1888,64 +1981,11 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
1888 | 1981 | ||
1889 | /* re-enable the original interrupt state, no lsc, no queues */ | 1982 | /* re-enable the original interrupt state, no lsc, no queues */ |
1890 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 1983 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1891 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr & | 1984 | ixgbe_irq_enable(adapter, false, false); |
1892 | ~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE)); | ||
1893 | 1985 | ||
1894 | return IRQ_HANDLED; | 1986 | return IRQ_HANDLED; |
1895 | } | 1987 | } |
1896 | 1988 | ||
1897 | static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, | ||
1898 | u64 qmask) | ||
1899 | { | ||
1900 | u32 mask; | ||
1901 | struct ixgbe_hw *hw = &adapter->hw; | ||
1902 | |||
1903 | switch (hw->mac.type) { | ||
1904 | case ixgbe_mac_82598EB: | ||
1905 | mask = (IXGBE_EIMS_RTX_QUEUE & qmask); | ||
1906 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask); | ||
1907 | break; | ||
1908 | case ixgbe_mac_82599EB: | ||
1909 | case ixgbe_mac_X540: | ||
1910 | mask = (qmask & 0xFFFFFFFF); | ||
1911 | if (mask) | ||
1912 | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask); | ||
1913 | mask = (qmask >> 32); | ||
1914 | if (mask) | ||
1915 | IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask); | ||
1916 | break; | ||
1917 | default: | ||
1918 | break; | ||
1919 | } | ||
1920 | /* skip the flush */ | ||
1921 | } | ||
1922 | |||
1923 | static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, | ||
1924 | u64 qmask) | ||
1925 | { | ||
1926 | u32 mask; | ||
1927 | struct ixgbe_hw *hw = &adapter->hw; | ||
1928 | |||
1929 | switch (hw->mac.type) { | ||
1930 | case ixgbe_mac_82598EB: | ||
1931 | mask = (IXGBE_EIMS_RTX_QUEUE & qmask); | ||
1932 | IXGBE_WRITE_REG(hw, IXGBE_EIMC, mask); | ||
1933 | break; | ||
1934 | case ixgbe_mac_82599EB: | ||
1935 | case ixgbe_mac_X540: | ||
1936 | mask = (qmask & 0xFFFFFFFF); | ||
1937 | if (mask) | ||
1938 | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(0), mask); | ||
1939 | mask = (qmask >> 32); | ||
1940 | if (mask) | ||
1941 | IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask); | ||
1942 | break; | ||
1943 | default: | ||
1944 | break; | ||
1945 | } | ||
1946 | /* skip the flush */ | ||
1947 | } | ||
1948 | |||
1949 | static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data) | 1989 | static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data) |
1950 | { | 1990 | { |
1951 | struct ixgbe_q_vector *q_vector = data; | 1991 | struct ixgbe_q_vector *q_vector = data; |
@@ -2077,9 +2117,8 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) | |||
2077 | } | 2117 | } |
2078 | } | 2118 | } |
2079 | 2119 | ||
2080 | sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name); | ||
2081 | err = request_irq(adapter->msix_entries[vector].vector, | 2120 | err = request_irq(adapter->msix_entries[vector].vector, |
2082 | ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter); | 2121 | ixgbe_msix_other, 0, netdev->name, adapter); |
2083 | if (err) { | 2122 | if (err) { |
2084 | e_err(probe, "request_irq for msix_lsc failed: %d\n", err); | 2123 | e_err(probe, "request_irq for msix_lsc failed: %d\n", err); |
2085 | goto free_queue_irqs; | 2124 | goto free_queue_irqs; |
@@ -2103,42 +2142,6 @@ free_queue_irqs: | |||
2103 | } | 2142 | } |
2104 | 2143 | ||
2105 | /** | 2144 | /** |
2106 | * ixgbe_irq_enable - Enable default interrupt generation settings | ||
2107 | * @adapter: board private structure | ||
2108 | **/ | ||
2109 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, | ||
2110 | bool flush) | ||
2111 | { | ||
2112 | u32 mask; | ||
2113 | |||
2114 | mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | ||
2115 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) | ||
2116 | mask |= IXGBE_EIMS_GPI_SDP0; | ||
2117 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) | ||
2118 | mask |= IXGBE_EIMS_GPI_SDP1; | ||
2119 | switch (adapter->hw.mac.type) { | ||
2120 | case ixgbe_mac_82599EB: | ||
2121 | case ixgbe_mac_X540: | ||
2122 | mask |= IXGBE_EIMS_ECC; | ||
2123 | mask |= IXGBE_EIMS_GPI_SDP1; | ||
2124 | mask |= IXGBE_EIMS_GPI_SDP2; | ||
2125 | if (adapter->num_vfs) | ||
2126 | mask |= IXGBE_EIMS_MAILBOX; | ||
2127 | break; | ||
2128 | default: | ||
2129 | break; | ||
2130 | } | ||
2131 | if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) | ||
2132 | mask |= IXGBE_EIMS_FLOW_DIR; | ||
2133 | |||
2134 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); | ||
2135 | if (queues) | ||
2136 | ixgbe_irq_enable_queues(adapter, ~0); | ||
2137 | if (flush) | ||
2138 | IXGBE_WRITE_FLUSH(&adapter->hw); | ||
2139 | } | ||
2140 | |||
2141 | /** | ||
2142 | * ixgbe_intr - legacy mode Interrupt Handler | 2145 | * ixgbe_intr - legacy mode Interrupt Handler |
2143 | * @irq: interrupt number | 2146 | * @irq: interrupt number |
2144 | * @data: pointer to a network interface device structure | 2147 | * @data: pointer to a network interface device structure |