diff options
-rw-r--r-- | drivers/net/ethernet/intel/i40e/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_client.c | 1012 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_client.h | 232 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 115 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_type.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | 34 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 247 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 4 |
9 files changed, 1657 insertions, 13 deletions
diff --git a/drivers/net/ethernet/intel/i40e/Makefile b/drivers/net/ethernet/intel/i40e/Makefile index b4729ba57c9c..3b3c63e54ed6 100644 --- a/drivers/net/ethernet/intel/i40e/Makefile +++ b/drivers/net/ethernet/intel/i40e/Makefile | |||
@@ -41,6 +41,7 @@ i40e-objs := i40e_main.o \ | |||
41 | i40e_diag.o \ | 41 | i40e_diag.o \ |
42 | i40e_txrx.o \ | 42 | i40e_txrx.o \ |
43 | i40e_ptp.o \ | 43 | i40e_ptp.o \ |
44 | i40e_client.o \ | ||
44 | i40e_virtchnl_pf.o | 45 | i40e_virtchnl_pf.o |
45 | 46 | ||
46 | i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o | 47 | i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o |
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 68f2204ec6f3..e734c649227d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h | |||
@@ -58,6 +58,7 @@ | |||
58 | #ifdef I40E_FCOE | 58 | #ifdef I40E_FCOE |
59 | #include "i40e_fcoe.h" | 59 | #include "i40e_fcoe.h" |
60 | #endif | 60 | #endif |
61 | #include "i40e_client.h" | ||
61 | #include "i40e_virtchnl.h" | 62 | #include "i40e_virtchnl.h" |
62 | #include "i40e_virtchnl_pf.h" | 63 | #include "i40e_virtchnl_pf.h" |
63 | #include "i40e_txrx.h" | 64 | #include "i40e_txrx.h" |
@@ -178,6 +179,7 @@ struct i40e_lump_tracking { | |||
178 | u16 search_hint; | 179 | u16 search_hint; |
179 | u16 list[0]; | 180 | u16 list[0]; |
180 | #define I40E_PILE_VALID_BIT 0x8000 | 181 | #define I40E_PILE_VALID_BIT 0x8000 |
182 | #define I40E_IWARP_IRQ_PILE_ID (I40E_PILE_VALID_BIT - 2) | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | #define I40E_DEFAULT_ATR_SAMPLE_RATE 20 | 185 | #define I40E_DEFAULT_ATR_SAMPLE_RATE 20 |
@@ -270,6 +272,8 @@ struct i40e_pf { | |||
270 | #endif /* I40E_FCOE */ | 272 | #endif /* I40E_FCOE */ |
271 | u16 num_lan_qps; /* num lan queues this PF has set up */ | 273 | u16 num_lan_qps; /* num lan queues this PF has set up */ |
272 | u16 num_lan_msix; /* num queue vectors for the base PF vsi */ | 274 | u16 num_lan_msix; /* num queue vectors for the base PF vsi */ |
275 | u16 num_iwarp_msix; /* num of iwarp vectors for this PF */ | ||
276 | int iwarp_base_vector; | ||
273 | int queues_left; /* queues left unclaimed */ | 277 | int queues_left; /* queues left unclaimed */ |
274 | u16 alloc_rss_size; /* allocated RSS queues */ | 278 | u16 alloc_rss_size; /* allocated RSS queues */ |
275 | u16 rss_size_max; /* HW defined max RSS queues */ | 279 | u16 rss_size_max; /* HW defined max RSS queues */ |
@@ -317,6 +321,7 @@ struct i40e_pf { | |||
317 | #define I40E_FLAG_16BYTE_RX_DESC_ENABLED BIT_ULL(13) | 321 | #define I40E_FLAG_16BYTE_RX_DESC_ENABLED BIT_ULL(13) |
318 | #define I40E_FLAG_CLEAN_ADMINQ BIT_ULL(14) | 322 | #define I40E_FLAG_CLEAN_ADMINQ BIT_ULL(14) |
319 | #define I40E_FLAG_FILTER_SYNC BIT_ULL(15) | 323 | #define I40E_FLAG_FILTER_SYNC BIT_ULL(15) |
324 | #define I40E_FLAG_SERVICE_CLIENT_REQUESTED BIT_ULL(16) | ||
320 | #define I40E_FLAG_PROCESS_MDD_EVENT BIT_ULL(17) | 325 | #define I40E_FLAG_PROCESS_MDD_EVENT BIT_ULL(17) |
321 | #define I40E_FLAG_PROCESS_VFLR_EVENT BIT_ULL(18) | 326 | #define I40E_FLAG_PROCESS_VFLR_EVENT BIT_ULL(18) |
322 | #define I40E_FLAG_SRIOV_ENABLED BIT_ULL(19) | 327 | #define I40E_FLAG_SRIOV_ENABLED BIT_ULL(19) |
@@ -557,6 +562,8 @@ struct i40e_vsi { | |||
557 | struct kobject *kobj; /* sysfs object */ | 562 | struct kobject *kobj; /* sysfs object */ |
558 | bool current_isup; /* Sync 'link up' logging */ | 563 | bool current_isup; /* Sync 'link up' logging */ |
559 | 564 | ||
565 | void *priv; /* client driver data reference. */ | ||
566 | |||
560 | /* VSI specific handlers */ | 567 | /* VSI specific handlers */ |
561 | irqreturn_t (*irq_handler)(int irq, void *data); | 568 | irqreturn_t (*irq_handler)(int irq, void *data); |
562 | 569 | ||
@@ -714,6 +721,10 @@ void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi, | |||
714 | struct i40e_vsi_context *ctxt, | 721 | struct i40e_vsi_context *ctxt, |
715 | u8 enabled_tc, bool is_add); | 722 | u8 enabled_tc, bool is_add); |
716 | #endif | 723 | #endif |
724 | void i40e_service_event_schedule(struct i40e_pf *pf); | ||
725 | void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id, | ||
726 | u8 *msg, u16 len); | ||
727 | |||
717 | int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable); | 728 | int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable); |
718 | int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count); | 729 | int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count); |
719 | struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid, | 730 | struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid, |
@@ -736,6 +747,17 @@ static inline void i40e_dbg_pf_exit(struct i40e_pf *pf) {} | |||
736 | static inline void i40e_dbg_init(void) {} | 747 | static inline void i40e_dbg_init(void) {} |
737 | static inline void i40e_dbg_exit(void) {} | 748 | static inline void i40e_dbg_exit(void) {} |
738 | #endif /* CONFIG_DEBUG_FS*/ | 749 | #endif /* CONFIG_DEBUG_FS*/ |
750 | /* needed by client drivers */ | ||
751 | int i40e_lan_add_device(struct i40e_pf *pf); | ||
752 | int i40e_lan_del_device(struct i40e_pf *pf); | ||
753 | void i40e_client_subtask(struct i40e_pf *pf); | ||
754 | void i40e_notify_client_of_l2_param_changes(struct i40e_vsi *vsi); | ||
755 | void i40e_notify_client_of_netdev_open(struct i40e_vsi *vsi); | ||
756 | void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset); | ||
757 | void i40e_notify_client_of_vf_enable(struct i40e_pf *pf, u32 num_vfs); | ||
758 | void i40e_notify_client_of_vf_reset(struct i40e_pf *pf, u32 vf_id); | ||
759 | int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id, | ||
760 | enum i40e_client_type type); | ||
739 | /** | 761 | /** |
740 | * i40e_irq_dynamic_enable - Enable default interrupt generation settings | 762 | * i40e_irq_dynamic_enable - Enable default interrupt generation settings |
741 | * @vsi: pointer to a vsi | 763 | * @vsi: pointer to a vsi |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c new file mode 100644 index 000000000000..0e6ac841321c --- /dev/null +++ b/drivers/net/ethernet/intel/i40e/i40e_client.c | |||
@@ -0,0 +1,1012 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Intel Ethernet Controller XL710 Family Linux Driver | ||
4 | * Copyright(c) 2013 - 2015 Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in | ||
19 | * the file called "COPYING". | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | ******************************************************************************/ | ||
26 | |||
27 | #include <linux/list.h> | ||
28 | #include <linux/errno.h> | ||
29 | |||
30 | #include "i40e.h" | ||
31 | #include "i40e_prototype.h" | ||
32 | #include "i40e_client.h" | ||
33 | |||
34 | static const char i40e_client_interface_version_str[] = I40E_CLIENT_VERSION_STR; | ||
35 | |||
36 | static LIST_HEAD(i40e_devices); | ||
37 | static DEFINE_MUTEX(i40e_device_mutex); | ||
38 | |||
39 | static LIST_HEAD(i40e_clients); | ||
40 | static DEFINE_MUTEX(i40e_client_mutex); | ||
41 | |||
42 | static LIST_HEAD(i40e_client_instances); | ||
43 | static DEFINE_MUTEX(i40e_client_instance_mutex); | ||
44 | |||
45 | static int i40e_client_virtchnl_send(struct i40e_info *ldev, | ||
46 | struct i40e_client *client, | ||
47 | u32 vf_id, u8 *msg, u16 len); | ||
48 | |||
49 | static int i40e_client_setup_qvlist(struct i40e_info *ldev, | ||
50 | struct i40e_client *client, | ||
51 | struct i40e_qvlist_info *qvlist_info); | ||
52 | |||
53 | static void i40e_client_request_reset(struct i40e_info *ldev, | ||
54 | struct i40e_client *client, | ||
55 | u32 reset_level); | ||
56 | |||
57 | static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev, | ||
58 | struct i40e_client *client, | ||
59 | bool is_vf, u32 vf_id, | ||
60 | u32 flag, u32 valid_flag); | ||
61 | |||
62 | static struct i40e_ops i40e_lan_ops = { | ||
63 | .virtchnl_send = i40e_client_virtchnl_send, | ||
64 | .setup_qvlist = i40e_client_setup_qvlist, | ||
65 | .request_reset = i40e_client_request_reset, | ||
66 | .update_vsi_ctxt = i40e_client_update_vsi_ctxt, | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * i40e_client_type_to_vsi_type - convert client type to vsi type | ||
71 | * @client_type: the i40e_client type | ||
72 | * | ||
73 | * returns the related vsi type value | ||
74 | **/ | ||
75 | static | ||
76 | enum i40e_vsi_type i40e_client_type_to_vsi_type(enum i40e_client_type type) | ||
77 | { | ||
78 | switch (type) { | ||
79 | case I40E_CLIENT_IWARP: | ||
80 | return I40E_VSI_IWARP; | ||
81 | |||
82 | case I40E_CLIENT_VMDQ2: | ||
83 | return I40E_VSI_VMDQ2; | ||
84 | |||
85 | default: | ||
86 | pr_err("i40e: Client type unknown\n"); | ||
87 | return I40E_VSI_TYPE_UNKNOWN; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * i40e_client_get_params - Get the params that can change at runtime | ||
93 | * @vsi: the VSI with the message | ||
94 | * @param: clinet param struct | ||
95 | * | ||
96 | **/ | ||
97 | static | ||
98 | int i40e_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params) | ||
99 | { | ||
100 | struct i40e_dcbx_config *dcb_cfg = &vsi->back->hw.local_dcbx_config; | ||
101 | int i = 0; | ||
102 | |||
103 | for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { | ||
104 | u8 tc = dcb_cfg->etscfg.prioritytable[i]; | ||
105 | u16 qs_handle; | ||
106 | |||
107 | /* If TC is not enabled for VSI use TC0 for UP */ | ||
108 | if (!(vsi->tc_config.enabled_tc & BIT(tc))) | ||
109 | tc = 0; | ||
110 | |||
111 | qs_handle = le16_to_cpu(vsi->info.qs_handle[tc]); | ||
112 | params->qos.prio_qos[i].tc = tc; | ||
113 | params->qos.prio_qos[i].qs_handle = qs_handle; | ||
114 | if (qs_handle == I40E_AQ_VSI_QS_HANDLE_INVALID) { | ||
115 | dev_err(&vsi->back->pdev->dev, "Invalid queue set handle for TC = %d, vsi id = %d\n", | ||
116 | tc, vsi->id); | ||
117 | return -EINVAL; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | params->mtu = vsi->netdev->mtu; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * i40e_notify_client_of_vf_msg - call the client vf message callback | ||
127 | * @vsi: the VSI with the message | ||
128 | * @vf_id: the absolute VF id that sent the message | ||
129 | * @msg: message buffer | ||
130 | * @len: length of the message | ||
131 | * | ||
132 | * If there is a client to this VSI, call the client | ||
133 | **/ | ||
134 | void | ||
135 | i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id, u8 *msg, u16 len) | ||
136 | { | ||
137 | struct i40e_client_instance *cdev; | ||
138 | |||
139 | if (!vsi) | ||
140 | return; | ||
141 | mutex_lock(&i40e_client_instance_mutex); | ||
142 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
143 | if (cdev->lan_info.pf == vsi->back) { | ||
144 | if (!cdev->client || | ||
145 | !cdev->client->ops || | ||
146 | !cdev->client->ops->virtchnl_receive) { | ||
147 | dev_dbg(&vsi->back->pdev->dev, | ||
148 | "Cannot locate client instance virtual channel receive routine\n"); | ||
149 | continue; | ||
150 | } | ||
151 | cdev->client->ops->virtchnl_receive(&cdev->lan_info, | ||
152 | cdev->client, | ||
153 | vf_id, msg, len); | ||
154 | } | ||
155 | } | ||
156 | mutex_unlock(&i40e_client_instance_mutex); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * i40e_notify_client_of_l2_param_changes - call the client notify callback | ||
161 | * @vsi: the VSI with l2 param changes | ||
162 | * | ||
163 | * If there is a client to this VSI, call the client | ||
164 | **/ | ||
165 | void i40e_notify_client_of_l2_param_changes(struct i40e_vsi *vsi) | ||
166 | { | ||
167 | struct i40e_client_instance *cdev; | ||
168 | struct i40e_params params; | ||
169 | |||
170 | if (!vsi) | ||
171 | return; | ||
172 | memset(¶ms, 0, sizeof(params)); | ||
173 | i40e_client_get_params(vsi, ¶ms); | ||
174 | mutex_lock(&i40e_client_instance_mutex); | ||
175 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
176 | if (cdev->lan_info.pf == vsi->back) { | ||
177 | if (!cdev->client || | ||
178 | !cdev->client->ops || | ||
179 | !cdev->client->ops->l2_param_change) { | ||
180 | dev_dbg(&vsi->back->pdev->dev, | ||
181 | "Cannot locate client instance l2_param_change routine\n"); | ||
182 | continue; | ||
183 | } | ||
184 | cdev->lan_info.params = params; | ||
185 | cdev->client->ops->l2_param_change(&cdev->lan_info, | ||
186 | cdev->client, | ||
187 | ¶ms); | ||
188 | } | ||
189 | } | ||
190 | mutex_unlock(&i40e_client_instance_mutex); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * i40e_notify_client_of_netdev_open - call the client open callback | ||
195 | * @vsi: the VSI with netdev opened | ||
196 | * | ||
197 | * If there is a client to this netdev, call the client with open | ||
198 | **/ | ||
199 | void i40e_notify_client_of_netdev_open(struct i40e_vsi *vsi) | ||
200 | { | ||
201 | struct i40e_client_instance *cdev; | ||
202 | |||
203 | if (!vsi) | ||
204 | return; | ||
205 | mutex_lock(&i40e_client_instance_mutex); | ||
206 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
207 | if (cdev->lan_info.netdev == vsi->netdev) { | ||
208 | if (!cdev->client || | ||
209 | !cdev->client->ops || !cdev->client->ops->open) { | ||
210 | dev_dbg(&vsi->back->pdev->dev, | ||
211 | "Cannot locate client instance open routine\n"); | ||
212 | continue; | ||
213 | } | ||
214 | cdev->client->ops->open(&cdev->lan_info, cdev->client); | ||
215 | } | ||
216 | } | ||
217 | mutex_unlock(&i40e_client_instance_mutex); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * i40e_client_release_qvlist | ||
222 | * @ldev: pointer to L2 context. | ||
223 | * | ||
224 | **/ | ||
225 | static void i40e_client_release_qvlist(struct i40e_info *ldev) | ||
226 | { | ||
227 | struct i40e_qvlist_info *qvlist_info = ldev->qvlist_info; | ||
228 | u32 i; | ||
229 | |||
230 | if (!ldev->qvlist_info) | ||
231 | return; | ||
232 | |||
233 | for (i = 0; i < qvlist_info->num_vectors; i++) { | ||
234 | struct i40e_pf *pf = ldev->pf; | ||
235 | struct i40e_qv_info *qv_info; | ||
236 | u32 reg_idx; | ||
237 | |||
238 | qv_info = &qvlist_info->qv_info[i]; | ||
239 | if (!qv_info) | ||
240 | continue; | ||
241 | reg_idx = I40E_PFINT_LNKLSTN(qv_info->v_idx - 1); | ||
242 | wr32(&pf->hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK); | ||
243 | } | ||
244 | kfree(ldev->qvlist_info); | ||
245 | ldev->qvlist_info = NULL; | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * i40e_notify_client_of_netdev_close - call the client close callback | ||
250 | * @vsi: the VSI with netdev closed | ||
251 | * @reset: true when close called due to a reset pending | ||
252 | * | ||
253 | * If there is a client to this netdev, call the client with close | ||
254 | **/ | ||
255 | void i40e_notify_client_of_netdev_close(struct i40e_vsi *vsi, bool reset) | ||
256 | { | ||
257 | struct i40e_client_instance *cdev; | ||
258 | |||
259 | if (!vsi) | ||
260 | return; | ||
261 | mutex_lock(&i40e_client_instance_mutex); | ||
262 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
263 | if (cdev->lan_info.netdev == vsi->netdev) { | ||
264 | if (!cdev->client || | ||
265 | !cdev->client->ops || !cdev->client->ops->close) { | ||
266 | dev_dbg(&vsi->back->pdev->dev, | ||
267 | "Cannot locate client instance close routine\n"); | ||
268 | continue; | ||
269 | } | ||
270 | cdev->client->ops->close(&cdev->lan_info, cdev->client, | ||
271 | reset); | ||
272 | i40e_client_release_qvlist(&cdev->lan_info); | ||
273 | } | ||
274 | } | ||
275 | mutex_unlock(&i40e_client_instance_mutex); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * i40e_notify_client_of_vf_reset - call the client vf reset callback | ||
280 | * @pf: PF device pointer | ||
281 | * @vf_id: asolute id of VF being reset | ||
282 | * | ||
283 | * If there is a client attached to this PF, notify when a VF is reset | ||
284 | **/ | ||
285 | void i40e_notify_client_of_vf_reset(struct i40e_pf *pf, u32 vf_id) | ||
286 | { | ||
287 | struct i40e_client_instance *cdev; | ||
288 | |||
289 | if (!pf) | ||
290 | return; | ||
291 | mutex_lock(&i40e_client_instance_mutex); | ||
292 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
293 | if (cdev->lan_info.pf == pf) { | ||
294 | if (!cdev->client || | ||
295 | !cdev->client->ops || | ||
296 | !cdev->client->ops->vf_reset) { | ||
297 | dev_dbg(&pf->pdev->dev, | ||
298 | "Cannot locate client instance VF reset routine\n"); | ||
299 | continue; | ||
300 | } | ||
301 | cdev->client->ops->vf_reset(&cdev->lan_info, | ||
302 | cdev->client, vf_id); | ||
303 | } | ||
304 | } | ||
305 | mutex_unlock(&i40e_client_instance_mutex); | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * i40e_notify_client_of_vf_enable - call the client vf notification callback | ||
310 | * @pf: PF device pointer | ||
311 | * @num_vfs: the number of VFs currently enabled, 0 for disable | ||
312 | * | ||
313 | * If there is a client attached to this PF, call its VF notification routine | ||
314 | **/ | ||
315 | void i40e_notify_client_of_vf_enable(struct i40e_pf *pf, u32 num_vfs) | ||
316 | { | ||
317 | struct i40e_client_instance *cdev; | ||
318 | |||
319 | if (!pf) | ||
320 | return; | ||
321 | mutex_lock(&i40e_client_instance_mutex); | ||
322 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
323 | if (cdev->lan_info.pf == pf) { | ||
324 | if (!cdev->client || | ||
325 | !cdev->client->ops || | ||
326 | !cdev->client->ops->vf_enable) { | ||
327 | dev_dbg(&pf->pdev->dev, | ||
328 | "Cannot locate client instance VF enable routine\n"); | ||
329 | continue; | ||
330 | } | ||
331 | cdev->client->ops->vf_enable(&cdev->lan_info, | ||
332 | cdev->client, num_vfs); | ||
333 | } | ||
334 | } | ||
335 | mutex_unlock(&i40e_client_instance_mutex); | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * i40e_vf_client_capable - ask the client if it likes the specified VF | ||
340 | * @pf: PF device pointer | ||
341 | * @vf_id: the VF in question | ||
342 | * | ||
343 | * If there is a client of the specified type attached to this PF, call | ||
344 | * its vf_capable routine | ||
345 | **/ | ||
346 | int i40e_vf_client_capable(struct i40e_pf *pf, u32 vf_id, | ||
347 | enum i40e_client_type type) | ||
348 | { | ||
349 | struct i40e_client_instance *cdev; | ||
350 | int capable = false; | ||
351 | |||
352 | if (!pf) | ||
353 | return false; | ||
354 | mutex_lock(&i40e_client_instance_mutex); | ||
355 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
356 | if (cdev->lan_info.pf == pf) { | ||
357 | if (!cdev->client || | ||
358 | !cdev->client->ops || | ||
359 | !cdev->client->ops->vf_capable || | ||
360 | !(cdev->client->type == type)) { | ||
361 | dev_dbg(&pf->pdev->dev, | ||
362 | "Cannot locate client instance VF capability routine\n"); | ||
363 | continue; | ||
364 | } | ||
365 | capable = cdev->client->ops->vf_capable(&cdev->lan_info, | ||
366 | cdev->client, | ||
367 | vf_id); | ||
368 | break; | ||
369 | } | ||
370 | } | ||
371 | mutex_unlock(&i40e_client_instance_mutex); | ||
372 | return capable; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi | ||
377 | * @pf: board private structure | ||
378 | * @type: vsi type | ||
379 | * @start_vsi: a VSI pointer from where to start the search | ||
380 | * | ||
381 | * Returns non NULL on success or NULL for failure | ||
382 | **/ | ||
383 | struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, | ||
384 | enum i40e_vsi_type type, | ||
385 | struct i40e_vsi *start_vsi) | ||
386 | { | ||
387 | struct i40e_vsi *vsi; | ||
388 | int i = 0; | ||
389 | |||
390 | if (start_vsi) { | ||
391 | for (i = 0; i < pf->num_alloc_vsi; i++) { | ||
392 | vsi = pf->vsi[i]; | ||
393 | if (vsi == start_vsi) | ||
394 | break; | ||
395 | } | ||
396 | } | ||
397 | for (; i < pf->num_alloc_vsi; i++) { | ||
398 | vsi = pf->vsi[i]; | ||
399 | if (vsi && vsi->type == type) | ||
400 | return vsi; | ||
401 | } | ||
402 | |||
403 | return NULL; | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * i40e_client_add_instance - add a client instance struct to the instance list | ||
408 | * @pf: pointer to the board struct | ||
409 | * @client: pointer to a client struct in the client list. | ||
410 | * | ||
411 | * Returns cdev ptr on success, NULL on failure | ||
412 | **/ | ||
413 | static | ||
414 | struct i40e_client_instance *i40e_client_add_instance(struct i40e_pf *pf, | ||
415 | struct i40e_client *client) | ||
416 | { | ||
417 | struct i40e_client_instance *cdev; | ||
418 | struct netdev_hw_addr *mac = NULL; | ||
419 | struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; | ||
420 | |||
421 | mutex_lock(&i40e_client_instance_mutex); | ||
422 | list_for_each_entry(cdev, &i40e_client_instances, list) { | ||
423 | if ((cdev->lan_info.pf == pf) && (cdev->client == client)) { | ||
424 | cdev = NULL; | ||
425 | goto out; | ||
426 | } | ||
427 | } | ||
428 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); | ||
429 | if (!cdev) | ||
430 | goto out; | ||
431 | |||
432 | cdev->lan_info.pf = (void *)pf; | ||
433 | cdev->lan_info.netdev = vsi->netdev; | ||
434 | cdev->lan_info.pcidev = pf->pdev; | ||
435 | cdev->lan_info.fid = pf->hw.pf_id; | ||
436 | cdev->lan_info.ftype = I40E_CLIENT_FTYPE_PF; | ||
437 | cdev->lan_info.hw_addr = pf->hw.hw_addr; | ||
438 | cdev->lan_info.ops = &i40e_lan_ops; | ||
439 | cdev->lan_info.version.major = I40E_CLIENT_VERSION_MAJOR; | ||
440 | cdev->lan_info.version.minor = I40E_CLIENT_VERSION_MINOR; | ||
441 | cdev->lan_info.version.build = I40E_CLIENT_VERSION_BUILD; | ||
442 | cdev->lan_info.fw_maj_ver = pf->hw.aq.fw_maj_ver; | ||
443 | cdev->lan_info.fw_min_ver = pf->hw.aq.fw_min_ver; | ||
444 | cdev->lan_info.fw_build = pf->hw.aq.fw_build; | ||
445 | set_bit(__I40E_CLIENT_INSTANCE_NONE, &cdev->state); | ||
446 | |||
447 | if (i40e_client_get_params(vsi, &cdev->lan_info.params)) { | ||
448 | kfree(cdev); | ||
449 | cdev = NULL; | ||
450 | goto out; | ||
451 | } | ||
452 | |||
453 | cdev->lan_info.msix_count = pf->num_iwarp_msix; | ||
454 | cdev->lan_info.msix_entries = &pf->msix_entries[pf->iwarp_base_vector]; | ||
455 | |||
456 | mac = list_first_entry(&cdev->lan_info.netdev->dev_addrs.list, | ||
457 | struct netdev_hw_addr, list); | ||
458 | if (mac) | ||
459 | ether_addr_copy(cdev->lan_info.lanmac, mac->addr); | ||
460 | else | ||
461 | dev_err(&pf->pdev->dev, "MAC address list is empty!\n"); | ||
462 | |||
463 | cdev->client = client; | ||
464 | INIT_LIST_HEAD(&cdev->list); | ||
465 | list_add(&cdev->list, &i40e_client_instances); | ||
466 | out: | ||
467 | mutex_unlock(&i40e_client_instance_mutex); | ||
468 | return cdev; | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * i40e_client_del_instance - removes a client instance from the list | ||
473 | * @pf: pointer to the board struct | ||
474 | * | ||
475 | * Returns 0 on success or non-0 on error | ||
476 | **/ | ||
477 | static | ||
478 | int i40e_client_del_instance(struct i40e_pf *pf, struct i40e_client *client) | ||
479 | { | ||
480 | struct i40e_client_instance *cdev, *tmp; | ||
481 | int ret = -ENODEV; | ||
482 | |||
483 | mutex_lock(&i40e_client_instance_mutex); | ||
484 | list_for_each_entry_safe(cdev, tmp, &i40e_client_instances, list) { | ||
485 | if ((cdev->lan_info.pf != pf) || (cdev->client != client)) | ||
486 | continue; | ||
487 | |||
488 | dev_info(&pf->pdev->dev, "Deleted instance of Client %s, of dev %d bus=0x%02x func=0x%02x)\n", | ||
489 | client->name, pf->hw.pf_id, | ||
490 | pf->hw.bus.device, pf->hw.bus.func); | ||
491 | list_del(&cdev->list); | ||
492 | kfree(cdev); | ||
493 | ret = 0; | ||
494 | break; | ||
495 | } | ||
496 | mutex_unlock(&i40e_client_instance_mutex); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * i40e_client_subtask - client maintenance work | ||
502 | * @pf: board private structure | ||
503 | **/ | ||
504 | void i40e_client_subtask(struct i40e_pf *pf) | ||
505 | { | ||
506 | struct i40e_client_instance *cdev; | ||
507 | struct i40e_client *client; | ||
508 | int ret = 0; | ||
509 | |||
510 | if (!(pf->flags & I40E_FLAG_SERVICE_CLIENT_REQUESTED)) | ||
511 | return; | ||
512 | pf->flags &= ~I40E_FLAG_SERVICE_CLIENT_REQUESTED; | ||
513 | |||
514 | /* If we're down or resetting, just bail */ | ||
515 | if (test_bit(__I40E_DOWN, &pf->state) || | ||
516 | test_bit(__I40E_CONFIG_BUSY, &pf->state)) | ||
517 | return; | ||
518 | |||
519 | /* Check client state and instantiate client if client registered */ | ||
520 | mutex_lock(&i40e_client_mutex); | ||
521 | list_for_each_entry(client, &i40e_clients, list) { | ||
522 | /* first check client is registered */ | ||
523 | if (!test_bit(__I40E_CLIENT_REGISTERED, &client->state)) | ||
524 | continue; | ||
525 | |||
526 | /* Do we also need the LAN VSI to be up, to create instance */ | ||
527 | if (!(client->flags & I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE)) { | ||
528 | /* check if L2 VSI is up, if not we are not ready */ | ||
529 | if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state)) | ||
530 | continue; | ||
531 | } | ||
532 | |||
533 | /* Add the client instance to the instance list */ | ||
534 | cdev = i40e_client_add_instance(pf, client); | ||
535 | if (!cdev) | ||
536 | continue; | ||
537 | |||
538 | /* Also up the ref_cnt of no. of instances of this client */ | ||
539 | atomic_inc(&client->ref_cnt); | ||
540 | dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n", | ||
541 | client->name, pf->hw.pf_id, | ||
542 | pf->hw.bus.device, pf->hw.bus.func); | ||
543 | |||
544 | /* Send an Open request to the client */ | ||
545 | atomic_inc(&cdev->ref_cnt); | ||
546 | if (client->ops && client->ops->open) | ||
547 | ret = client->ops->open(&cdev->lan_info, client); | ||
548 | atomic_dec(&cdev->ref_cnt); | ||
549 | if (!ret) { | ||
550 | set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); | ||
551 | } else { | ||
552 | /* remove client instance */ | ||
553 | i40e_client_del_instance(pf, client); | ||
554 | atomic_dec(&client->ref_cnt); | ||
555 | continue; | ||
556 | } | ||
557 | } | ||
558 | mutex_unlock(&i40e_client_mutex); | ||
559 | } | ||
560 | |||
561 | /** | ||
562 | * i40e_lan_add_device - add a lan device struct to the list of lan devices | ||
563 | * @pf: pointer to the board struct | ||
564 | * | ||
565 | * Returns 0 on success or none 0 on error | ||
566 | **/ | ||
567 | int i40e_lan_add_device(struct i40e_pf *pf) | ||
568 | { | ||
569 | struct i40e_device *ldev; | ||
570 | int ret = 0; | ||
571 | |||
572 | mutex_lock(&i40e_device_mutex); | ||
573 | list_for_each_entry(ldev, &i40e_devices, list) { | ||
574 | if (ldev->pf == pf) { | ||
575 | ret = -EEXIST; | ||
576 | goto out; | ||
577 | } | ||
578 | } | ||
579 | ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); | ||
580 | if (!ldev) { | ||
581 | ret = -ENOMEM; | ||
582 | goto out; | ||
583 | } | ||
584 | ldev->pf = pf; | ||
585 | INIT_LIST_HEAD(&ldev->list); | ||
586 | list_add(&ldev->list, &i40e_devices); | ||
587 | dev_info(&pf->pdev->dev, "Added LAN device PF%d bus=0x%02x func=0x%02x\n", | ||
588 | pf->hw.pf_id, pf->hw.bus.device, pf->hw.bus.func); | ||
589 | |||
590 | /* Since in some cases register may have happened before a device gets | ||
591 | * added, we can schedule a subtask to go initiate the clients. | ||
592 | */ | ||
593 | pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED; | ||
594 | i40e_service_event_schedule(pf); | ||
595 | |||
596 | out: | ||
597 | mutex_unlock(&i40e_device_mutex); | ||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * i40e_lan_del_device - removes a lan device from the device list | ||
603 | * @pf: pointer to the board struct | ||
604 | * | ||
605 | * Returns 0 on success or non-0 on error | ||
606 | **/ | ||
607 | int i40e_lan_del_device(struct i40e_pf *pf) | ||
608 | { | ||
609 | struct i40e_device *ldev, *tmp; | ||
610 | int ret = -ENODEV; | ||
611 | |||
612 | mutex_lock(&i40e_device_mutex); | ||
613 | list_for_each_entry_safe(ldev, tmp, &i40e_devices, list) { | ||
614 | if (ldev->pf == pf) { | ||
615 | dev_info(&pf->pdev->dev, "Deleted LAN device PF%d bus=0x%02x func=0x%02x\n", | ||
616 | pf->hw.pf_id, pf->hw.bus.device, | ||
617 | pf->hw.bus.func); | ||
618 | list_del(&ldev->list); | ||
619 | kfree(ldev); | ||
620 | ret = 0; | ||
621 | break; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | mutex_unlock(&i40e_device_mutex); | ||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * i40e_client_release - release client specific resources | ||
631 | * @client: pointer to the registered client | ||
632 | * | ||
633 | * Return 0 on success or < 0 on error | ||
634 | **/ | ||
635 | static int i40e_client_release(struct i40e_client *client) | ||
636 | { | ||
637 | struct i40e_client_instance *cdev, *tmp; | ||
638 | struct i40e_pf *pf = NULL; | ||
639 | int ret = 0; | ||
640 | |||
641 | LIST_HEAD(cdevs_tmp); | ||
642 | |||
643 | mutex_lock(&i40e_client_instance_mutex); | ||
644 | list_for_each_entry_safe(cdev, tmp, &i40e_client_instances, list) { | ||
645 | if (strncmp(cdev->client->name, client->name, | ||
646 | I40E_CLIENT_STR_LENGTH)) | ||
647 | continue; | ||
648 | if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) { | ||
649 | if (atomic_read(&cdev->ref_cnt) > 0) { | ||
650 | ret = I40E_ERR_NOT_READY; | ||
651 | goto out; | ||
652 | } | ||
653 | pf = (struct i40e_pf *)cdev->lan_info.pf; | ||
654 | if (client->ops && client->ops->close) | ||
655 | client->ops->close(&cdev->lan_info, client, | ||
656 | false); | ||
657 | i40e_client_release_qvlist(&cdev->lan_info); | ||
658 | clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state); | ||
659 | |||
660 | dev_warn(&pf->pdev->dev, | ||
661 | "Client %s instance for PF id %d closed\n", | ||
662 | client->name, pf->hw.pf_id); | ||
663 | } | ||
664 | /* delete the client instance from the list */ | ||
665 | list_del(&cdev->list); | ||
666 | list_add(&cdev->list, &cdevs_tmp); | ||
667 | atomic_dec(&client->ref_cnt); | ||
668 | dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n", | ||
669 | client->name); | ||
670 | } | ||
671 | out: | ||
672 | mutex_unlock(&i40e_client_instance_mutex); | ||
673 | |||
674 | /* free the client device and release its vsi */ | ||
675 | list_for_each_entry_safe(cdev, tmp, &cdevs_tmp, list) { | ||
676 | kfree(cdev); | ||
677 | } | ||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * i40e_client_prepare - prepare client specific resources | ||
683 | * @client: pointer to the registered client | ||
684 | * | ||
685 | * Return 0 on success or < 0 on error | ||
686 | **/ | ||
687 | static int i40e_client_prepare(struct i40e_client *client) | ||
688 | { | ||
689 | struct i40e_device *ldev; | ||
690 | struct i40e_pf *pf; | ||
691 | int ret = 0; | ||
692 | |||
693 | mutex_lock(&i40e_device_mutex); | ||
694 | list_for_each_entry(ldev, &i40e_devices, list) { | ||
695 | pf = ldev->pf; | ||
696 | /* Start the client subtask */ | ||
697 | pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED; | ||
698 | i40e_service_event_schedule(pf); | ||
699 | } | ||
700 | mutex_unlock(&i40e_device_mutex); | ||
701 | return ret; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * i40e_client_virtchnl_send - TBD | ||
706 | * @ldev: pointer to L2 context | ||
707 | * @client: Client pointer | ||
708 | * @vf_id: absolute VF identifier | ||
709 | * @msg: message buffer | ||
710 | * @len: length of message buffer | ||
711 | * | ||
712 | * Return 0 on success or < 0 on error | ||
713 | **/ | ||
714 | static int i40e_client_virtchnl_send(struct i40e_info *ldev, | ||
715 | struct i40e_client *client, | ||
716 | u32 vf_id, u8 *msg, u16 len) | ||
717 | { | ||
718 | struct i40e_pf *pf = ldev->pf; | ||
719 | struct i40e_hw *hw = &pf->hw; | ||
720 | i40e_status err; | ||
721 | |||
722 | err = i40e_aq_send_msg_to_vf(hw, vf_id, I40E_VIRTCHNL_OP_IWARP, | ||
723 | 0, msg, len, NULL); | ||
724 | if (err) | ||
725 | dev_err(&pf->pdev->dev, "Unable to send iWarp message to VF, error %d, aq status %d\n", | ||
726 | err, hw->aq.asq_last_status); | ||
727 | |||
728 | return err; | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * i40e_client_setup_qvlist | ||
733 | * @ldev: pointer to L2 context. | ||
734 | * @client: Client pointer. | ||
735 | * @qv_info: queue and vector list | ||
736 | * | ||
737 | * Return 0 on success or < 0 on error | ||
738 | **/ | ||
739 | static int i40e_client_setup_qvlist(struct i40e_info *ldev, | ||
740 | struct i40e_client *client, | ||
741 | struct i40e_qvlist_info *qvlist_info) | ||
742 | { | ||
743 | struct i40e_pf *pf = ldev->pf; | ||
744 | struct i40e_hw *hw = &pf->hw; | ||
745 | struct i40e_qv_info *qv_info; | ||
746 | u32 v_idx, i, reg_idx, reg; | ||
747 | u32 size; | ||
748 | |||
749 | size = sizeof(struct i40e_qvlist_info) + | ||
750 | (sizeof(struct i40e_qv_info) * (qvlist_info->num_vectors - 1)); | ||
751 | ldev->qvlist_info = kzalloc(size, GFP_KERNEL); | ||
752 | ldev->qvlist_info->num_vectors = qvlist_info->num_vectors; | ||
753 | |||
754 | for (i = 0; i < qvlist_info->num_vectors; i++) { | ||
755 | qv_info = &qvlist_info->qv_info[i]; | ||
756 | if (!qv_info) | ||
757 | continue; | ||
758 | v_idx = qv_info->v_idx; | ||
759 | |||
760 | /* Validate vector id belongs to this client */ | ||
761 | if ((v_idx >= (pf->iwarp_base_vector + pf->num_iwarp_msix)) || | ||
762 | (v_idx < pf->iwarp_base_vector)) | ||
763 | goto err; | ||
764 | |||
765 | ldev->qvlist_info->qv_info[i] = *qv_info; | ||
766 | reg_idx = I40E_PFINT_LNKLSTN(v_idx - 1); | ||
767 | |||
768 | if (qv_info->ceq_idx == I40E_QUEUE_INVALID_IDX) { | ||
769 | /* Special case - No CEQ mapped on this vector */ | ||
770 | wr32(hw, reg_idx, I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK); | ||
771 | } else { | ||
772 | reg = (qv_info->ceq_idx & | ||
773 | I40E_PFINT_LNKLSTN_FIRSTQ_INDX_MASK) | | ||
774 | (I40E_QUEUE_TYPE_PE_CEQ << | ||
775 | I40E_PFINT_LNKLSTN_FIRSTQ_TYPE_SHIFT); | ||
776 | wr32(hw, reg_idx, reg); | ||
777 | |||
778 | reg = (I40E_PFINT_CEQCTL_CAUSE_ENA_MASK | | ||
779 | (v_idx << I40E_PFINT_CEQCTL_MSIX_INDX_SHIFT) | | ||
780 | (qv_info->itr_idx << | ||
781 | I40E_PFINT_CEQCTL_ITR_INDX_SHIFT) | | ||
782 | (I40E_QUEUE_END_OF_LIST << | ||
783 | I40E_PFINT_CEQCTL_NEXTQ_INDX_SHIFT)); | ||
784 | wr32(hw, I40E_PFINT_CEQCTL(qv_info->ceq_idx), reg); | ||
785 | } | ||
786 | if (qv_info->aeq_idx != I40E_QUEUE_INVALID_IDX) { | ||
787 | reg = (I40E_PFINT_AEQCTL_CAUSE_ENA_MASK | | ||
788 | (v_idx << I40E_PFINT_AEQCTL_MSIX_INDX_SHIFT) | | ||
789 | (qv_info->itr_idx << | ||
790 | I40E_PFINT_AEQCTL_ITR_INDX_SHIFT)); | ||
791 | |||
792 | wr32(hw, I40E_PFINT_AEQCTL, reg); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | return 0; | ||
797 | err: | ||
798 | kfree(ldev->qvlist_info); | ||
799 | ldev->qvlist_info = NULL; | ||
800 | return -EINVAL; | ||
801 | } | ||
802 | |||
803 | /** | ||
804 | * i40e_client_request_reset | ||
805 | * @ldev: pointer to L2 context. | ||
806 | * @client: Client pointer. | ||
807 | * @level: reset level | ||
808 | **/ | ||
809 | static void i40e_client_request_reset(struct i40e_info *ldev, | ||
810 | struct i40e_client *client, | ||
811 | u32 reset_level) | ||
812 | { | ||
813 | struct i40e_pf *pf = ldev->pf; | ||
814 | |||
815 | switch (reset_level) { | ||
816 | case I40E_CLIENT_RESET_LEVEL_PF: | ||
817 | set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); | ||
818 | break; | ||
819 | case I40E_CLIENT_RESET_LEVEL_CORE: | ||
820 | set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); | ||
821 | break; | ||
822 | default: | ||
823 | dev_warn(&pf->pdev->dev, | ||
824 | "Client %s instance for PF id %d request an unsupported reset: %d.\n", | ||
825 | client->name, pf->hw.pf_id, reset_level); | ||
826 | break; | ||
827 | } | ||
828 | |||
829 | i40e_service_event_schedule(pf); | ||
830 | } | ||
831 | |||
832 | /** | ||
833 | * i40e_client_update_vsi_ctxt | ||
834 | * @ldev: pointer to L2 context. | ||
835 | * @client: Client pointer. | ||
836 | * @is_vf: if this for the VF | ||
837 | * @vf_id: if is_vf true this carries the vf_id | ||
838 | * @flag: Any device level setting that needs to be done for PE | ||
839 | * @valid_flag: Bits in this match up and enable changing of flag bits | ||
840 | * | ||
841 | * Return 0 on success or < 0 on error | ||
842 | **/ | ||
843 | static int i40e_client_update_vsi_ctxt(struct i40e_info *ldev, | ||
844 | struct i40e_client *client, | ||
845 | bool is_vf, u32 vf_id, | ||
846 | u32 flag, u32 valid_flag) | ||
847 | { | ||
848 | struct i40e_pf *pf = ldev->pf; | ||
849 | struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; | ||
850 | struct i40e_vsi_context ctxt; | ||
851 | bool update = true; | ||
852 | i40e_status err; | ||
853 | |||
854 | /* TODO: for now do not allow setting VF's VSI setting */ | ||
855 | if (is_vf) | ||
856 | return -EINVAL; | ||
857 | |||
858 | ctxt.seid = pf->main_vsi_seid; | ||
859 | ctxt.pf_num = pf->hw.pf_id; | ||
860 | err = i40e_aq_get_vsi_params(&pf->hw, &ctxt, NULL); | ||
861 | ctxt.flags = I40E_AQ_VSI_TYPE_PF; | ||
862 | if (err) { | ||
863 | dev_info(&pf->pdev->dev, | ||
864 | "couldn't get PF vsi config, err %s aq_err %s\n", | ||
865 | i40e_stat_str(&pf->hw, err), | ||
866 | i40e_aq_str(&pf->hw, | ||
867 | pf->hw.aq.asq_last_status)); | ||
868 | return -ENOENT; | ||
869 | } | ||
870 | |||
871 | if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) && | ||
872 | (flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) { | ||
873 | ctxt.info.valid_sections = | ||
874 | cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID); | ||
875 | ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA; | ||
876 | } else if ((valid_flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE) && | ||
877 | !(flag & I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE)) { | ||
878 | ctxt.info.valid_sections = | ||
879 | cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID); | ||
880 | ctxt.info.queueing_opt_flags &= ~I40E_AQ_VSI_QUE_OPT_TCP_ENA; | ||
881 | } else { | ||
882 | update = false; | ||
883 | dev_warn(&pf->pdev->dev, | ||
884 | "Client %s instance for PF id %d request an unsupported Config: %x.\n", | ||
885 | client->name, pf->hw.pf_id, flag); | ||
886 | } | ||
887 | |||
888 | if (update) { | ||
889 | err = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); | ||
890 | if (err) { | ||
891 | dev_info(&pf->pdev->dev, | ||
892 | "update VSI ctxt for PE failed, err %s aq_err %s\n", | ||
893 | i40e_stat_str(&pf->hw, err), | ||
894 | i40e_aq_str(&pf->hw, | ||
895 | pf->hw.aq.asq_last_status)); | ||
896 | } | ||
897 | } | ||
898 | return err; | ||
899 | } | ||
900 | |||
901 | /** | ||
902 | * i40e_register_client - Register a i40e client driver with the L2 driver | ||
903 | * @client: pointer to the i40e_client struct | ||
904 | * | ||
905 | * Returns 0 on success or non-0 on error | ||
906 | **/ | ||
907 | int i40e_register_client(struct i40e_client *client) | ||
908 | { | ||
909 | int ret = 0; | ||
910 | enum i40e_vsi_type vsi_type; | ||
911 | |||
912 | if (!client) { | ||
913 | ret = -EIO; | ||
914 | goto out; | ||
915 | } | ||
916 | |||
917 | if (strlen(client->name) == 0) { | ||
918 | pr_info("i40e: Failed to register client with no name\n"); | ||
919 | ret = -EIO; | ||
920 | goto out; | ||
921 | } | ||
922 | |||
923 | mutex_lock(&i40e_client_mutex); | ||
924 | if (i40e_client_is_registered(client)) { | ||
925 | pr_info("i40e: Client %s has already been registered!\n", | ||
926 | client->name); | ||
927 | mutex_unlock(&i40e_client_mutex); | ||
928 | ret = -EEXIST; | ||
929 | goto out; | ||
930 | } | ||
931 | |||
932 | if ((client->version.major != I40E_CLIENT_VERSION_MAJOR) || | ||
933 | (client->version.minor != I40E_CLIENT_VERSION_MINOR)) { | ||
934 | pr_info("i40e: Failed to register client %s due to mismatched client interface version\n", | ||
935 | client->name); | ||
936 | pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n", | ||
937 | client->version.major, client->version.minor, | ||
938 | client->version.build, | ||
939 | i40e_client_interface_version_str); | ||
940 | mutex_unlock(&i40e_client_mutex); | ||
941 | ret = -EIO; | ||
942 | goto out; | ||
943 | } | ||
944 | |||
945 | vsi_type = i40e_client_type_to_vsi_type(client->type); | ||
946 | if (vsi_type == I40E_VSI_TYPE_UNKNOWN) { | ||
947 | pr_info("i40e: Failed to register client %s due to unknown client type %d\n", | ||
948 | client->name, client->type); | ||
949 | mutex_unlock(&i40e_client_mutex); | ||
950 | ret = -EIO; | ||
951 | goto out; | ||
952 | } | ||
953 | list_add(&client->list, &i40e_clients); | ||
954 | set_bit(__I40E_CLIENT_REGISTERED, &client->state); | ||
955 | mutex_unlock(&i40e_client_mutex); | ||
956 | |||
957 | if (i40e_client_prepare(client)) { | ||
958 | ret = -EIO; | ||
959 | goto out; | ||
960 | } | ||
961 | |||
962 | pr_info("i40e: Registered client %s with return code %d\n", | ||
963 | client->name, ret); | ||
964 | out: | ||
965 | return ret; | ||
966 | } | ||
967 | EXPORT_SYMBOL(i40e_register_client); | ||
968 | |||
969 | /** | ||
970 | * i40e_unregister_client - Unregister a i40e client driver with the L2 driver | ||
971 | * @client: pointer to the i40e_client struct | ||
972 | * | ||
973 | * Returns 0 on success or non-0 on error | ||
974 | **/ | ||
975 | int i40e_unregister_client(struct i40e_client *client) | ||
976 | { | ||
977 | int ret = 0; | ||
978 | |||
979 | /* When a unregister request comes through we would have to send | ||
980 | * a close for each of the client instances that were opened. | ||
981 | * client_release function is called to handle this. | ||
982 | */ | ||
983 | if (!client || i40e_client_release(client)) { | ||
984 | ret = -EIO; | ||
985 | goto out; | ||
986 | } | ||
987 | |||
988 | /* TODO: check if device is in reset, or if that matters? */ | ||
989 | mutex_lock(&i40e_client_mutex); | ||
990 | if (!i40e_client_is_registered(client)) { | ||
991 | pr_info("i40e: Client %s has not been registered\n", | ||
992 | client->name); | ||
993 | mutex_unlock(&i40e_client_mutex); | ||
994 | ret = -ENODEV; | ||
995 | goto out; | ||
996 | } | ||
997 | if (atomic_read(&client->ref_cnt) == 0) { | ||
998 | clear_bit(__I40E_CLIENT_REGISTERED, &client->state); | ||
999 | list_del(&client->list); | ||
1000 | pr_info("i40e: Unregistered client %s with return code %d\n", | ||
1001 | client->name, ret); | ||
1002 | } else { | ||
1003 | ret = I40E_ERR_NOT_READY; | ||
1004 | pr_err("i40e: Client %s failed unregister - client has open instances\n", | ||
1005 | client->name); | ||
1006 | } | ||
1007 | |||
1008 | mutex_unlock(&i40e_client_mutex); | ||
1009 | out: | ||
1010 | return ret; | ||
1011 | } | ||
1012 | EXPORT_SYMBOL(i40e_unregister_client); | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.h b/drivers/net/ethernet/intel/i40e/i40e_client.h new file mode 100644 index 000000000000..bf6b453d93a1 --- /dev/null +++ b/drivers/net/ethernet/intel/i40e/i40e_client.h | |||
@@ -0,0 +1,232 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Intel Ethernet Controller XL710 Family Linux Driver | ||
4 | * Copyright(c) 2013 - 2015 Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in | ||
19 | * the file called "COPYING". | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | ******************************************************************************/ | ||
26 | |||
27 | #ifndef _I40E_CLIENT_H_ | ||
28 | #define _I40E_CLIENT_H_ | ||
29 | |||
30 | #define I40E_CLIENT_STR_LENGTH 10 | ||
31 | |||
32 | /* Client interface version should be updated anytime there is a change in the | ||
33 | * existing APIs or data structures. | ||
34 | */ | ||
35 | #define I40E_CLIENT_VERSION_MAJOR 0 | ||
36 | #define I40E_CLIENT_VERSION_MINOR 01 | ||
37 | #define I40E_CLIENT_VERSION_BUILD 00 | ||
38 | #define I40E_CLIENT_VERSION_STR \ | ||
39 | XSTRINGIFY(I40E_CLIENT_VERSION_MAJOR) "." \ | ||
40 | XSTRINGIFY(I40E_CLIENT_VERSION_MINOR) "." \ | ||
41 | XSTRINGIFY(I40E_CLIENT_VERSION_BUILD) | ||
42 | |||
43 | struct i40e_client_version { | ||
44 | u8 major; | ||
45 | u8 minor; | ||
46 | u8 build; | ||
47 | u8 rsvd; | ||
48 | }; | ||
49 | |||
50 | enum i40e_client_state { | ||
51 | __I40E_CLIENT_NULL, | ||
52 | __I40E_CLIENT_REGISTERED | ||
53 | }; | ||
54 | |||
55 | enum i40e_client_instance_state { | ||
56 | __I40E_CLIENT_INSTANCE_NONE, | ||
57 | __I40E_CLIENT_INSTANCE_OPENED, | ||
58 | }; | ||
59 | |||
60 | enum i40e_client_type { | ||
61 | I40E_CLIENT_IWARP, | ||
62 | I40E_CLIENT_VMDQ2 | ||
63 | }; | ||
64 | |||
65 | struct i40e_ops; | ||
66 | struct i40e_client; | ||
67 | |||
68 | /* HW does not define a type value for AEQ; only for RX/TX and CEQ. | ||
69 | * In order for us to keep the interface simple, SW will define a | ||
70 | * unique type value for AEQ. | ||
71 | */ | ||
72 | #define I40E_QUEUE_TYPE_PE_AEQ 0x80 | ||
73 | #define I40E_QUEUE_INVALID_IDX 0xFFFF | ||
74 | |||
75 | struct i40e_qv_info { | ||
76 | u32 v_idx; /* msix_vector */ | ||
77 | u16 ceq_idx; | ||
78 | u16 aeq_idx; | ||
79 | u8 itr_idx; | ||
80 | }; | ||
81 | |||
82 | struct i40e_qvlist_info { | ||
83 | u32 num_vectors; | ||
84 | struct i40e_qv_info qv_info[1]; | ||
85 | }; | ||
86 | |||
87 | #define I40E_CLIENT_MSIX_ALL 0xFFFFFFFF | ||
88 | |||
89 | /* set of LAN parameters useful for clients managed by LAN */ | ||
90 | |||
91 | /* Struct to hold per priority info */ | ||
92 | struct i40e_prio_qos_params { | ||
93 | u16 qs_handle; /* qs handle for prio */ | ||
94 | u8 tc; /* TC mapped to prio */ | ||
95 | u8 reserved; | ||
96 | }; | ||
97 | |||
98 | #define I40E_CLIENT_MAX_USER_PRIORITY 8 | ||
99 | /* Struct to hold Client QoS */ | ||
100 | struct i40e_qos_params { | ||
101 | struct i40e_prio_qos_params prio_qos[I40E_CLIENT_MAX_USER_PRIORITY]; | ||
102 | }; | ||
103 | |||
104 | struct i40e_params { | ||
105 | struct i40e_qos_params qos; | ||
106 | u16 mtu; | ||
107 | }; | ||
108 | |||
109 | /* Structure to hold Lan device info for a client device */ | ||
110 | struct i40e_info { | ||
111 | struct i40e_client_version version; | ||
112 | u8 lanmac[6]; | ||
113 | struct net_device *netdev; | ||
114 | struct pci_dev *pcidev; | ||
115 | u8 __iomem *hw_addr; | ||
116 | u8 fid; /* function id, PF id or VF id */ | ||
117 | #define I40E_CLIENT_FTYPE_PF 0 | ||
118 | #define I40E_CLIENT_FTYPE_VF 1 | ||
119 | u8 ftype; /* function type, PF or VF */ | ||
120 | void *pf; | ||
121 | |||
122 | /* All L2 params that could change during the life span of the PF | ||
123 | * and needs to be communicated to the client when they change | ||
124 | */ | ||
125 | struct i40e_qvlist_info *qvlist_info; | ||
126 | struct i40e_params params; | ||
127 | struct i40e_ops *ops; | ||
128 | |||
129 | u16 msix_count; /* number of msix vectors*/ | ||
130 | /* Array down below will be dynamically allocated based on msix_count */ | ||
131 | struct msix_entry *msix_entries; | ||
132 | u16 itr_index; /* Which ITR index the PE driver is suppose to use */ | ||
133 | u16 fw_maj_ver; /* firmware major version */ | ||
134 | u16 fw_min_ver; /* firmware minor version */ | ||
135 | u32 fw_build; /* firmware build number */ | ||
136 | }; | ||
137 | |||
138 | #define I40E_CLIENT_RESET_LEVEL_PF 1 | ||
139 | #define I40E_CLIENT_RESET_LEVEL_CORE 2 | ||
140 | #define I40E_CLIENT_VSI_FLAG_TCP_PACKET_ENABLE BIT(1) | ||
141 | |||
142 | struct i40e_ops { | ||
143 | /* setup_q_vector_list enables queues with a particular vector */ | ||
144 | int (*setup_qvlist)(struct i40e_info *ldev, struct i40e_client *client, | ||
145 | struct i40e_qvlist_info *qv_info); | ||
146 | |||
147 | int (*virtchnl_send)(struct i40e_info *ldev, struct i40e_client *client, | ||
148 | u32 vf_id, u8 *msg, u16 len); | ||
149 | |||
150 | /* If the PE Engine is unresponsive, RDMA driver can request a reset. | ||
151 | * The level helps determine the level of reset being requested. | ||
152 | */ | ||
153 | void (*request_reset)(struct i40e_info *ldev, | ||
154 | struct i40e_client *client, u32 level); | ||
155 | |||
156 | /* API for the RDMA driver to set certain VSI flags that control | ||
157 | * PE Engine. | ||
158 | */ | ||
159 | int (*update_vsi_ctxt)(struct i40e_info *ldev, | ||
160 | struct i40e_client *client, | ||
161 | bool is_vf, u32 vf_id, | ||
162 | u32 flag, u32 valid_flag); | ||
163 | }; | ||
164 | |||
165 | struct i40e_client_ops { | ||
166 | /* Should be called from register_client() or whenever PF is ready | ||
167 | * to create a specific client instance. | ||
168 | */ | ||
169 | int (*open)(struct i40e_info *ldev, struct i40e_client *client); | ||
170 | |||
171 | /* Should be called when netdev is unavailable or when unregister | ||
172 | * call comes in. If the close is happenening due to a reset being | ||
173 | * triggered set the reset bit to true. | ||
174 | */ | ||
175 | void (*close)(struct i40e_info *ldev, struct i40e_client *client, | ||
176 | bool reset); | ||
177 | |||
178 | /* called when some l2 managed parameters changes - mtu */ | ||
179 | void (*l2_param_change)(struct i40e_info *ldev, | ||
180 | struct i40e_client *client, | ||
181 | struct i40e_params *params); | ||
182 | |||
183 | int (*virtchnl_receive)(struct i40e_info *ldev, | ||
184 | struct i40e_client *client, u32 vf_id, | ||
185 | u8 *msg, u16 len); | ||
186 | |||
187 | /* called when a VF is reset by the PF */ | ||
188 | void (*vf_reset)(struct i40e_info *ldev, | ||
189 | struct i40e_client *client, u32 vf_id); | ||
190 | |||
191 | /* called when the number of VFs changes */ | ||
192 | void (*vf_enable)(struct i40e_info *ldev, | ||
193 | struct i40e_client *client, u32 num_vfs); | ||
194 | |||
195 | /* returns true if VF is capable of specified offload */ | ||
196 | int (*vf_capable)(struct i40e_info *ldev, | ||
197 | struct i40e_client *client, u32 vf_id); | ||
198 | }; | ||
199 | |||
200 | /* Client device */ | ||
201 | struct i40e_client_instance { | ||
202 | struct list_head list; | ||
203 | struct i40e_info lan_info; | ||
204 | struct i40e_client *client; | ||
205 | unsigned long state; | ||
206 | /* A count of all the in-progress calls to the client */ | ||
207 | atomic_t ref_cnt; | ||
208 | }; | ||
209 | |||
210 | struct i40e_client { | ||
211 | struct list_head list; /* list of registered clients */ | ||
212 | char name[I40E_CLIENT_STR_LENGTH]; | ||
213 | struct i40e_client_version version; | ||
214 | unsigned long state; /* client state */ | ||
215 | atomic_t ref_cnt; /* Count of all the client devices of this kind */ | ||
216 | u32 flags; | ||
217 | #define I40E_CLIENT_FLAGS_LAUNCH_ON_PROBE BIT(0) | ||
218 | #define I40E_TX_FLAGS_NOTIFY_OTHER_EVENTS BIT(2) | ||
219 | enum i40e_client_type type; | ||
220 | struct i40e_client_ops *ops; /* client ops provided by the client */ | ||
221 | }; | ||
222 | |||
223 | static inline bool i40e_client_is_registered(struct i40e_client *client) | ||
224 | { | ||
225 | return test_bit(__I40E_CLIENT_REGISTERED, &client->state); | ||
226 | } | ||
227 | |||
228 | /* used by clients */ | ||
229 | int i40e_register_client(struct i40e_client *client); | ||
230 | int i40e_unregister_client(struct i40e_client *client); | ||
231 | |||
232 | #endif /* _I40E_CLIENT_H_ */ | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8f3b53e0dc46..1df2629d3705 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c | |||
@@ -290,7 +290,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id) | |||
290 | * | 290 | * |
291 | * If not already scheduled, this puts the task into the work queue | 291 | * If not already scheduled, this puts the task into the work queue |
292 | **/ | 292 | **/ |
293 | static void i40e_service_event_schedule(struct i40e_pf *pf) | 293 | void i40e_service_event_schedule(struct i40e_pf *pf) |
294 | { | 294 | { |
295 | if (!test_bit(__I40E_DOWN, &pf->state) && | 295 | if (!test_bit(__I40E_DOWN, &pf->state) && |
296 | !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) && | 296 | !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) && |
@@ -2212,7 +2212,7 @@ static int i40e_change_mtu(struct net_device *netdev, int new_mtu) | |||
2212 | netdev->mtu = new_mtu; | 2212 | netdev->mtu = new_mtu; |
2213 | if (netif_running(netdev)) | 2213 | if (netif_running(netdev)) |
2214 | i40e_vsi_reinit_locked(vsi); | 2214 | i40e_vsi_reinit_locked(vsi); |
2215 | 2215 | i40e_notify_client_of_l2_param_changes(vsi); | |
2216 | return 0; | 2216 | return 0; |
2217 | } | 2217 | } |
2218 | 2218 | ||
@@ -4166,6 +4166,9 @@ static void i40e_clear_interrupt_scheme(struct i40e_pf *pf) | |||
4166 | free_irq(pf->msix_entries[0].vector, pf); | 4166 | free_irq(pf->msix_entries[0].vector, pf); |
4167 | } | 4167 | } |
4168 | 4168 | ||
4169 | i40e_put_lump(pf->irq_pile, pf->iwarp_base_vector, | ||
4170 | I40E_IWARP_IRQ_PILE_ID); | ||
4171 | |||
4169 | i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1); | 4172 | i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1); |
4170 | for (i = 0; i < pf->num_alloc_vsi; i++) | 4173 | for (i = 0; i < pf->num_alloc_vsi; i++) |
4171 | if (pf->vsi[i]) | 4174 | if (pf->vsi[i]) |
@@ -4209,12 +4212,17 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi) | |||
4209 | **/ | 4212 | **/ |
4210 | static void i40e_vsi_close(struct i40e_vsi *vsi) | 4213 | static void i40e_vsi_close(struct i40e_vsi *vsi) |
4211 | { | 4214 | { |
4215 | bool reset = false; | ||
4216 | |||
4212 | if (!test_and_set_bit(__I40E_DOWN, &vsi->state)) | 4217 | if (!test_and_set_bit(__I40E_DOWN, &vsi->state)) |
4213 | i40e_down(vsi); | 4218 | i40e_down(vsi); |
4214 | i40e_vsi_free_irq(vsi); | 4219 | i40e_vsi_free_irq(vsi); |
4215 | i40e_vsi_free_tx_resources(vsi); | 4220 | i40e_vsi_free_tx_resources(vsi); |
4216 | i40e_vsi_free_rx_resources(vsi); | 4221 | i40e_vsi_free_rx_resources(vsi); |
4217 | vsi->current_netdev_flags = 0; | 4222 | vsi->current_netdev_flags = 0; |
4223 | if (test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) | ||
4224 | reset = true; | ||
4225 | i40e_notify_client_of_netdev_close(vsi, reset); | ||
4218 | } | 4226 | } |
4219 | 4227 | ||
4220 | /** | 4228 | /** |
@@ -4831,6 +4839,12 @@ static int i40e_vsi_config_tc(struct i40e_vsi *vsi, u8 enabled_tc) | |||
4831 | ctxt.info = vsi->info; | 4839 | ctxt.info = vsi->info; |
4832 | i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false); | 4840 | i40e_vsi_setup_queue_map(vsi, &ctxt, enabled_tc, false); |
4833 | 4841 | ||
4842 | if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) { | ||
4843 | ctxt.info.valid_sections |= | ||
4844 | cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID); | ||
4845 | ctxt.info.queueing_opt_flags |= I40E_AQ_VSI_QUE_OPT_TCP_ENA; | ||
4846 | } | ||
4847 | |||
4834 | /* Update the VSI after updating the VSI queue-mapping information */ | 4848 | /* Update the VSI after updating the VSI queue-mapping information */ |
4835 | ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); | 4849 | ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL); |
4836 | if (ret) { | 4850 | if (ret) { |
@@ -4974,6 +4988,7 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf) | |||
4974 | if (pf->vsi[v]->netdev) | 4988 | if (pf->vsi[v]->netdev) |
4975 | i40e_dcbnl_set_all(pf->vsi[v]); | 4989 | i40e_dcbnl_set_all(pf->vsi[v]); |
4976 | } | 4990 | } |
4991 | i40e_notify_client_of_l2_param_changes(pf->vsi[v]); | ||
4977 | } | 4992 | } |
4978 | } | 4993 | } |
4979 | 4994 | ||
@@ -5173,6 +5188,11 @@ static int i40e_up_complete(struct i40e_vsi *vsi) | |||
5173 | } | 5188 | } |
5174 | i40e_fdir_filter_restore(vsi); | 5189 | i40e_fdir_filter_restore(vsi); |
5175 | } | 5190 | } |
5191 | |||
5192 | /* On the next run of the service_task, notify any clients of the new | ||
5193 | * opened netdev | ||
5194 | */ | ||
5195 | pf->flags |= I40E_FLAG_SERVICE_CLIENT_REQUESTED; | ||
5176 | i40e_service_event_schedule(pf); | 5196 | i40e_service_event_schedule(pf); |
5177 | 5197 | ||
5178 | return 0; | 5198 | return 0; |
@@ -5351,6 +5371,8 @@ int i40e_open(struct net_device *netdev) | |||
5351 | geneve_get_rx_port(netdev); | 5371 | geneve_get_rx_port(netdev); |
5352 | #endif | 5372 | #endif |
5353 | 5373 | ||
5374 | i40e_notify_client_of_netdev_open(vsi); | ||
5375 | |||
5354 | return 0; | 5376 | return 0; |
5355 | } | 5377 | } |
5356 | 5378 | ||
@@ -6015,6 +6037,7 @@ static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up) | |||
6015 | case I40E_VSI_SRIOV: | 6037 | case I40E_VSI_SRIOV: |
6016 | case I40E_VSI_VMDQ2: | 6038 | case I40E_VSI_VMDQ2: |
6017 | case I40E_VSI_CTRL: | 6039 | case I40E_VSI_CTRL: |
6040 | case I40E_VSI_IWARP: | ||
6018 | case I40E_VSI_MIRROR: | 6041 | case I40E_VSI_MIRROR: |
6019 | default: | 6042 | default: |
6020 | /* there is no notification for other VSIs */ | 6043 | /* there is no notification for other VSIs */ |
@@ -7116,6 +7139,7 @@ static void i40e_service_task(struct work_struct *work) | |||
7116 | i40e_vc_process_vflr_event(pf); | 7139 | i40e_vc_process_vflr_event(pf); |
7117 | i40e_watchdog_subtask(pf); | 7140 | i40e_watchdog_subtask(pf); |
7118 | i40e_fdir_reinit_subtask(pf); | 7141 | i40e_fdir_reinit_subtask(pf); |
7142 | i40e_client_subtask(pf); | ||
7119 | i40e_sync_filters_subtask(pf); | 7143 | i40e_sync_filters_subtask(pf); |
7120 | i40e_sync_udp_filters_subtask(pf); | 7144 | i40e_sync_udp_filters_subtask(pf); |
7121 | i40e_clean_adminq_subtask(pf); | 7145 | i40e_clean_adminq_subtask(pf); |
@@ -7520,6 +7544,7 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7520 | int vectors_left; | 7544 | int vectors_left; |
7521 | int v_budget, i; | 7545 | int v_budget, i; |
7522 | int v_actual; | 7546 | int v_actual; |
7547 | int iwarp_requested = 0; | ||
7523 | 7548 | ||
7524 | if (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) | 7549 | if (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) |
7525 | return -ENODEV; | 7550 | return -ENODEV; |
@@ -7533,6 +7558,7 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7533 | * is governed by number of cpus in the system. | 7558 | * is governed by number of cpus in the system. |
7534 | * - assumes symmetric Tx/Rx pairing | 7559 | * - assumes symmetric Tx/Rx pairing |
7535 | * - The number of VMDq pairs | 7560 | * - The number of VMDq pairs |
7561 | * - The CPU count within the NUMA node if iWARP is enabled | ||
7536 | #ifdef I40E_FCOE | 7562 | #ifdef I40E_FCOE |
7537 | * - The number of FCOE qps. | 7563 | * - The number of FCOE qps. |
7538 | #endif | 7564 | #endif |
@@ -7579,6 +7605,16 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7579 | } | 7605 | } |
7580 | 7606 | ||
7581 | #endif | 7607 | #endif |
7608 | /* can we reserve enough for iWARP? */ | ||
7609 | if (pf->flags & I40E_FLAG_IWARP_ENABLED) { | ||
7610 | if (!vectors_left) | ||
7611 | pf->num_iwarp_msix = 0; | ||
7612 | else if (vectors_left < pf->num_iwarp_msix) | ||
7613 | pf->num_iwarp_msix = 1; | ||
7614 | v_budget += pf->num_iwarp_msix; | ||
7615 | vectors_left -= pf->num_iwarp_msix; | ||
7616 | } | ||
7617 | |||
7582 | /* any vectors left over go for VMDq support */ | 7618 | /* any vectors left over go for VMDq support */ |
7583 | if (pf->flags & I40E_FLAG_VMDQ_ENABLED) { | 7619 | if (pf->flags & I40E_FLAG_VMDQ_ENABLED) { |
7584 | int vmdq_vecs_wanted = pf->num_vmdq_vsis * pf->num_vmdq_qps; | 7620 | int vmdq_vecs_wanted = pf->num_vmdq_vsis * pf->num_vmdq_qps; |
@@ -7613,6 +7649,8 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7613 | * of these features based on the policy and at the end disable | 7649 | * of these features based on the policy and at the end disable |
7614 | * the features that did not get any vectors. | 7650 | * the features that did not get any vectors. |
7615 | */ | 7651 | */ |
7652 | iwarp_requested = pf->num_iwarp_msix; | ||
7653 | pf->num_iwarp_msix = 0; | ||
7616 | #ifdef I40E_FCOE | 7654 | #ifdef I40E_FCOE |
7617 | pf->num_fcoe_qps = 0; | 7655 | pf->num_fcoe_qps = 0; |
7618 | pf->num_fcoe_msix = 0; | 7656 | pf->num_fcoe_msix = 0; |
@@ -7651,17 +7689,33 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7651 | pf->num_lan_msix = 1; | 7689 | pf->num_lan_msix = 1; |
7652 | break; | 7690 | break; |
7653 | case 3: | 7691 | case 3: |
7692 | if (pf->flags & I40E_FLAG_IWARP_ENABLED) { | ||
7693 | pf->num_lan_msix = 1; | ||
7694 | pf->num_iwarp_msix = 1; | ||
7695 | } else { | ||
7696 | pf->num_lan_msix = 2; | ||
7697 | } | ||
7654 | #ifdef I40E_FCOE | 7698 | #ifdef I40E_FCOE |
7655 | /* give one vector to FCoE */ | 7699 | /* give one vector to FCoE */ |
7656 | if (pf->flags & I40E_FLAG_FCOE_ENABLED) { | 7700 | if (pf->flags & I40E_FLAG_FCOE_ENABLED) { |
7657 | pf->num_lan_msix = 1; | 7701 | pf->num_lan_msix = 1; |
7658 | pf->num_fcoe_msix = 1; | 7702 | pf->num_fcoe_msix = 1; |
7659 | } | 7703 | } |
7660 | #else | ||
7661 | pf->num_lan_msix = 2; | ||
7662 | #endif | 7704 | #endif |
7663 | break; | 7705 | break; |
7664 | default: | 7706 | default: |
7707 | if (pf->flags & I40E_FLAG_IWARP_ENABLED) { | ||
7708 | pf->num_iwarp_msix = min_t(int, (vec / 3), | ||
7709 | iwarp_requested); | ||
7710 | pf->num_vmdq_vsis = min_t(int, (vec / 3), | ||
7711 | I40E_DEFAULT_NUM_VMDQ_VSI); | ||
7712 | } else { | ||
7713 | pf->num_vmdq_vsis = min_t(int, (vec / 2), | ||
7714 | I40E_DEFAULT_NUM_VMDQ_VSI); | ||
7715 | } | ||
7716 | pf->num_lan_msix = min_t(int, | ||
7717 | (vec - (pf->num_iwarp_msix + pf->num_vmdq_vsis)), | ||
7718 | pf->num_lan_msix); | ||
7665 | #ifdef I40E_FCOE | 7719 | #ifdef I40E_FCOE |
7666 | /* give one vector to FCoE */ | 7720 | /* give one vector to FCoE */ |
7667 | if (pf->flags & I40E_FLAG_FCOE_ENABLED) { | 7721 | if (pf->flags & I40E_FLAG_FCOE_ENABLED) { |
@@ -7669,8 +7723,6 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7669 | vec--; | 7723 | vec--; |
7670 | } | 7724 | } |
7671 | #endif | 7725 | #endif |
7672 | /* give the rest to the PF */ | ||
7673 | pf->num_lan_msix = min_t(int, vec, pf->num_lan_qps); | ||
7674 | break; | 7726 | break; |
7675 | } | 7727 | } |
7676 | } | 7728 | } |
@@ -7680,6 +7732,12 @@ static int i40e_init_msix(struct i40e_pf *pf) | |||
7680 | dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n"); | 7732 | dev_info(&pf->pdev->dev, "VMDq disabled, not enough MSI-X vectors\n"); |
7681 | pf->flags &= ~I40E_FLAG_VMDQ_ENABLED; | 7733 | pf->flags &= ~I40E_FLAG_VMDQ_ENABLED; |
7682 | } | 7734 | } |
7735 | |||
7736 | if ((pf->flags & I40E_FLAG_IWARP_ENABLED) && | ||
7737 | (pf->num_iwarp_msix == 0)) { | ||
7738 | dev_info(&pf->pdev->dev, "IWARP disabled, not enough MSI-X vectors\n"); | ||
7739 | pf->flags &= ~I40E_FLAG_IWARP_ENABLED; | ||
7740 | } | ||
7683 | #ifdef I40E_FCOE | 7741 | #ifdef I40E_FCOE |
7684 | 7742 | ||
7685 | if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) { | 7743 | if ((pf->flags & I40E_FLAG_FCOE_ENABLED) && (pf->num_fcoe_msix == 0)) { |
@@ -7771,6 +7829,7 @@ static int i40e_init_interrupt_scheme(struct i40e_pf *pf) | |||
7771 | vectors = i40e_init_msix(pf); | 7829 | vectors = i40e_init_msix(pf); |
7772 | if (vectors < 0) { | 7830 | if (vectors < 0) { |
7773 | pf->flags &= ~(I40E_FLAG_MSIX_ENABLED | | 7831 | pf->flags &= ~(I40E_FLAG_MSIX_ENABLED | |
7832 | I40E_FLAG_IWARP_ENABLED | | ||
7774 | #ifdef I40E_FCOE | 7833 | #ifdef I40E_FCOE |
7775 | I40E_FLAG_FCOE_ENABLED | | 7834 | I40E_FLAG_FCOE_ENABLED | |
7776 | #endif | 7835 | #endif |
@@ -8373,6 +8432,12 @@ static int i40e_sw_init(struct i40e_pf *pf) | |||
8373 | pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf); | 8432 | pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf); |
8374 | } | 8433 | } |
8375 | 8434 | ||
8435 | if (pf->hw.func_caps.iwarp) { | ||
8436 | pf->flags |= I40E_FLAG_IWARP_ENABLED; | ||
8437 | /* IWARP needs one extra vector for CQP just like MISC.*/ | ||
8438 | pf->num_iwarp_msix = (int)num_online_cpus() + 1; | ||
8439 | } | ||
8440 | |||
8376 | #ifdef I40E_FCOE | 8441 | #ifdef I40E_FCOE |
8377 | i40e_init_pf_fcoe(pf); | 8442 | i40e_init_pf_fcoe(pf); |
8378 | 8443 | ||
@@ -9216,6 +9281,13 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) | |||
9216 | cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB); | 9281 | cpu_to_le16(I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB); |
9217 | } | 9282 | } |
9218 | 9283 | ||
9284 | if (vsi->back->flags & I40E_FLAG_IWARP_ENABLED) { | ||
9285 | ctxt.info.valid_sections |= | ||
9286 | cpu_to_le16(I40E_AQ_VSI_PROP_QUEUE_OPT_VALID); | ||
9287 | ctxt.info.queueing_opt_flags |= | ||
9288 | I40E_AQ_VSI_QUE_OPT_TCP_ENA; | ||
9289 | } | ||
9290 | |||
9219 | ctxt.info.valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID); | 9291 | ctxt.info.valid_sections |= cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID); |
9220 | ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL; | 9292 | ctxt.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_ALL; |
9221 | if (pf->vf[vsi->vf_id].spoofchk) { | 9293 | if (pf->vf[vsi->vf_id].spoofchk) { |
@@ -9239,6 +9311,10 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) | |||
9239 | break; | 9311 | break; |
9240 | 9312 | ||
9241 | #endif /* I40E_FCOE */ | 9313 | #endif /* I40E_FCOE */ |
9314 | case I40E_VSI_IWARP: | ||
9315 | /* send down message to iWARP */ | ||
9316 | break; | ||
9317 | |||
9242 | default: | 9318 | default: |
9243 | return -ENODEV; | 9319 | return -ENODEV; |
9244 | } | 9320 | } |
@@ -10350,6 +10426,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) | |||
10350 | 10426 | ||
10351 | /* make sure all the fancies are disabled */ | 10427 | /* make sure all the fancies are disabled */ |
10352 | pf->flags &= ~(I40E_FLAG_RSS_ENABLED | | 10428 | pf->flags &= ~(I40E_FLAG_RSS_ENABLED | |
10429 | I40E_FLAG_IWARP_ENABLED | | ||
10353 | #ifdef I40E_FCOE | 10430 | #ifdef I40E_FCOE |
10354 | I40E_FLAG_FCOE_ENABLED | | 10431 | I40E_FLAG_FCOE_ENABLED | |
10355 | #endif | 10432 | #endif |
@@ -10367,6 +10444,7 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) | |||
10367 | queues_left -= pf->num_lan_qps; | 10444 | queues_left -= pf->num_lan_qps; |
10368 | 10445 | ||
10369 | pf->flags &= ~(I40E_FLAG_RSS_ENABLED | | 10446 | pf->flags &= ~(I40E_FLAG_RSS_ENABLED | |
10447 | I40E_FLAG_IWARP_ENABLED | | ||
10370 | #ifdef I40E_FCOE | 10448 | #ifdef I40E_FCOE |
10371 | I40E_FLAG_FCOE_ENABLED | | 10449 | I40E_FLAG_FCOE_ENABLED | |
10372 | #endif | 10450 | #endif |
@@ -10959,7 +11037,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
10959 | } | 11037 | } |
10960 | #endif /* CONFIG_PCI_IOV */ | 11038 | #endif /* CONFIG_PCI_IOV */ |
10961 | 11039 | ||
10962 | pfs_found++; | 11040 | if (pf->flags & I40E_FLAG_IWARP_ENABLED) { |
11041 | pf->iwarp_base_vector = i40e_get_lump(pf, pf->irq_pile, | ||
11042 | pf->num_iwarp_msix, | ||
11043 | I40E_IWARP_IRQ_PILE_ID); | ||
11044 | if (pf->iwarp_base_vector < 0) { | ||
11045 | dev_info(&pdev->dev, | ||
11046 | "failed to get tracking for %d vectors for IWARP err=%d\n", | ||
11047 | pf->num_iwarp_msix, pf->iwarp_base_vector); | ||
11048 | pf->flags &= ~I40E_FLAG_IWARP_ENABLED; | ||
11049 | } | ||
11050 | } | ||
10963 | 11051 | ||
10964 | i40e_dbg_pf_init(pf); | 11052 | i40e_dbg_pf_init(pf); |
10965 | 11053 | ||
@@ -10970,6 +11058,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
10970 | mod_timer(&pf->service_timer, | 11058 | mod_timer(&pf->service_timer, |
10971 | round_jiffies(jiffies + pf->service_timer_period)); | 11059 | round_jiffies(jiffies + pf->service_timer_period)); |
10972 | 11060 | ||
11061 | /* add this PF to client device list and launch a client service task */ | ||
11062 | err = i40e_lan_add_device(pf); | ||
11063 | if (err) | ||
11064 | dev_info(&pdev->dev, "Failed to add PF to client API service list: %d\n", | ||
11065 | err); | ||
11066 | |||
10973 | #ifdef I40E_FCOE | 11067 | #ifdef I40E_FCOE |
10974 | /* create FCoE interface */ | 11068 | /* create FCoE interface */ |
10975 | i40e_fcoe_vsi_setup(pf); | 11069 | i40e_fcoe_vsi_setup(pf); |
@@ -11140,6 +11234,13 @@ static void i40e_remove(struct pci_dev *pdev) | |||
11140 | if (pf->vsi[pf->lan_vsi]) | 11234 | if (pf->vsi[pf->lan_vsi]) |
11141 | i40e_vsi_release(pf->vsi[pf->lan_vsi]); | 11235 | i40e_vsi_release(pf->vsi[pf->lan_vsi]); |
11142 | 11236 | ||
11237 | /* remove attached clients */ | ||
11238 | ret_code = i40e_lan_del_device(pf); | ||
11239 | if (ret_code) { | ||
11240 | dev_warn(&pdev->dev, "Failed to delete client device: %d\n", | ||
11241 | ret_code); | ||
11242 | } | ||
11243 | |||
11143 | /* shutdown and destroy the HMC */ | 11244 | /* shutdown and destroy the HMC */ |
11144 | if (pf->hw.hmc.hmc_obj) { | 11245 | if (pf->hw.hmc.hmc_obj) { |
11145 | ret_code = i40e_shutdown_lan_hmc(&pf->hw); | 11246 | ret_code = i40e_shutdown_lan_hmc(&pf->hw); |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index dd2da356d9a1..79e975d29a1e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h | |||
@@ -78,7 +78,7 @@ enum i40e_debug_mask { | |||
78 | I40E_DEBUG_DCB = 0x00000400, | 78 | I40E_DEBUG_DCB = 0x00000400, |
79 | I40E_DEBUG_DIAG = 0x00000800, | 79 | I40E_DEBUG_DIAG = 0x00000800, |
80 | I40E_DEBUG_FD = 0x00001000, | 80 | I40E_DEBUG_FD = 0x00001000, |
81 | 81 | I40E_DEBUG_IWARP = 0x00F00000, | |
82 | I40E_DEBUG_AQ_MESSAGE = 0x01000000, | 82 | I40E_DEBUG_AQ_MESSAGE = 0x01000000, |
83 | I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000, | 83 | I40E_DEBUG_AQ_DESCRIPTOR = 0x02000000, |
84 | I40E_DEBUG_AQ_DESC_BUFFER = 0x04000000, | 84 | I40E_DEBUG_AQ_DESC_BUFFER = 0x04000000, |
@@ -144,6 +144,7 @@ enum i40e_vsi_type { | |||
144 | I40E_VSI_MIRROR = 5, | 144 | I40E_VSI_MIRROR = 5, |
145 | I40E_VSI_SRIOV = 6, | 145 | I40E_VSI_SRIOV = 6, |
146 | I40E_VSI_FDIR = 7, | 146 | I40E_VSI_FDIR = 7, |
147 | I40E_VSI_IWARP = 8, | ||
147 | I40E_VSI_TYPE_UNKNOWN | 148 | I40E_VSI_TYPE_UNKNOWN |
148 | }; | 149 | }; |
149 | 150 | ||
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index 3226946bf3d4..ab866cf3dc18 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | |||
@@ -81,6 +81,9 @@ enum i40e_virtchnl_ops { | |||
81 | I40E_VIRTCHNL_OP_GET_STATS = 15, | 81 | I40E_VIRTCHNL_OP_GET_STATS = 15, |
82 | I40E_VIRTCHNL_OP_FCOE = 16, | 82 | I40E_VIRTCHNL_OP_FCOE = 16, |
83 | I40E_VIRTCHNL_OP_EVENT = 17, | 83 | I40E_VIRTCHNL_OP_EVENT = 17, |
84 | I40E_VIRTCHNL_OP_IWARP = 20, | ||
85 | I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP = 21, | ||
86 | I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP = 22, | ||
84 | }; | 87 | }; |
85 | 88 | ||
86 | /* Virtual channel message descriptor. This overlays the admin queue | 89 | /* Virtual channel message descriptor. This overlays the admin queue |
@@ -348,6 +351,37 @@ struct i40e_virtchnl_pf_event { | |||
348 | int severity; | 351 | int severity; |
349 | }; | 352 | }; |
350 | 353 | ||
354 | /* I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP | ||
355 | * VF uses this message to request PF to map IWARP vectors to IWARP queues. | ||
356 | * The request for this originates from the VF IWARP driver through | ||
357 | * a client interface between VF LAN and VF IWARP driver. | ||
358 | * A vector could have an AEQ and CEQ attached to it although | ||
359 | * there is a single AEQ per VF IWARP instance in which case | ||
360 | * most vectors will have an INVALID_IDX for aeq and valid idx for ceq. | ||
361 | * There will never be a case where there will be multiple CEQs attached | ||
362 | * to a single vector. | ||
363 | * PF configures interrupt mapping and returns status. | ||
364 | */ | ||
365 | |||
366 | /* HW does not define a type value for AEQ; only for RX/TX and CEQ. | ||
367 | * In order for us to keep the interface simple, SW will define a | ||
368 | * unique type value for AEQ. | ||
369 | */ | ||
370 | #define I40E_QUEUE_TYPE_PE_AEQ 0x80 | ||
371 | #define I40E_QUEUE_INVALID_IDX 0xFFFF | ||
372 | |||
373 | struct i40e_virtchnl_iwarp_qv_info { | ||
374 | u32 v_idx; /* msix_vector */ | ||
375 | u16 ceq_idx; | ||
376 | u16 aeq_idx; | ||
377 | u8 itr_idx; | ||
378 | }; | ||
379 | |||
380 | struct i40e_virtchnl_iwarp_qvlist_info { | ||
381 | u32 num_vectors; | ||
382 | struct i40e_virtchnl_iwarp_qv_info qv_info[1]; | ||
383 | }; | ||
384 | |||
351 | /* VF reset states - these are written into the RSTAT register: | 385 | /* VF reset states - these are written into the RSTAT register: |
352 | * I40E_VFGEN_RSTAT1 on the PF | 386 | * I40E_VFGEN_RSTAT1 on the PF |
353 | * I40E_VFGEN_RSTAT on the VF | 387 | * I40E_VFGEN_RSTAT on the VF |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 63e62f9aec6e..bf35b64f6a4a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | |||
@@ -352,6 +352,136 @@ irq_list_done: | |||
352 | } | 352 | } |
353 | 353 | ||
354 | /** | 354 | /** |
355 | * i40e_release_iwarp_qvlist | ||
356 | * @vf: pointer to the VF. | ||
357 | * | ||
358 | **/ | ||
359 | static void i40e_release_iwarp_qvlist(struct i40e_vf *vf) | ||
360 | { | ||
361 | struct i40e_pf *pf = vf->pf; | ||
362 | struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info = vf->qvlist_info; | ||
363 | u32 msix_vf; | ||
364 | u32 i; | ||
365 | |||
366 | if (!vf->qvlist_info) | ||
367 | return; | ||
368 | |||
369 | msix_vf = pf->hw.func_caps.num_msix_vectors_vf; | ||
370 | for (i = 0; i < qvlist_info->num_vectors; i++) { | ||
371 | struct i40e_virtchnl_iwarp_qv_info *qv_info; | ||
372 | u32 next_q_index, next_q_type; | ||
373 | struct i40e_hw *hw = &pf->hw; | ||
374 | u32 v_idx, reg_idx, reg; | ||
375 | |||
376 | qv_info = &qvlist_info->qv_info[i]; | ||
377 | if (!qv_info) | ||
378 | continue; | ||
379 | v_idx = qv_info->v_idx; | ||
380 | if (qv_info->ceq_idx != I40E_QUEUE_INVALID_IDX) { | ||
381 | /* Figure out the queue after CEQ and make that the | ||
382 | * first queue. | ||
383 | */ | ||
384 | reg_idx = (msix_vf - 1) * vf->vf_id + qv_info->ceq_idx; | ||
385 | reg = rd32(hw, I40E_VPINT_CEQCTL(reg_idx)); | ||
386 | next_q_index = (reg & I40E_VPINT_CEQCTL_NEXTQ_INDX_MASK) | ||
387 | >> I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT; | ||
388 | next_q_type = (reg & I40E_VPINT_CEQCTL_NEXTQ_TYPE_MASK) | ||
389 | >> I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT; | ||
390 | |||
391 | reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1); | ||
392 | reg = (next_q_index & | ||
393 | I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) | | ||
394 | (next_q_type << | ||
395 | I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT); | ||
396 | |||
397 | wr32(hw, I40E_VPINT_LNKLSTN(reg_idx), reg); | ||
398 | } | ||
399 | } | ||
400 | kfree(vf->qvlist_info); | ||
401 | vf->qvlist_info = NULL; | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * i40e_config_iwarp_qvlist | ||
406 | * @vf: pointer to the VF info | ||
407 | * @qvlist_info: queue and vector list | ||
408 | * | ||
409 | * Return 0 on success or < 0 on error | ||
410 | **/ | ||
411 | static int i40e_config_iwarp_qvlist(struct i40e_vf *vf, | ||
412 | struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info) | ||
413 | { | ||
414 | struct i40e_pf *pf = vf->pf; | ||
415 | struct i40e_hw *hw = &pf->hw; | ||
416 | struct i40e_virtchnl_iwarp_qv_info *qv_info; | ||
417 | u32 v_idx, i, reg_idx, reg; | ||
418 | u32 next_q_idx, next_q_type; | ||
419 | u32 msix_vf, size; | ||
420 | |||
421 | size = sizeof(struct i40e_virtchnl_iwarp_qvlist_info) + | ||
422 | (sizeof(struct i40e_virtchnl_iwarp_qv_info) * | ||
423 | (qvlist_info->num_vectors - 1)); | ||
424 | vf->qvlist_info = kzalloc(size, GFP_KERNEL); | ||
425 | vf->qvlist_info->num_vectors = qvlist_info->num_vectors; | ||
426 | |||
427 | msix_vf = pf->hw.func_caps.num_msix_vectors_vf; | ||
428 | for (i = 0; i < qvlist_info->num_vectors; i++) { | ||
429 | qv_info = &qvlist_info->qv_info[i]; | ||
430 | if (!qv_info) | ||
431 | continue; | ||
432 | v_idx = qv_info->v_idx; | ||
433 | |||
434 | /* Validate vector id belongs to this vf */ | ||
435 | if (!i40e_vc_isvalid_vector_id(vf, v_idx)) | ||
436 | goto err; | ||
437 | |||
438 | vf->qvlist_info->qv_info[i] = *qv_info; | ||
439 | |||
440 | reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1); | ||
441 | /* We might be sharing the interrupt, so get the first queue | ||
442 | * index and type, push it down the list by adding the new | ||
443 | * queue on top. Also link it with the new queue in CEQCTL. | ||
444 | */ | ||
445 | reg = rd32(hw, I40E_VPINT_LNKLSTN(reg_idx)); | ||
446 | next_q_idx = ((reg & I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) >> | ||
447 | I40E_VPINT_LNKLSTN_FIRSTQ_INDX_SHIFT); | ||
448 | next_q_type = ((reg & I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK) >> | ||
449 | I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT); | ||
450 | |||
451 | if (qv_info->ceq_idx != I40E_QUEUE_INVALID_IDX) { | ||
452 | reg_idx = (msix_vf - 1) * vf->vf_id + qv_info->ceq_idx; | ||
453 | reg = (I40E_VPINT_CEQCTL_CAUSE_ENA_MASK | | ||
454 | (v_idx << I40E_VPINT_CEQCTL_MSIX_INDX_SHIFT) | | ||
455 | (qv_info->itr_idx << I40E_VPINT_CEQCTL_ITR_INDX_SHIFT) | | ||
456 | (next_q_type << I40E_VPINT_CEQCTL_NEXTQ_TYPE_SHIFT) | | ||
457 | (next_q_idx << I40E_VPINT_CEQCTL_NEXTQ_INDX_SHIFT)); | ||
458 | wr32(hw, I40E_VPINT_CEQCTL(reg_idx), reg); | ||
459 | |||
460 | reg_idx = ((msix_vf - 1) * vf->vf_id) + (v_idx - 1); | ||
461 | reg = (qv_info->ceq_idx & | ||
462 | I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK) | | ||
463 | (I40E_QUEUE_TYPE_PE_CEQ << | ||
464 | I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT); | ||
465 | wr32(hw, I40E_VPINT_LNKLSTN(reg_idx), reg); | ||
466 | } | ||
467 | |||
468 | if (qv_info->aeq_idx != I40E_QUEUE_INVALID_IDX) { | ||
469 | reg = (I40E_VPINT_AEQCTL_CAUSE_ENA_MASK | | ||
470 | (v_idx << I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT) | | ||
471 | (qv_info->itr_idx << I40E_VPINT_AEQCTL_ITR_INDX_SHIFT)); | ||
472 | |||
473 | wr32(hw, I40E_VPINT_AEQCTL(vf->vf_id), reg); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | return 0; | ||
478 | err: | ||
479 | kfree(vf->qvlist_info); | ||
480 | vf->qvlist_info = NULL; | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | /** | ||
355 | * i40e_config_vsi_tx_queue | 485 | * i40e_config_vsi_tx_queue |
356 | * @vf: pointer to the VF info | 486 | * @vf: pointer to the VF info |
357 | * @vsi_id: id of VSI as provided by the FW | 487 | * @vsi_id: id of VSI as provided by the FW |
@@ -849,9 +979,11 @@ complete_reset: | |||
849 | /* reallocate VF resources to reset the VSI state */ | 979 | /* reallocate VF resources to reset the VSI state */ |
850 | i40e_free_vf_res(vf); | 980 | i40e_free_vf_res(vf); |
851 | if (!i40e_alloc_vf_res(vf)) { | 981 | if (!i40e_alloc_vf_res(vf)) { |
982 | int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; | ||
852 | i40e_enable_vf_mappings(vf); | 983 | i40e_enable_vf_mappings(vf); |
853 | set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); | 984 | set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); |
854 | clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states); | 985 | clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states); |
986 | i40e_notify_client_of_vf_reset(pf, abs_vf_id); | ||
855 | } | 987 | } |
856 | /* tell the VF the reset is done */ | 988 | /* tell the VF the reset is done */ |
857 | wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE); | 989 | wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE); |
@@ -876,11 +1008,7 @@ void i40e_free_vfs(struct i40e_pf *pf) | |||
876 | while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state)) | 1008 | while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state)) |
877 | usleep_range(1000, 2000); | 1009 | usleep_range(1000, 2000); |
878 | 1010 | ||
879 | for (i = 0; i < pf->num_alloc_vfs; i++) | 1011 | i40e_notify_client_of_vf_enable(pf, 0); |
880 | if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) | ||
881 | i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], | ||
882 | false); | ||
883 | |||
884 | for (i = 0; i < pf->num_alloc_vfs; i++) | 1012 | for (i = 0; i < pf->num_alloc_vfs; i++) |
885 | if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) | 1013 | if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) |
886 | i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], | 1014 | i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], |
@@ -952,6 +1080,7 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs) | |||
952 | goto err_iov; | 1080 | goto err_iov; |
953 | } | 1081 | } |
954 | } | 1082 | } |
1083 | i40e_notify_client_of_vf_enable(pf, num_alloc_vfs); | ||
955 | /* allocate memory */ | 1084 | /* allocate memory */ |
956 | vfs = kcalloc(num_alloc_vfs, sizeof(struct i40e_vf), GFP_KERNEL); | 1085 | vfs = kcalloc(num_alloc_vfs, sizeof(struct i40e_vf), GFP_KERNEL); |
957 | if (!vfs) { | 1086 | if (!vfs) { |
@@ -1205,6 +1334,13 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) | |||
1205 | vsi = pf->vsi[vf->lan_vsi_idx]; | 1334 | vsi = pf->vsi[vf->lan_vsi_idx]; |
1206 | if (!vsi->info.pvid) | 1335 | if (!vsi->info.pvid) |
1207 | vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_VLAN; | 1336 | vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_VLAN; |
1337 | |||
1338 | if (i40e_vf_client_capable(pf, vf->vf_id, I40E_CLIENT_IWARP) && | ||
1339 | (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_IWARP)) { | ||
1340 | vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_IWARP; | ||
1341 | set_bit(I40E_VF_STAT_IWARPENA, &vf->vf_states); | ||
1342 | } | ||
1343 | |||
1208 | if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { | 1344 | if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) { |
1209 | if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ) | 1345 | if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ) |
1210 | vfres->vf_offload_flags |= | 1346 | vfres->vf_offload_flags |= |
@@ -1814,6 +1950,72 @@ error_param: | |||
1814 | } | 1950 | } |
1815 | 1951 | ||
1816 | /** | 1952 | /** |
1953 | * i40e_vc_iwarp_msg | ||
1954 | * @vf: pointer to the VF info | ||
1955 | * @msg: pointer to the msg buffer | ||
1956 | * @msglen: msg length | ||
1957 | * | ||
1958 | * called from the VF for the iwarp msgs | ||
1959 | **/ | ||
1960 | static int i40e_vc_iwarp_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) | ||
1961 | { | ||
1962 | struct i40e_pf *pf = vf->pf; | ||
1963 | int abs_vf_id = vf->vf_id + pf->hw.func_caps.vf_base_id; | ||
1964 | i40e_status aq_ret = 0; | ||
1965 | |||
1966 | if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || | ||
1967 | !test_bit(I40E_VF_STAT_IWARPENA, &vf->vf_states)) { | ||
1968 | aq_ret = I40E_ERR_PARAM; | ||
1969 | goto error_param; | ||
1970 | } | ||
1971 | |||
1972 | i40e_notify_client_of_vf_msg(pf->vsi[pf->lan_vsi], abs_vf_id, | ||
1973 | msg, msglen); | ||
1974 | |||
1975 | error_param: | ||
1976 | /* send the response to the VF */ | ||
1977 | return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_IWARP, | ||
1978 | aq_ret); | ||
1979 | } | ||
1980 | |||
1981 | /** | ||
1982 | * i40e_vc_iwarp_qvmap_msg | ||
1983 | * @vf: pointer to the VF info | ||
1984 | * @msg: pointer to the msg buffer | ||
1985 | * @msglen: msg length | ||
1986 | * @config: config qvmap or release it | ||
1987 | * | ||
1988 | * called from the VF for the iwarp msgs | ||
1989 | **/ | ||
1990 | static int i40e_vc_iwarp_qvmap_msg(struct i40e_vf *vf, u8 *msg, u16 msglen, | ||
1991 | bool config) | ||
1992 | { | ||
1993 | struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info = | ||
1994 | (struct i40e_virtchnl_iwarp_qvlist_info *)msg; | ||
1995 | i40e_status aq_ret = 0; | ||
1996 | |||
1997 | if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) || | ||
1998 | !test_bit(I40E_VF_STAT_IWARPENA, &vf->vf_states)) { | ||
1999 | aq_ret = I40E_ERR_PARAM; | ||
2000 | goto error_param; | ||
2001 | } | ||
2002 | |||
2003 | if (config) { | ||
2004 | if (i40e_config_iwarp_qvlist(vf, qvlist_info)) | ||
2005 | aq_ret = I40E_ERR_PARAM; | ||
2006 | } else { | ||
2007 | i40e_release_iwarp_qvlist(vf); | ||
2008 | } | ||
2009 | |||
2010 | error_param: | ||
2011 | /* send the response to the VF */ | ||
2012 | return i40e_vc_send_resp_to_vf(vf, | ||
2013 | config ? I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP : | ||
2014 | I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP, | ||
2015 | aq_ret); | ||
2016 | } | ||
2017 | |||
2018 | /** | ||
1817 | * i40e_vc_validate_vf_msg | 2019 | * i40e_vc_validate_vf_msg |
1818 | * @vf: pointer to the VF info | 2020 | * @vf: pointer to the VF info |
1819 | * @msg: pointer to the msg buffer | 2021 | * @msg: pointer to the msg buffer |
@@ -1908,6 +2110,32 @@ static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode, | |||
1908 | case I40E_VIRTCHNL_OP_GET_STATS: | 2110 | case I40E_VIRTCHNL_OP_GET_STATS: |
1909 | valid_len = sizeof(struct i40e_virtchnl_queue_select); | 2111 | valid_len = sizeof(struct i40e_virtchnl_queue_select); |
1910 | break; | 2112 | break; |
2113 | case I40E_VIRTCHNL_OP_IWARP: | ||
2114 | /* These messages are opaque to us and will be validated in | ||
2115 | * the RDMA client code. We just need to check for nonzero | ||
2116 | * length. The firmware will enforce max length restrictions. | ||
2117 | */ | ||
2118 | if (msglen) | ||
2119 | valid_len = msglen; | ||
2120 | else | ||
2121 | err_msg_format = true; | ||
2122 | break; | ||
2123 | case I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: | ||
2124 | valid_len = 0; | ||
2125 | break; | ||
2126 | case I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP: | ||
2127 | valid_len = sizeof(struct i40e_virtchnl_iwarp_qvlist_info); | ||
2128 | if (msglen >= valid_len) { | ||
2129 | struct i40e_virtchnl_iwarp_qvlist_info *qv = | ||
2130 | (struct i40e_virtchnl_iwarp_qvlist_info *)msg; | ||
2131 | if (qv->num_vectors == 0) { | ||
2132 | err_msg_format = true; | ||
2133 | break; | ||
2134 | } | ||
2135 | valid_len += ((qv->num_vectors - 1) * | ||
2136 | sizeof(struct i40e_virtchnl_iwarp_qv_info)); | ||
2137 | } | ||
2138 | break; | ||
1911 | /* These are always errors coming from the VF. */ | 2139 | /* These are always errors coming from the VF. */ |
1912 | case I40E_VIRTCHNL_OP_EVENT: | 2140 | case I40E_VIRTCHNL_OP_EVENT: |
1913 | case I40E_VIRTCHNL_OP_UNKNOWN: | 2141 | case I40E_VIRTCHNL_OP_UNKNOWN: |
@@ -1997,6 +2225,15 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode, | |||
1997 | case I40E_VIRTCHNL_OP_GET_STATS: | 2225 | case I40E_VIRTCHNL_OP_GET_STATS: |
1998 | ret = i40e_vc_get_stats_msg(vf, msg, msglen); | 2226 | ret = i40e_vc_get_stats_msg(vf, msg, msglen); |
1999 | break; | 2227 | break; |
2228 | case I40E_VIRTCHNL_OP_IWARP: | ||
2229 | ret = i40e_vc_iwarp_msg(vf, msg, msglen); | ||
2230 | break; | ||
2231 | case I40E_VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP: | ||
2232 | ret = i40e_vc_iwarp_qvmap_msg(vf, msg, msglen, true); | ||
2233 | break; | ||
2234 | case I40E_VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP: | ||
2235 | ret = i40e_vc_iwarp_qvmap_msg(vf, msg, msglen, false); | ||
2236 | break; | ||
2000 | case I40E_VIRTCHNL_OP_UNKNOWN: | 2237 | case I40E_VIRTCHNL_OP_UNKNOWN: |
2001 | default: | 2238 | default: |
2002 | dev_err(&pf->pdev->dev, "Unsupported opcode %d from VF %d\n", | 2239 | dev_err(&pf->pdev->dev, "Unsupported opcode %d from VF %d\n", |
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index da44995def42..1da4d9ac4c7a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | |||
@@ -58,6 +58,7 @@ enum i40e_queue_ctrl { | |||
58 | enum i40e_vf_states { | 58 | enum i40e_vf_states { |
59 | I40E_VF_STAT_INIT = 0, | 59 | I40E_VF_STAT_INIT = 0, |
60 | I40E_VF_STAT_ACTIVE, | 60 | I40E_VF_STAT_ACTIVE, |
61 | I40E_VF_STAT_IWARPENA, | ||
61 | I40E_VF_STAT_FCOEENA, | 62 | I40E_VF_STAT_FCOEENA, |
62 | I40E_VF_STAT_DISABLED, | 63 | I40E_VF_STAT_DISABLED, |
63 | }; | 64 | }; |
@@ -66,6 +67,7 @@ enum i40e_vf_states { | |||
66 | enum i40e_vf_capabilities { | 67 | enum i40e_vf_capabilities { |
67 | I40E_VIRTCHNL_VF_CAP_PRIVILEGE = 0, | 68 | I40E_VIRTCHNL_VF_CAP_PRIVILEGE = 0, |
68 | I40E_VIRTCHNL_VF_CAP_L2, | 69 | I40E_VIRTCHNL_VF_CAP_L2, |
70 | I40E_VIRTCHNL_VF_CAP_IWARP, | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | /* VF information structure */ | 73 | /* VF information structure */ |
@@ -106,6 +108,8 @@ struct i40e_vf { | |||
106 | bool link_forced; | 108 | bool link_forced; |
107 | bool link_up; /* only valid if VF link is forced */ | 109 | bool link_up; /* only valid if VF link is forced */ |
108 | bool spoofchk; | 110 | bool spoofchk; |
111 | /* RDMA Client */ | ||
112 | struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info; | ||
109 | }; | 113 | }; |
110 | 114 | ||
111 | void i40e_free_vfs(struct i40e_pf *pf); | 115 | void i40e_free_vfs(struct i40e_pf *pf); |