1 /*******************************************************************************
3 * Copyright (c) 2015-2016 Intel Corporation. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenFabrics.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 *******************************************************************************/
35 #include "i40iw_osdep.h"
36 #include "i40iw_register.h"
37 #include "i40iw_status.h"
38 #include "i40iw_hmc.h"
40 #include "i40iw_type.h"
42 #include "i40iw_virtchnl.h"
45 * vchnl_vf_send_get_ver_req - Request Channel version
46 * @dev: IWARP device pointer
47 * @vchnl_req: Virtual channel message request pointer
49 static enum i40iw_status_code
vchnl_vf_send_get_ver_req(struct i40iw_sc_dev
*dev
,
50 struct i40iw_virtchnl_req
*vchnl_req
)
52 enum i40iw_status_code ret_code
= I40IW_ERR_NOT_READY
;
53 struct i40iw_virtchnl_op_buf
*vchnl_msg
= vchnl_req
->vchnl_msg
;
58 memset(vchnl_msg
, 0, sizeof(*vchnl_msg
));
59 vchnl_msg
->iw_chnl_op_ctx
= (uintptr_t)vchnl_req
;
60 vchnl_msg
->iw_chnl_buf_len
= sizeof(*vchnl_msg
);
61 vchnl_msg
->iw_op_code
= I40IW_VCHNL_OP_GET_VER
;
62 vchnl_msg
->iw_op_ver
= I40IW_VCHNL_OP_GET_VER_V0
;
63 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, 0, (u8
*)vchnl_msg
, vchnl_msg
->iw_chnl_buf_len
);
65 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
66 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
71 * vchnl_vf_send_get_hmc_fcn_req - Request HMC Function from VF
72 * @dev: IWARP device pointer
73 * @vchnl_req: Virtual channel message request pointer
75 static enum i40iw_status_code
vchnl_vf_send_get_hmc_fcn_req(struct i40iw_sc_dev
*dev
,
76 struct i40iw_virtchnl_req
*vchnl_req
)
78 enum i40iw_status_code ret_code
= I40IW_ERR_NOT_READY
;
79 struct i40iw_virtchnl_op_buf
*vchnl_msg
= vchnl_req
->vchnl_msg
;
84 memset(vchnl_msg
, 0, sizeof(*vchnl_msg
));
85 vchnl_msg
->iw_chnl_op_ctx
= (uintptr_t)vchnl_req
;
86 vchnl_msg
->iw_chnl_buf_len
= sizeof(*vchnl_msg
);
87 vchnl_msg
->iw_op_code
= I40IW_VCHNL_OP_GET_HMC_FCN
;
88 vchnl_msg
->iw_op_ver
= I40IW_VCHNL_OP_GET_HMC_FCN_V0
;
89 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, 0, (u8
*)vchnl_msg
, vchnl_msg
->iw_chnl_buf_len
);
91 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
92 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
97 * vchnl_vf_send_get_pe_stats_req - Request PE stats from VF
98 * @dev: IWARP device pointer
99 * @vchnl_req: Virtual channel message request pointer
101 static enum i40iw_status_code
vchnl_vf_send_get_pe_stats_req(struct i40iw_sc_dev
*dev
,
102 struct i40iw_virtchnl_req
*vchnl_req
)
104 enum i40iw_status_code ret_code
= I40IW_ERR_NOT_READY
;
105 struct i40iw_virtchnl_op_buf
*vchnl_msg
= vchnl_req
->vchnl_msg
;
110 memset(vchnl_msg
, 0, sizeof(*vchnl_msg
));
111 vchnl_msg
->iw_chnl_op_ctx
= (uintptr_t)vchnl_req
;
112 vchnl_msg
->iw_chnl_buf_len
= sizeof(*vchnl_msg
) + sizeof(struct i40iw_dev_hw_stats
) - 1;
113 vchnl_msg
->iw_op_code
= I40IW_VCHNL_OP_GET_STATS
;
114 vchnl_msg
->iw_op_ver
= I40IW_VCHNL_OP_GET_STATS_V0
;
115 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, 0, (u8
*)vchnl_msg
, vchnl_msg
->iw_chnl_buf_len
);
117 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
118 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
123 * vchnl_vf_send_add_hmc_objs_req - Add HMC objects
124 * @dev: IWARP device pointer
125 * @vchnl_req: Virtual channel message request pointer
127 static enum i40iw_status_code
vchnl_vf_send_add_hmc_objs_req(struct i40iw_sc_dev
*dev
,
128 struct i40iw_virtchnl_req
*vchnl_req
,
129 enum i40iw_hmc_rsrc_type rsrc_type
,
133 enum i40iw_status_code ret_code
= I40IW_ERR_NOT_READY
;
134 struct i40iw_virtchnl_op_buf
*vchnl_msg
= vchnl_req
->vchnl_msg
;
135 struct i40iw_virtchnl_hmc_obj_range
*add_hmc_obj
;
140 add_hmc_obj
= (struct i40iw_virtchnl_hmc_obj_range
*)vchnl_msg
->iw_chnl_buf
;
141 memset(vchnl_msg
, 0, sizeof(*vchnl_msg
));
142 memset(add_hmc_obj
, 0, sizeof(*add_hmc_obj
));
143 vchnl_msg
->iw_chnl_op_ctx
= (uintptr_t)vchnl_req
;
144 vchnl_msg
->iw_chnl_buf_len
= sizeof(*vchnl_msg
) + sizeof(struct i40iw_virtchnl_hmc_obj_range
) - 1;
145 vchnl_msg
->iw_op_code
= I40IW_VCHNL_OP_ADD_HMC_OBJ_RANGE
;
146 vchnl_msg
->iw_op_ver
= I40IW_VCHNL_OP_ADD_HMC_OBJ_RANGE_V0
;
147 add_hmc_obj
->obj_type
= (u16
)rsrc_type
;
148 add_hmc_obj
->start_index
= start_index
;
149 add_hmc_obj
->obj_count
= rsrc_count
;
150 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, 0, (u8
*)vchnl_msg
, vchnl_msg
->iw_chnl_buf_len
);
152 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
153 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
158 * vchnl_vf_send_del_hmc_objs_req - del HMC objects
159 * @dev: IWARP device pointer
160 * @vchnl_req: Virtual channel message request pointer
161 * @ rsrc_type - resource type to delete
162 * @ start_index - starting index for resource
163 * @ rsrc_count - number of resource type to delete
165 static enum i40iw_status_code
vchnl_vf_send_del_hmc_objs_req(struct i40iw_sc_dev
*dev
,
166 struct i40iw_virtchnl_req
*vchnl_req
,
167 enum i40iw_hmc_rsrc_type rsrc_type
,
171 enum i40iw_status_code ret_code
= I40IW_ERR_NOT_READY
;
172 struct i40iw_virtchnl_op_buf
*vchnl_msg
= vchnl_req
->vchnl_msg
;
173 struct i40iw_virtchnl_hmc_obj_range
*add_hmc_obj
;
178 add_hmc_obj
= (struct i40iw_virtchnl_hmc_obj_range
*)vchnl_msg
->iw_chnl_buf
;
179 memset(vchnl_msg
, 0, sizeof(*vchnl_msg
));
180 memset(add_hmc_obj
, 0, sizeof(*add_hmc_obj
));
181 vchnl_msg
->iw_chnl_op_ctx
= (uintptr_t)vchnl_req
;
182 vchnl_msg
->iw_chnl_buf_len
= sizeof(*vchnl_msg
) + sizeof(struct i40iw_virtchnl_hmc_obj_range
) - 1;
183 vchnl_msg
->iw_op_code
= I40IW_VCHNL_OP_DEL_HMC_OBJ_RANGE
;
184 vchnl_msg
->iw_op_ver
= I40IW_VCHNL_OP_DEL_HMC_OBJ_RANGE_V0
;
185 add_hmc_obj
->obj_type
= (u16
)rsrc_type
;
186 add_hmc_obj
->start_index
= start_index
;
187 add_hmc_obj
->obj_count
= rsrc_count
;
188 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, 0, (u8
*)vchnl_msg
, vchnl_msg
->iw_chnl_buf_len
);
190 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
191 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
196 * vchnl_pf_send_get_ver_resp - Send channel version to VF
197 * @dev: IWARP device pointer
198 * @vf_id: Virtual function ID associated with the message
199 * @vchnl_msg: Virtual channel message buffer pointer
201 static void vchnl_pf_send_get_ver_resp(struct i40iw_sc_dev
*dev
,
203 struct i40iw_virtchnl_op_buf
*vchnl_msg
)
205 enum i40iw_status_code ret_code
;
206 u8 resp_buffer
[sizeof(struct i40iw_virtchnl_resp_buf
) + sizeof(u32
) - 1];
207 struct i40iw_virtchnl_resp_buf
*vchnl_msg_resp
= (struct i40iw_virtchnl_resp_buf
*)resp_buffer
;
209 memset(resp_buffer
, 0, sizeof(*resp_buffer
));
210 vchnl_msg_resp
->iw_chnl_op_ctx
= vchnl_msg
->iw_chnl_op_ctx
;
211 vchnl_msg_resp
->iw_chnl_buf_len
= sizeof(resp_buffer
);
212 vchnl_msg_resp
->iw_op_ret_code
= I40IW_SUCCESS
;
213 *((u32
*)vchnl_msg_resp
->iw_chnl_buf
) = I40IW_VCHNL_CHNL_VER_V0
;
214 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, vf_id
, resp_buffer
, sizeof(resp_buffer
));
216 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
217 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
221 * vchnl_pf_send_get_hmc_fcn_resp - Send HMC Function to VF
222 * @dev: IWARP device pointer
223 * @vf_id: Virtual function ID associated with the message
224 * @vchnl_msg: Virtual channel message buffer pointer
226 static void vchnl_pf_send_get_hmc_fcn_resp(struct i40iw_sc_dev
*dev
,
228 struct i40iw_virtchnl_op_buf
*vchnl_msg
,
231 enum i40iw_status_code ret_code
;
232 u8 resp_buffer
[sizeof(struct i40iw_virtchnl_resp_buf
) + sizeof(u16
) - 1];
233 struct i40iw_virtchnl_resp_buf
*vchnl_msg_resp
= (struct i40iw_virtchnl_resp_buf
*)resp_buffer
;
235 memset(resp_buffer
, 0, sizeof(*resp_buffer
));
236 vchnl_msg_resp
->iw_chnl_op_ctx
= vchnl_msg
->iw_chnl_op_ctx
;
237 vchnl_msg_resp
->iw_chnl_buf_len
= sizeof(resp_buffer
);
238 vchnl_msg_resp
->iw_op_ret_code
= I40IW_SUCCESS
;
239 *((u16
*)vchnl_msg_resp
->iw_chnl_buf
) = hmc_fcn
;
240 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, vf_id
, resp_buffer
, sizeof(resp_buffer
));
242 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
243 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
247 * vchnl_pf_send_get_pe_stats_resp - Send PE Stats to VF
248 * @dev: IWARP device pointer
249 * @vf_id: Virtual function ID associated with the message
250 * @vchnl_msg: Virtual channel message buffer pointer
251 * @hw_stats: HW Stats struct
254 static void vchnl_pf_send_get_pe_stats_resp(struct i40iw_sc_dev
*dev
,
256 struct i40iw_virtchnl_op_buf
*vchnl_msg
,
257 struct i40iw_dev_hw_stats
*hw_stats
)
259 enum i40iw_status_code ret_code
;
260 u8 resp_buffer
[sizeof(struct i40iw_virtchnl_resp_buf
) + sizeof(struct i40iw_dev_hw_stats
) - 1];
261 struct i40iw_virtchnl_resp_buf
*vchnl_msg_resp
= (struct i40iw_virtchnl_resp_buf
*)resp_buffer
;
263 memset(resp_buffer
, 0, sizeof(*resp_buffer
));
264 vchnl_msg_resp
->iw_chnl_op_ctx
= vchnl_msg
->iw_chnl_op_ctx
;
265 vchnl_msg_resp
->iw_chnl_buf_len
= sizeof(resp_buffer
);
266 vchnl_msg_resp
->iw_op_ret_code
= I40IW_SUCCESS
;
267 *((struct i40iw_dev_hw_stats
*)vchnl_msg_resp
->iw_chnl_buf
) = *hw_stats
;
268 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, vf_id
, resp_buffer
, sizeof(resp_buffer
));
270 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
271 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
275 * vchnl_pf_send_error_resp - Send an error response to VF
276 * @dev: IWARP device pointer
277 * @vf_id: Virtual function ID associated with the message
278 * @vchnl_msg: Virtual channel message buffer pointer
280 static void vchnl_pf_send_error_resp(struct i40iw_sc_dev
*dev
, u32 vf_id
,
281 struct i40iw_virtchnl_op_buf
*vchnl_msg
,
284 enum i40iw_status_code ret_code
;
285 u8 resp_buffer
[sizeof(struct i40iw_virtchnl_resp_buf
)];
286 struct i40iw_virtchnl_resp_buf
*vchnl_msg_resp
= (struct i40iw_virtchnl_resp_buf
*)resp_buffer
;
288 memset(resp_buffer
, 0, sizeof(resp_buffer
));
289 vchnl_msg_resp
->iw_chnl_op_ctx
= vchnl_msg
->iw_chnl_op_ctx
;
290 vchnl_msg_resp
->iw_chnl_buf_len
= sizeof(resp_buffer
);
291 vchnl_msg_resp
->iw_op_ret_code
= (u16
)op_ret_code
;
292 ret_code
= dev
->vchnl_if
.vchnl_send(dev
, vf_id
, resp_buffer
, sizeof(resp_buffer
));
294 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
295 "%s: virt channel send failed 0x%x\n", __func__
, ret_code
);
299 * pf_cqp_get_hmc_fcn_callback - Callback for Get HMC Fcn
300 * @cqp_req_param: CQP Request param value
301 * @not_used: unused CQP callback parameter
303 static void pf_cqp_get_hmc_fcn_callback(struct i40iw_sc_dev
*dev
, void *callback_param
,
304 struct i40iw_ccq_cqe_info
*cqe_info
)
306 struct i40iw_vfdev
*vf_dev
= callback_param
;
307 struct i40iw_virt_mem vf_dev_mem
;
309 if (cqe_info
->error
) {
310 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
311 "CQP Completion Error on Get HMC Function. Maj = 0x%04x, Minor = 0x%04x\n",
312 cqe_info
->maj_err_code
, cqe_info
->min_err_code
);
313 dev
->vf_dev
[vf_dev
->iw_vf_idx
] = NULL
;
314 vchnl_pf_send_error_resp(dev
, vf_dev
->vf_id
, &vf_dev
->vf_msg_buffer
.vchnl_msg
,
315 (u16
)I40IW_ERR_CQP_COMPL_ERROR
);
316 vf_dev_mem
.va
= vf_dev
;
317 vf_dev_mem
.size
= sizeof(*vf_dev
);
318 i40iw_free_virt_mem(dev
->hw
, &vf_dev_mem
);
320 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
321 "CQP Completion Operation Return information = 0x%08x\n",
322 cqe_info
->op_ret_val
);
323 vf_dev
->pmf_index
= (u16
)cqe_info
->op_ret_val
;
325 vchnl_pf_send_get_hmc_fcn_resp(dev
,
327 &vf_dev
->vf_msg_buffer
.vchnl_msg
,
333 * pf_add_hmc_obj - Callback for Add HMC Object
334 * @vf_dev: pointer to the VF Device
336 static void pf_add_hmc_obj_callback(void *work_vf_dev
)
338 struct i40iw_vfdev
*vf_dev
= (struct i40iw_vfdev
*)work_vf_dev
;
339 struct i40iw_hmc_info
*hmc_info
= &vf_dev
->hmc_info
;
340 struct i40iw_virtchnl_op_buf
*vchnl_msg
= &vf_dev
->vf_msg_buffer
.vchnl_msg
;
341 struct i40iw_hmc_create_obj_info info
;
342 struct i40iw_virtchnl_hmc_obj_range
*add_hmc_obj
;
343 enum i40iw_status_code ret_code
;
345 if (!vf_dev
->pf_hmc_initialized
) {
346 ret_code
= i40iw_pf_init_vfhmc(vf_dev
->pf_dev
, (u8
)vf_dev
->pmf_index
, NULL
);
349 vf_dev
->pf_hmc_initialized
= true;
352 add_hmc_obj
= (struct i40iw_virtchnl_hmc_obj_range
*)vchnl_msg
->iw_chnl_buf
;
354 memset(&info
, 0, sizeof(info
));
355 info
.hmc_info
= hmc_info
;
357 info
.rsrc_type
= (u32
)add_hmc_obj
->obj_type
;
358 info
.entry_type
= (info
.rsrc_type
== I40IW_HMC_IW_PBLE
) ? I40IW_SD_TYPE_PAGED
: I40IW_SD_TYPE_DIRECT
;
359 info
.start_idx
= add_hmc_obj
->start_index
;
360 info
.count
= add_hmc_obj
->obj_count
;
361 i40iw_debug(vf_dev
->pf_dev
, I40IW_DEBUG_VIRT
,
362 "I40IW_VCHNL_OP_ADD_HMC_OBJ_RANGE. Add %u type %u objects\n",
363 info
.count
, info
.rsrc_type
);
364 ret_code
= i40iw_sc_create_hmc_obj(vf_dev
->pf_dev
, &info
);
366 vf_dev
->hmc_info
.hmc_obj
[add_hmc_obj
->obj_type
].cnt
= add_hmc_obj
->obj_count
;
369 vchnl_pf_send_error_resp(vf_dev
->pf_dev
, vf_dev
->vf_id
, vchnl_msg
, (u16
)ret_code
);
373 * pf_del_hmc_obj_callback - Callback for delete HMC Object
374 * @work_vf_dev: pointer to the VF Device
376 static void pf_del_hmc_obj_callback(void *work_vf_dev
)
378 struct i40iw_vfdev
*vf_dev
= (struct i40iw_vfdev
*)work_vf_dev
;
379 struct i40iw_hmc_info
*hmc_info
= &vf_dev
->hmc_info
;
380 struct i40iw_virtchnl_op_buf
*vchnl_msg
= &vf_dev
->vf_msg_buffer
.vchnl_msg
;
381 struct i40iw_hmc_del_obj_info info
;
382 struct i40iw_virtchnl_hmc_obj_range
*del_hmc_obj
;
383 enum i40iw_status_code ret_code
= I40IW_SUCCESS
;
385 if (!vf_dev
->pf_hmc_initialized
)
388 del_hmc_obj
= (struct i40iw_virtchnl_hmc_obj_range
*)vchnl_msg
->iw_chnl_buf
;
390 memset(&info
, 0, sizeof(info
));
391 info
.hmc_info
= hmc_info
;
393 info
.rsrc_type
= (u32
)del_hmc_obj
->obj_type
;
394 info
.start_idx
= del_hmc_obj
->start_index
;
395 info
.count
= del_hmc_obj
->obj_count
;
396 i40iw_debug(vf_dev
->pf_dev
, I40IW_DEBUG_VIRT
,
397 "I40IW_VCHNL_OP_DEL_HMC_OBJ_RANGE. Delete %u type %u objects\n",
398 info
.count
, info
.rsrc_type
);
399 ret_code
= i40iw_sc_del_hmc_obj(vf_dev
->pf_dev
, &info
, false);
402 vchnl_pf_send_error_resp(vf_dev
->pf_dev
, vf_dev
->vf_id
, vchnl_msg
, (u16
)ret_code
);
406 * i40iw_vf_init_pestat - Initialize stats for VF
407 * @devL pointer to the VF Device
408 * @stats: Statistics structure pointer
409 * @index: Stats index
411 static void i40iw_vf_init_pestat(struct i40iw_sc_dev
*dev
, struct i40iw_vsi_pestat
*stats
, u16 index
)
414 i40iw_hw_stats_init(stats
, (u8
)index
, false);
415 spin_lock_init(&stats
->lock
);
419 * i40iw_vchnl_recv_pf - Receive PF virtual channel messages
420 * @dev: IWARP device pointer
421 * @vf_id: Virtual function ID associated with the message
422 * @msg: Virtual channel message buffer pointer
423 * @len: Length of the virtual channels message
425 enum i40iw_status_code
i40iw_vchnl_recv_pf(struct i40iw_sc_dev
*dev
,
430 struct i40iw_virtchnl_op_buf
*vchnl_msg
= (struct i40iw_virtchnl_op_buf
*)msg
;
431 struct i40iw_vfdev
*vf_dev
= NULL
;
432 struct i40iw_hmc_fcn_info hmc_fcn_info
;
434 u16 first_avail_iw_vf
= I40IW_MAX_PE_ENABLED_VF_COUNT
;
435 struct i40iw_virt_mem vf_dev_mem
;
436 struct i40iw_virtchnl_work_info work_info
;
437 struct i40iw_vsi_pestat
*stats
;
438 enum i40iw_status_code ret_code
;
440 if (!dev
|| !msg
|| !len
)
441 return I40IW_ERR_PARAM
;
444 return I40IW_ERR_NOT_READY
;
445 if (vchnl_msg
->iw_op_code
== I40IW_VCHNL_OP_GET_VER
) {
446 vchnl_pf_send_get_ver_resp(dev
, vf_id
, vchnl_msg
);
447 return I40IW_SUCCESS
;
449 for (iw_vf_idx
= 0; iw_vf_idx
< I40IW_MAX_PE_ENABLED_VF_COUNT
; iw_vf_idx
++) {
450 if (!dev
->vf_dev
[iw_vf_idx
]) {
451 if (first_avail_iw_vf
== I40IW_MAX_PE_ENABLED_VF_COUNT
)
452 first_avail_iw_vf
= iw_vf_idx
;
455 if (dev
->vf_dev
[iw_vf_idx
]->vf_id
== vf_id
) {
456 vf_dev
= dev
->vf_dev
[iw_vf_idx
];
461 if (!vf_dev
->msg_count
) {
464 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
465 "VF%u already has a channel message in progress.\n",
467 return I40IW_SUCCESS
;
470 switch (vchnl_msg
->iw_op_code
) {
471 case I40IW_VCHNL_OP_GET_HMC_FCN
:
473 (first_avail_iw_vf
!= I40IW_MAX_PE_ENABLED_VF_COUNT
)) {
474 ret_code
= i40iw_allocate_virt_mem(dev
->hw
, &vf_dev_mem
, sizeof(struct i40iw_vfdev
) +
475 (sizeof(struct i40iw_hmc_obj_info
) * I40IW_HMC_IW_MAX
));
477 vf_dev
= vf_dev_mem
.va
;
478 vf_dev
->stats_initialized
= false;
479 vf_dev
->pf_dev
= dev
;
480 vf_dev
->msg_count
= 1;
481 vf_dev
->vf_id
= vf_id
;
482 vf_dev
->iw_vf_idx
= first_avail_iw_vf
;
483 vf_dev
->pf_hmc_initialized
= false;
484 vf_dev
->hmc_info
.hmc_obj
= (struct i40iw_hmc_obj_info
*)(&vf_dev
[1]);
485 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
486 "vf_dev %p, hmc_info %p, hmc_obj %p\n",
487 vf_dev
, &vf_dev
->hmc_info
, vf_dev
->hmc_info
.hmc_obj
);
488 dev
->vf_dev
[first_avail_iw_vf
] = vf_dev
;
489 iw_vf_idx
= first_avail_iw_vf
;
491 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
492 "VF%u Unable to allocate a VF device structure.\n",
494 vchnl_pf_send_error_resp(dev
, vf_id
, vchnl_msg
, (u16
)I40IW_ERR_NO_MEMORY
);
495 return I40IW_SUCCESS
;
497 memcpy(&vf_dev
->vf_msg_buffer
.vchnl_msg
, vchnl_msg
, len
);
498 hmc_fcn_info
.callback_fcn
= pf_cqp_get_hmc_fcn_callback
;
499 hmc_fcn_info
.vf_id
= vf_id
;
500 hmc_fcn_info
.iw_vf_idx
= vf_dev
->iw_vf_idx
;
501 hmc_fcn_info
.cqp_callback_param
= vf_dev
;
502 hmc_fcn_info
.free_fcn
= false;
503 ret_code
= i40iw_cqp_manage_hmc_fcn_cmd(dev
, &hmc_fcn_info
);
505 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
506 "VF%u error CQP HMC Function operation.\n",
508 i40iw_vf_init_pestat(dev
, &vf_dev
->pestat
, vf_dev
->pmf_index
);
509 vf_dev
->stats_initialized
= true;
513 vchnl_pf_send_get_hmc_fcn_resp(dev
, vf_id
, vchnl_msg
, vf_dev
->pmf_index
);
515 vchnl_pf_send_error_resp(dev
, vf_id
, vchnl_msg
,
516 (u16
)I40IW_ERR_NO_MEMORY
);
520 case I40IW_VCHNL_OP_ADD_HMC_OBJ_RANGE
:
522 return I40IW_ERR_BAD_PTR
;
523 work_info
.worker_vf_dev
= vf_dev
;
524 work_info
.callback_fcn
= pf_add_hmc_obj_callback
;
525 memcpy(&vf_dev
->vf_msg_buffer
.vchnl_msg
, vchnl_msg
, len
);
526 i40iw_cqp_spawn_worker(dev
, &work_info
, vf_dev
->iw_vf_idx
);
528 case I40IW_VCHNL_OP_DEL_HMC_OBJ_RANGE
:
530 return I40IW_ERR_BAD_PTR
;
531 work_info
.worker_vf_dev
= vf_dev
;
532 work_info
.callback_fcn
= pf_del_hmc_obj_callback
;
533 memcpy(&vf_dev
->vf_msg_buffer
.vchnl_msg
, vchnl_msg
, len
);
534 i40iw_cqp_spawn_worker(dev
, &work_info
, vf_dev
->iw_vf_idx
);
536 case I40IW_VCHNL_OP_GET_STATS
:
538 return I40IW_ERR_BAD_PTR
;
539 stats
= &vf_dev
->pestat
;
540 i40iw_hw_stats_read_all(stats
, &stats
->hw_stats
);
542 vchnl_pf_send_get_pe_stats_resp(dev
, vf_id
, vchnl_msg
, &stats
->hw_stats
);
545 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
546 "40iw_vchnl_recv_pf: Invalid OpCode 0x%x\n",
547 vchnl_msg
->iw_op_code
);
548 vchnl_pf_send_error_resp(dev
, vf_id
,
549 vchnl_msg
, (u16
)I40IW_ERR_NOT_IMPLEMENTED
);
551 return I40IW_SUCCESS
;
555 * i40iw_vchnl_recv_vf - Receive VF virtual channel messages
556 * @dev: IWARP device pointer
557 * @vf_id: Virtual function ID associated with the message
558 * @msg: Virtual channel message buffer pointer
559 * @len: Length of the virtual channels message
561 enum i40iw_status_code
i40iw_vchnl_recv_vf(struct i40iw_sc_dev
*dev
,
566 struct i40iw_virtchnl_resp_buf
*vchnl_msg_resp
= (struct i40iw_virtchnl_resp_buf
*)msg
;
567 struct i40iw_virtchnl_req
*vchnl_req
;
569 vchnl_req
= (struct i40iw_virtchnl_req
*)(uintptr_t)vchnl_msg_resp
->iw_chnl_op_ctx
;
570 vchnl_req
->ret_code
= (enum i40iw_status_code
)vchnl_msg_resp
->iw_op_ret_code
;
571 if (len
== (sizeof(*vchnl_msg_resp
) + vchnl_req
->parm_len
- 1)) {
572 if (vchnl_req
->parm_len
&& vchnl_req
->parm
)
573 memcpy(vchnl_req
->parm
, vchnl_msg_resp
->iw_chnl_buf
, vchnl_req
->parm_len
);
574 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
575 "%s: Got response, data size %u\n", __func__
,
576 vchnl_req
->parm_len
);
578 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
579 "%s: error length on response, Got %u, expected %u\n", __func__
,
580 len
, (u32
)(sizeof(*vchnl_msg_resp
) + vchnl_req
->parm_len
- 1));
583 return I40IW_SUCCESS
;
587 * i40iw_vchnl_vf_get_ver - Request Channel version
588 * @dev: IWARP device pointer
589 * @vchnl_ver: Virtual channel message version pointer
591 enum i40iw_status_code
i40iw_vchnl_vf_get_ver(struct i40iw_sc_dev
*dev
,
594 struct i40iw_virtchnl_req vchnl_req
;
595 enum i40iw_status_code ret_code
;
597 if (!i40iw_vf_clear_to_send(dev
))
598 return I40IW_ERR_TIMEOUT
;
599 memset(&vchnl_req
, 0, sizeof(vchnl_req
));
601 vchnl_req
.parm
= vchnl_ver
;
602 vchnl_req
.parm_len
= sizeof(*vchnl_ver
);
603 vchnl_req
.vchnl_msg
= &dev
->vchnl_vf_msg_buf
.vchnl_msg
;
605 ret_code
= vchnl_vf_send_get_ver_req(dev
, &vchnl_req
);
607 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
608 "%s Send message failed 0x%0x\n", __func__
, ret_code
);
611 ret_code
= i40iw_vf_wait_vchnl_resp(dev
);
615 return vchnl_req
.ret_code
;
619 * i40iw_vchnl_vf_get_hmc_fcn - Request HMC Function
620 * @dev: IWARP device pointer
621 * @hmc_fcn: HMC function index pointer
623 enum i40iw_status_code
i40iw_vchnl_vf_get_hmc_fcn(struct i40iw_sc_dev
*dev
,
626 struct i40iw_virtchnl_req vchnl_req
;
627 enum i40iw_status_code ret_code
;
629 if (!i40iw_vf_clear_to_send(dev
))
630 return I40IW_ERR_TIMEOUT
;
631 memset(&vchnl_req
, 0, sizeof(vchnl_req
));
633 vchnl_req
.parm
= hmc_fcn
;
634 vchnl_req
.parm_len
= sizeof(*hmc_fcn
);
635 vchnl_req
.vchnl_msg
= &dev
->vchnl_vf_msg_buf
.vchnl_msg
;
637 ret_code
= vchnl_vf_send_get_hmc_fcn_req(dev
, &vchnl_req
);
639 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
640 "%s Send message failed 0x%0x\n", __func__
, ret_code
);
643 ret_code
= i40iw_vf_wait_vchnl_resp(dev
);
647 return vchnl_req
.ret_code
;
651 * i40iw_vchnl_vf_add_hmc_objs - Add HMC Object
652 * @dev: IWARP device pointer
653 * @rsrc_type: HMC Resource type
654 * @start_index: Starting index of the objects to be added
655 * @rsrc_count: Number of resources to be added
657 enum i40iw_status_code
i40iw_vchnl_vf_add_hmc_objs(struct i40iw_sc_dev
*dev
,
658 enum i40iw_hmc_rsrc_type rsrc_type
,
662 struct i40iw_virtchnl_req vchnl_req
;
663 enum i40iw_status_code ret_code
;
665 if (!i40iw_vf_clear_to_send(dev
))
666 return I40IW_ERR_TIMEOUT
;
667 memset(&vchnl_req
, 0, sizeof(vchnl_req
));
669 vchnl_req
.vchnl_msg
= &dev
->vchnl_vf_msg_buf
.vchnl_msg
;
671 ret_code
= vchnl_vf_send_add_hmc_objs_req(dev
,
677 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
678 "%s Send message failed 0x%0x\n", __func__
, ret_code
);
681 ret_code
= i40iw_vf_wait_vchnl_resp(dev
);
685 return vchnl_req
.ret_code
;
689 * i40iw_vchnl_vf_del_hmc_obj - del HMC obj
690 * @dev: IWARP device pointer
691 * @rsrc_type: HMC Resource type
692 * @start_index: Starting index of the object to delete
693 * @rsrc_count: Number of resources to be delete
695 enum i40iw_status_code
i40iw_vchnl_vf_del_hmc_obj(struct i40iw_sc_dev
*dev
,
696 enum i40iw_hmc_rsrc_type rsrc_type
,
700 struct i40iw_virtchnl_req vchnl_req
;
701 enum i40iw_status_code ret_code
;
703 if (!i40iw_vf_clear_to_send(dev
))
704 return I40IW_ERR_TIMEOUT
;
705 memset(&vchnl_req
, 0, sizeof(vchnl_req
));
707 vchnl_req
.vchnl_msg
= &dev
->vchnl_vf_msg_buf
.vchnl_msg
;
709 ret_code
= vchnl_vf_send_del_hmc_objs_req(dev
,
715 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
716 "%s Send message failed 0x%0x\n", __func__
, ret_code
);
719 ret_code
= i40iw_vf_wait_vchnl_resp(dev
);
723 return vchnl_req
.ret_code
;
727 * i40iw_vchnl_vf_get_pe_stats - Get PE stats
728 * @dev: IWARP device pointer
729 * @hw_stats: HW stats struct
731 enum i40iw_status_code
i40iw_vchnl_vf_get_pe_stats(struct i40iw_sc_dev
*dev
,
732 struct i40iw_dev_hw_stats
*hw_stats
)
734 struct i40iw_virtchnl_req vchnl_req
;
735 enum i40iw_status_code ret_code
;
737 if (!i40iw_vf_clear_to_send(dev
))
738 return I40IW_ERR_TIMEOUT
;
739 memset(&vchnl_req
, 0, sizeof(vchnl_req
));
741 vchnl_req
.parm
= hw_stats
;
742 vchnl_req
.parm_len
= sizeof(*hw_stats
);
743 vchnl_req
.vchnl_msg
= &dev
->vchnl_vf_msg_buf
.vchnl_msg
;
745 ret_code
= vchnl_vf_send_get_pe_stats_req(dev
, &vchnl_req
);
747 i40iw_debug(dev
, I40IW_DEBUG_VIRT
,
748 "%s Send message failed 0x%0x\n", __func__
, ret_code
);
751 ret_code
= i40iw_vf_wait_vchnl_resp(dev
);
755 return vchnl_req
.ret_code
;