diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-15 17:29:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-15 17:29:00 -0400 |
commit | 6b9107d6a10b69cc0a675447bde9383dff8a1d4f (patch) | |
tree | ce579f705e65eebb447204c3e8c3166ade049ed1 /drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | |
parent | 074975d0374333f656c48487aa046a21a9b9d7a1 (diff) | |
parent | 2aea6dcb7864e174dada15728c43c5330637d424 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue
Jeff Kirsher says:
====================
Intel Wired LAN Driver Updates 2015-04-14
This series contains updates to i40e and i40evf.
Mitch provides a fix for i40e, where VFs were gone and the associated
VSI's had been removed and the rings were not stopped, which in some
circumstances cased memory corruption or DMAR errors. So stop all the
rings associated with each VF before releasing its resources. Also
cleaned up a poorly indented piece of code. Fixes VF link state, where
VF devices were assuming link is up unless told otherwise, which means
that VFs instantiated on a PF with no link, would report the wrong state.
Anjali adds support to add Flow director Sideband rules for a VF from it's
PF. Fixes a recently discovered hardware issue, where after a VFLR
hardware might be indicating to us a reset completion little too early, so
wait another 10 msec for cache to be cleaned up.
Jesse enables the user to dump the internal hardware state for better
debugging by allowing a bash script to acquire information about the
internal hardware state. The data output to the kernel log is collected
by the script and can then be sent to Intel. Also fixed a possible
failure path to allocate memory that was found by smatch. Cleaned up
unused local variables.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 244 |
1 files changed, 132 insertions, 112 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 4d69e1f04901..78d1c4ff565e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | |||
@@ -26,6 +26,129 @@ | |||
26 | 26 | ||
27 | #include "i40e.h" | 27 | #include "i40e.h" |
28 | 28 | ||
29 | /*********************notification routines***********************/ | ||
30 | |||
31 | /** | ||
32 | * i40e_vc_vf_broadcast | ||
33 | * @pf: pointer to the PF structure | ||
34 | * @opcode: operation code | ||
35 | * @retval: return value | ||
36 | * @msg: pointer to the msg buffer | ||
37 | * @msglen: msg length | ||
38 | * | ||
39 | * send a message to all VFs on a given PF | ||
40 | **/ | ||
41 | static void i40e_vc_vf_broadcast(struct i40e_pf *pf, | ||
42 | enum i40e_virtchnl_ops v_opcode, | ||
43 | i40e_status v_retval, u8 *msg, | ||
44 | u16 msglen) | ||
45 | { | ||
46 | struct i40e_hw *hw = &pf->hw; | ||
47 | struct i40e_vf *vf = pf->vf; | ||
48 | int i; | ||
49 | |||
50 | for (i = 0; i < pf->num_alloc_vfs; i++, vf++) { | ||
51 | int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; | ||
52 | /* Not all vfs are enabled so skip the ones that are not */ | ||
53 | if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) && | ||
54 | !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) | ||
55 | continue; | ||
56 | |||
57 | /* Ignore return value on purpose - a given VF may fail, but | ||
58 | * we need to keep going and send to all of them | ||
59 | */ | ||
60 | i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval, | ||
61 | msg, msglen, NULL); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * i40e_vc_notify_link_state | ||
67 | * @vf: pointer to the VF structure | ||
68 | * | ||
69 | * send a link status message to a single VF | ||
70 | **/ | ||
71 | static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf) | ||
72 | { | ||
73 | struct i40e_virtchnl_pf_event pfe; | ||
74 | struct i40e_pf *pf = vf->pf; | ||
75 | struct i40e_hw *hw = &pf->hw; | ||
76 | struct i40e_link_status *ls = &pf->hw.phy.link_info; | ||
77 | int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; | ||
78 | |||
79 | pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE; | ||
80 | pfe.severity = I40E_PF_EVENT_SEVERITY_INFO; | ||
81 | if (vf->link_forced) { | ||
82 | pfe.event_data.link_event.link_status = vf->link_up; | ||
83 | pfe.event_data.link_event.link_speed = | ||
84 | (vf->link_up ? I40E_LINK_SPEED_40GB : 0); | ||
85 | } else { | ||
86 | pfe.event_data.link_event.link_status = | ||
87 | ls->link_info & I40E_AQ_LINK_UP; | ||
88 | pfe.event_data.link_event.link_speed = ls->link_speed; | ||
89 | } | ||
90 | i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT, | ||
91 | 0, (u8 *)&pfe, sizeof(pfe), NULL); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * i40e_vc_notify_link_state | ||
96 | * @pf: pointer to the PF structure | ||
97 | * | ||
98 | * send a link status message to all VFs on a given PF | ||
99 | **/ | ||
100 | void i40e_vc_notify_link_state(struct i40e_pf *pf) | ||
101 | { | ||
102 | int i; | ||
103 | |||
104 | for (i = 0; i < pf->num_alloc_vfs; i++) | ||
105 | i40e_vc_notify_vf_link_state(&pf->vf[i]); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * i40e_vc_notify_reset | ||
110 | * @pf: pointer to the PF structure | ||
111 | * | ||
112 | * indicate a pending reset to all VFs on a given PF | ||
113 | **/ | ||
114 | void i40e_vc_notify_reset(struct i40e_pf *pf) | ||
115 | { | ||
116 | struct i40e_virtchnl_pf_event pfe; | ||
117 | |||
118 | pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING; | ||
119 | pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM; | ||
120 | i40e_vc_vf_broadcast(pf, I40E_VIRTCHNL_OP_EVENT, 0, | ||
121 | (u8 *)&pfe, sizeof(struct i40e_virtchnl_pf_event)); | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * i40e_vc_notify_vf_reset | ||
126 | * @vf: pointer to the VF structure | ||
127 | * | ||
128 | * indicate a pending reset to the given VF | ||
129 | **/ | ||
130 | void i40e_vc_notify_vf_reset(struct i40e_vf *vf) | ||
131 | { | ||
132 | struct i40e_virtchnl_pf_event pfe; | ||
133 | int abs_vf_id; | ||
134 | |||
135 | /* validate the request */ | ||
136 | if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs) | ||
137 | return; | ||
138 | |||
139 | /* verify if the VF is in either init or active before proceeding */ | ||
140 | if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) && | ||
141 | !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) | ||
142 | return; | ||
143 | |||
144 | abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id; | ||
145 | |||
146 | pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING; | ||
147 | pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM; | ||
148 | i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT, | ||
149 | 0, (u8 *)&pfe, | ||
150 | sizeof(struct i40e_virtchnl_pf_event), NULL); | ||
151 | } | ||
29 | /***********************misc routines*****************************/ | 152 | /***********************misc routines*****************************/ |
30 | 153 | ||
31 | /** | 154 | /** |
@@ -689,6 +812,9 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) | |||
689 | } | 812 | } |
690 | } | 813 | } |
691 | 814 | ||
815 | if (flr) | ||
816 | usleep_range(10000, 20000); | ||
817 | |||
692 | if (!rsd) | 818 | if (!rsd) |
693 | dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n", | 819 | dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n", |
694 | vf->vf_id); | 820 | vf->vf_id); |
@@ -733,6 +859,11 @@ void i40e_free_vfs(struct i40e_pf *pf) | |||
733 | while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state)) | 859 | while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state)) |
734 | usleep_range(1000, 2000); | 860 | usleep_range(1000, 2000); |
735 | 861 | ||
862 | for (i = 0; i < pf->num_alloc_vfs; i++) | ||
863 | if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) | ||
864 | i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], | ||
865 | false); | ||
866 | |||
736 | /* Disable IOV before freeing resources. This lets any VF drivers | 867 | /* Disable IOV before freeing resources. This lets any VF drivers |
737 | * running in the host get themselves cleaned up before we yank | 868 | * running in the host get themselves cleaned up before we yank |
738 | * the carpet out from underneath their feet. | 869 | * the carpet out from underneath their feet. |
@@ -1762,6 +1893,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode, | |||
1762 | break; | 1893 | break; |
1763 | case I40E_VIRTCHNL_OP_ENABLE_QUEUES: | 1894 | case I40E_VIRTCHNL_OP_ENABLE_QUEUES: |
1764 | ret = i40e_vc_enable_queues_msg(vf, msg, msglen); | 1895 | ret = i40e_vc_enable_queues_msg(vf, msg, msglen); |
1896 | i40e_vc_notify_vf_link_state(vf); | ||
1765 | break; | 1897 | break; |
1766 | case I40E_VIRTCHNL_OP_DISABLE_QUEUES: | 1898 | case I40E_VIRTCHNL_OP_DISABLE_QUEUES: |
1767 | ret = i40e_vc_disable_queues_msg(vf, msg, msglen); | 1899 | ret = i40e_vc_disable_queues_msg(vf, msg, msglen); |
@@ -1835,118 +1967,6 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) | |||
1835 | } | 1967 | } |
1836 | 1968 | ||
1837 | /** | 1969 | /** |
1838 | * i40e_vc_vf_broadcast | ||
1839 | * @pf: pointer to the PF structure | ||
1840 | * @opcode: operation code | ||
1841 | * @retval: return value | ||
1842 | * @msg: pointer to the msg buffer | ||
1843 | * @msglen: msg length | ||
1844 | * | ||
1845 | * send a message to all VFs on a given PF | ||
1846 | **/ | ||
1847 | static void i40e_vc_vf_broadcast(struct i40e_pf *pf, | ||
1848 | enum i40e_virtchnl_ops v_opcode, | ||
1849 | i40e_status v_retval, u8 *msg, | ||
1850 | u16 msglen) | ||
1851 | { | ||
1852 | struct i40e_hw *hw = &pf->hw; | ||
1853 | struct i40e_vf *vf = pf->vf; | ||
1854 | int i; | ||
1855 | |||
1856 | for (i = 0; i < pf->num_alloc_vfs; i++, vf++) { | ||
1857 | int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; | ||
1858 | /* Not all VFs are enabled so skip the ones that are not */ | ||
1859 | if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) && | ||
1860 | !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) | ||
1861 | continue; | ||
1862 | |||
1863 | /* Ignore return value on purpose - a given VF may fail, but | ||
1864 | * we need to keep going and send to all of them | ||
1865 | */ | ||
1866 | i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval, | ||
1867 | msg, msglen, NULL); | ||
1868 | } | ||
1869 | } | ||
1870 | |||
1871 | /** | ||
1872 | * i40e_vc_notify_link_state | ||
1873 | * @pf: pointer to the PF structure | ||
1874 | * | ||
1875 | * send a link status message to all VFs on a given PF | ||
1876 | **/ | ||
1877 | void i40e_vc_notify_link_state(struct i40e_pf *pf) | ||
1878 | { | ||
1879 | struct i40e_virtchnl_pf_event pfe; | ||
1880 | struct i40e_hw *hw = &pf->hw; | ||
1881 | struct i40e_vf *vf = pf->vf; | ||
1882 | struct i40e_link_status *ls = &pf->hw.phy.link_info; | ||
1883 | int i; | ||
1884 | |||
1885 | pfe.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE; | ||
1886 | pfe.severity = I40E_PF_EVENT_SEVERITY_INFO; | ||
1887 | for (i = 0; i < pf->num_alloc_vfs; i++, vf++) { | ||
1888 | int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; | ||
1889 | if (vf->link_forced) { | ||
1890 | pfe.event_data.link_event.link_status = vf->link_up; | ||
1891 | pfe.event_data.link_event.link_speed = | ||
1892 | (vf->link_up ? I40E_LINK_SPEED_40GB : 0); | ||
1893 | } else { | ||
1894 | pfe.event_data.link_event.link_status = | ||
1895 | ls->link_info & I40E_AQ_LINK_UP; | ||
1896 | pfe.event_data.link_event.link_speed = ls->link_speed; | ||
1897 | } | ||
1898 | i40e_aq_send_msg_to_vf(hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT, | ||
1899 | 0, (u8 *)&pfe, sizeof(pfe), | ||
1900 | NULL); | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | /** | ||
1905 | * i40e_vc_notify_reset | ||
1906 | * @pf: pointer to the PF structure | ||
1907 | * | ||
1908 | * indicate a pending reset to all VFs on a given PF | ||
1909 | **/ | ||
1910 | void i40e_vc_notify_reset(struct i40e_pf *pf) | ||
1911 | { | ||
1912 | struct i40e_virtchnl_pf_event pfe; | ||
1913 | |||
1914 | pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING; | ||
1915 | pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM; | ||
1916 | i40e_vc_vf_broadcast(pf, I40E_VIRTCHNL_OP_EVENT, I40E_SUCCESS, | ||
1917 | (u8 *)&pfe, sizeof(struct i40e_virtchnl_pf_event)); | ||
1918 | } | ||
1919 | |||
1920 | /** | ||
1921 | * i40e_vc_notify_vf_reset | ||
1922 | * @vf: pointer to the VF structure | ||
1923 | * | ||
1924 | * indicate a pending reset to the given VF | ||
1925 | **/ | ||
1926 | void i40e_vc_notify_vf_reset(struct i40e_vf *vf) | ||
1927 | { | ||
1928 | struct i40e_virtchnl_pf_event pfe; | ||
1929 | int abs_vf_id; | ||
1930 | |||
1931 | /* validate the request */ | ||
1932 | if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs) | ||
1933 | return; | ||
1934 | |||
1935 | /* verify if the VF is in either init or active before proceeding */ | ||
1936 | if (!test_bit(I40E_VF_STAT_INIT, &vf->vf_states) && | ||
1937 | !test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) | ||
1938 | return; | ||
1939 | |||
1940 | abs_vf_id = vf->vf_id + vf->pf->hw.func_caps.vf_base_id; | ||
1941 | |||
1942 | pfe.event = I40E_VIRTCHNL_EVENT_RESET_IMPENDING; | ||
1943 | pfe.severity = I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM; | ||
1944 | i40e_aq_send_msg_to_vf(&vf->pf->hw, abs_vf_id, I40E_VIRTCHNL_OP_EVENT, | ||
1945 | I40E_SUCCESS, (u8 *)&pfe, | ||
1946 | sizeof(struct i40e_virtchnl_pf_event), NULL); | ||
1947 | } | ||
1948 | |||
1949 | /** | ||
1950 | * i40e_ndo_set_vf_mac | 1970 | * i40e_ndo_set_vf_mac |
1951 | * @netdev: network interface device structure | 1971 | * @netdev: network interface device structure |
1952 | * @vf_id: VF identifier | 1972 | * @vf_id: VF identifier |