xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c (revision 37a93dd5c49b5fda807fd204edf2547c3493319c)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3 
4 #include <linux/delay.h>
5 
6 #include "hinic3_cmdq.h"
7 #include "hinic3_hw_comm.h"
8 #include "hinic3_hwdev.h"
9 #include "hinic3_hwif.h"
10 #include "hinic3_mbox.h"
11 
hinic3_get_interrupt_cfg(struct hinic3_hwdev * hwdev,struct hinic3_interrupt_info * info)12 static int hinic3_get_interrupt_cfg(struct hinic3_hwdev *hwdev,
13 				    struct hinic3_interrupt_info *info)
14 {
15 	struct comm_cmd_cfg_msix_ctrl_reg msix_cfg = {};
16 	struct mgmt_msg_params msg_params = {};
17 	int err;
18 
19 	msix_cfg.func_id = hinic3_global_func_id(hwdev);
20 	msix_cfg.msix_index = info->msix_index;
21 	msix_cfg.opcode = MGMT_MSG_CMD_OP_GET;
22 
23 	mgmt_msg_params_init_default(&msg_params, &msix_cfg, sizeof(msix_cfg));
24 
25 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
26 				       COMM_CMD_CFG_MSIX_CTRL_REG, &msg_params);
27 	if (err || msix_cfg.head.status) {
28 		dev_err(hwdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x\n",
29 			err, msix_cfg.head.status);
30 		return -EFAULT;
31 	}
32 
33 	info->lli_credit_limit = msix_cfg.lli_credit_cnt;
34 	info->lli_timer_cfg = msix_cfg.lli_timer_cnt;
35 	info->pending_limit = msix_cfg.pending_cnt;
36 	info->coalesc_timer_cfg = msix_cfg.coalesce_timer_cnt;
37 	info->resend_timer_cfg = msix_cfg.resend_timer_cnt;
38 
39 	return 0;
40 }
41 
hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev * hwdev,const struct hinic3_interrupt_info * info)42 int hinic3_set_interrupt_cfg_direct(struct hinic3_hwdev *hwdev,
43 				    const struct hinic3_interrupt_info *info)
44 {
45 	struct comm_cmd_cfg_msix_ctrl_reg msix_cfg = {};
46 	struct mgmt_msg_params msg_params = {};
47 	int err;
48 
49 	msix_cfg.func_id = hinic3_global_func_id(hwdev);
50 	msix_cfg.msix_index = info->msix_index;
51 	msix_cfg.opcode = MGMT_MSG_CMD_OP_SET;
52 
53 	msix_cfg.lli_credit_cnt = info->lli_credit_limit;
54 	msix_cfg.lli_timer_cnt = info->lli_timer_cfg;
55 	msix_cfg.pending_cnt = info->pending_limit;
56 	msix_cfg.coalesce_timer_cnt = info->coalesc_timer_cfg;
57 	msix_cfg.resend_timer_cnt = info->resend_timer_cfg;
58 
59 	mgmt_msg_params_init_default(&msg_params, &msix_cfg, sizeof(msix_cfg));
60 
61 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
62 				       COMM_CMD_CFG_MSIX_CTRL_REG, &msg_params);
63 	if (err || msix_cfg.head.status) {
64 		dev_err(hwdev->dev,
65 			"Failed to set interrupt config, err: %d, status: 0x%x\n",
66 			err, msix_cfg.head.status);
67 		return -EINVAL;
68 	}
69 
70 	return 0;
71 }
72 
hinic3_set_interrupt_cfg(struct hinic3_hwdev * hwdev,struct hinic3_interrupt_info info)73 int hinic3_set_interrupt_cfg(struct hinic3_hwdev *hwdev,
74 			     struct hinic3_interrupt_info info)
75 {
76 	struct hinic3_interrupt_info temp_info;
77 	int err;
78 
79 	temp_info.msix_index = info.msix_index;
80 
81 	err = hinic3_get_interrupt_cfg(hwdev, &temp_info);
82 	if (err)
83 		return err;
84 
85 	info.lli_credit_limit = temp_info.lli_credit_limit;
86 	info.lli_timer_cfg = temp_info.lli_timer_cfg;
87 
88 	if (!info.interrupt_coalesc_set) {
89 		info.pending_limit = temp_info.pending_limit;
90 		info.coalesc_timer_cfg = temp_info.coalesc_timer_cfg;
91 		info.resend_timer_cfg = temp_info.resend_timer_cfg;
92 	}
93 
94 	return hinic3_set_interrupt_cfg_direct(hwdev, &info);
95 }
96 
hinic3_func_reset(struct hinic3_hwdev * hwdev,u16 func_id,u64 reset_flag)97 int hinic3_func_reset(struct hinic3_hwdev *hwdev, u16 func_id, u64 reset_flag)
98 {
99 	struct comm_cmd_func_reset func_reset = {};
100 	struct mgmt_msg_params msg_params = {};
101 	int err;
102 
103 	func_reset.func_id = func_id;
104 	func_reset.reset_flag = reset_flag;
105 
106 	mgmt_msg_params_init_default(&msg_params, &func_reset,
107 				     sizeof(func_reset));
108 
109 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
110 				       COMM_CMD_FUNC_RESET, &msg_params);
111 	if (err || func_reset.head.status) {
112 		dev_err(hwdev->dev, "Failed to reset func resources, reset_flag 0x%llx, err: %d, status: 0x%x\n",
113 			reset_flag, err, func_reset.head.status);
114 		return -EIO;
115 	}
116 
117 	return 0;
118 }
119 
hinic3_comm_features_nego(struct hinic3_hwdev * hwdev,u8 opcode,u64 * s_feature,u16 size)120 static int hinic3_comm_features_nego(struct hinic3_hwdev *hwdev, u8 opcode,
121 				     u64 *s_feature, u16 size)
122 {
123 	struct comm_cmd_feature_nego feature_nego = {};
124 	struct mgmt_msg_params msg_params = {};
125 	int err;
126 
127 	feature_nego.func_id = hinic3_global_func_id(hwdev);
128 	feature_nego.opcode = opcode;
129 	if (opcode == MGMT_MSG_CMD_OP_SET)
130 		memcpy(feature_nego.s_feature, s_feature,
131 		       array_size(size, sizeof(u64)));
132 
133 	mgmt_msg_params_init_default(&msg_params, &feature_nego,
134 				     sizeof(feature_nego));
135 
136 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
137 				       COMM_CMD_FEATURE_NEGO, &msg_params);
138 	if (err || feature_nego.head.status) {
139 		dev_err(hwdev->dev, "Failed to negotiate feature, err: %d, status: 0x%x\n",
140 			err, feature_nego.head.status);
141 		return -EINVAL;
142 	}
143 
144 	if (opcode == MGMT_MSG_CMD_OP_GET)
145 		memcpy(s_feature, feature_nego.s_feature,
146 		       array_size(size, sizeof(u64)));
147 
148 	return 0;
149 }
150 
hinic3_get_comm_features(struct hinic3_hwdev * hwdev,u64 * s_feature,u16 size)151 int hinic3_get_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature,
152 			     u16 size)
153 {
154 	return hinic3_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_GET, s_feature,
155 					 size);
156 }
157 
hinic3_set_comm_features(struct hinic3_hwdev * hwdev,u64 * s_feature,u16 size)158 int hinic3_set_comm_features(struct hinic3_hwdev *hwdev, u64 *s_feature,
159 			     u16 size)
160 {
161 	return hinic3_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_SET, s_feature,
162 					 size);
163 }
164 
hinic3_get_global_attr(struct hinic3_hwdev * hwdev,struct comm_global_attr * attr)165 int hinic3_get_global_attr(struct hinic3_hwdev *hwdev,
166 			   struct comm_global_attr *attr)
167 {
168 	struct comm_cmd_get_glb_attr get_attr = {};
169 	struct mgmt_msg_params msg_params = {};
170 	int err;
171 
172 	mgmt_msg_params_init_default(&msg_params, &get_attr, sizeof(get_attr));
173 
174 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
175 				       COMM_CMD_GET_GLOBAL_ATTR, &msg_params);
176 	if (err || get_attr.head.status) {
177 		dev_err(hwdev->dev,
178 			"Failed to get global attribute, err: %d, status: 0x%x\n",
179 			err, get_attr.head.status);
180 		return -EIO;
181 	}
182 
183 	memcpy(attr, &get_attr.attr, sizeof(*attr));
184 
185 	return 0;
186 }
187 
hinic3_set_func_svc_used_state(struct hinic3_hwdev * hwdev,u16 svc_type,u8 state)188 int hinic3_set_func_svc_used_state(struct hinic3_hwdev *hwdev, u16 svc_type,
189 				   u8 state)
190 {
191 	struct comm_cmd_set_func_svc_used_state used_state = {};
192 	struct mgmt_msg_params msg_params = {};
193 	int err;
194 
195 	used_state.func_id = hinic3_global_func_id(hwdev);
196 	used_state.svc_type = svc_type;
197 	used_state.used_state = state;
198 
199 	mgmt_msg_params_init_default(&msg_params, &used_state,
200 				     sizeof(used_state));
201 
202 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
203 				       COMM_CMD_SET_FUNC_SVC_USED_STATE,
204 				       &msg_params);
205 	if (err || used_state.head.status) {
206 		dev_err(hwdev->dev,
207 			"Failed to set func service used state, err: %d, status: 0x%x\n",
208 			err, used_state.head.status);
209 		return -EIO;
210 	}
211 
212 	return 0;
213 }
214 
hinic3_set_dma_attr_tbl(struct hinic3_hwdev * hwdev,u8 entry_idx,u8 st,u8 at,u8 ph,u8 no_snooping,u8 tph_en)215 int hinic3_set_dma_attr_tbl(struct hinic3_hwdev *hwdev, u8 entry_idx, u8 st,
216 			    u8 at, u8 ph, u8 no_snooping, u8 tph_en)
217 {
218 	struct comm_cmd_set_dma_attr dma_attr = {};
219 	struct mgmt_msg_params msg_params = {};
220 	int err;
221 
222 	dma_attr.func_id = hinic3_global_func_id(hwdev);
223 	dma_attr.entry_idx = entry_idx;
224 	dma_attr.st = st;
225 	dma_attr.at = at;
226 	dma_attr.ph = ph;
227 	dma_attr.no_snooping = no_snooping;
228 	dma_attr.tph_en = tph_en;
229 
230 	mgmt_msg_params_init_default(&msg_params, &dma_attr, sizeof(dma_attr));
231 
232 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
233 				       COMM_CMD_SET_DMA_ATTR, &msg_params);
234 	if (err || dma_attr.head.status) {
235 		dev_err(hwdev->dev, "Failed to set dma attr, err: %d, status: 0x%x\n",
236 			err, dma_attr.head.status);
237 		return -EIO;
238 	}
239 
240 	return 0;
241 }
242 
hinic3_set_wq_page_size(struct hinic3_hwdev * hwdev,u16 func_idx,u32 page_size)243 int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u16 func_idx,
244 			    u32 page_size)
245 {
246 	struct comm_cmd_cfg_wq_page_size page_size_info = {};
247 	struct mgmt_msg_params msg_params = {};
248 	int err;
249 
250 	page_size_info.func_id = func_idx;
251 	page_size_info.page_size = ilog2(page_size / HINIC3_MIN_PAGE_SIZE);
252 	page_size_info.opcode = MGMT_MSG_CMD_OP_SET;
253 
254 	mgmt_msg_params_init_default(&msg_params, &page_size_info,
255 				     sizeof(page_size_info));
256 
257 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
258 				       COMM_CMD_CFG_PAGESIZE, &msg_params);
259 	if (err || page_size_info.head.status) {
260 		dev_err(hwdev->dev,
261 			"Failed to set wq page size, err: %d, status: 0x%x\n",
262 			err, page_size_info.head.status);
263 		return -EFAULT;
264 	}
265 
266 	return 0;
267 }
268 
hinic3_set_cmdq_depth(struct hinic3_hwdev * hwdev,u16 cmdq_depth)269 int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth)
270 {
271 	struct comm_cmd_set_root_ctxt root_ctxt = {};
272 	struct mgmt_msg_params msg_params = {};
273 	int err;
274 
275 	root_ctxt.func_id = hinic3_global_func_id(hwdev);
276 
277 	root_ctxt.set_cmdq_depth = 1;
278 	root_ctxt.cmdq_depth = ilog2(cmdq_depth);
279 
280 	mgmt_msg_params_init_default(&msg_params, &root_ctxt,
281 				     sizeof(root_ctxt));
282 
283 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
284 				       COMM_CMD_SET_VAT, &msg_params);
285 	if (err || root_ctxt.head.status) {
286 		dev_err(hwdev->dev,
287 			"Failed to set cmdq depth, err: %d, status: 0x%x\n",
288 			err, root_ctxt.head.status);
289 		return -EFAULT;
290 	}
291 
292 	return 0;
293 }
294 
295 #define HINIC3_WAIT_CMDQ_IDLE_TIMEOUT    5000
296 
check_cmdq_stop_handler(void * priv_data)297 static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data)
298 {
299 	struct hinic3_hwdev *hwdev = priv_data;
300 	enum hinic3_cmdq_type cmdq_type;
301 	struct hinic3_cmdqs *cmdqs;
302 
303 	cmdqs = hwdev->cmdqs;
304 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
305 		if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type]))
306 			return HINIC3_WAIT_PROCESS_WAITING;
307 	}
308 
309 	return HINIC3_WAIT_PROCESS_CPL;
310 }
311 
wait_cmdq_stop(struct hinic3_hwdev * hwdev)312 static int wait_cmdq_stop(struct hinic3_hwdev *hwdev)
313 {
314 	struct hinic3_cmdqs *cmdqs = hwdev->cmdqs;
315 	enum hinic3_cmdq_type cmdq_type;
316 	int err;
317 
318 	if (!(cmdqs->status & HINIC3_CMDQ_ENABLE))
319 		return 0;
320 
321 	cmdqs->status &= ~HINIC3_CMDQ_ENABLE;
322 	err = hinic3_wait_for_timeout(hwdev, check_cmdq_stop_handler,
323 				      HINIC3_WAIT_CMDQ_IDLE_TIMEOUT,
324 				      USEC_PER_MSEC);
325 
326 	if (err)
327 		goto err_reenable_cmdq;
328 
329 	return 0;
330 
331 err_reenable_cmdq:
332 	for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) {
333 		if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type]))
334 			dev_err(hwdev->dev, "Cmdq %d is busy\n", cmdq_type);
335 	}
336 	cmdqs->status |= HINIC3_CMDQ_ENABLE;
337 
338 	return err;
339 }
340 
hinic3_func_rx_tx_flush(struct hinic3_hwdev * hwdev)341 int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev)
342 {
343 	struct comm_cmd_clear_resource clear_db = {};
344 	struct comm_cmd_clear_resource clr_res = {};
345 	struct hinic3_hwif *hwif = hwdev->hwif;
346 	struct mgmt_msg_params msg_params = {};
347 	int ret = 0;
348 	int err;
349 
350 	err = wait_cmdq_stop(hwdev);
351 	if (err) {
352 		dev_warn(hwdev->dev, "CMDQ is still working, CMDQ timeout value is unreasonable\n");
353 		ret = err;
354 	}
355 
356 	hinic3_toggle_doorbell(hwif, DISABLE_DOORBELL);
357 
358 	clear_db.func_id = hwif->attr.func_global_idx;
359 	mgmt_msg_params_init_default(&msg_params, &clear_db, sizeof(clear_db));
360 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
361 				       COMM_CMD_FLUSH_DOORBELL, &msg_params);
362 	if (err || clear_db.head.status) {
363 		dev_warn(hwdev->dev, "Failed to flush doorbell, err: %d, status: 0x%x\n",
364 			 err, clear_db.head.status);
365 		if (err)
366 			ret = err;
367 		else
368 			ret = -EFAULT;
369 	}
370 
371 	hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_FLR_START_FLAG);
372 
373 	clr_res.func_id = hwif->attr.func_global_idx;
374 	msg_params.buf_in = &clr_res;
375 	msg_params.in_size = sizeof(clr_res);
376 	err = hinic3_send_mbox_to_mgmt_no_ack(hwdev, MGMT_MOD_COMM,
377 					      COMM_CMD_START_FLUSH,
378 					      &msg_params);
379 	if (err) {
380 		dev_warn(hwdev->dev, "Failed to notice flush message, err: %d\n",
381 			 err);
382 		ret = err;
383 	}
384 
385 	hinic3_toggle_doorbell(hwif, ENABLE_DOORBELL);
386 
387 	err = hinic3_reinit_cmdq_ctxts(hwdev);
388 	if (err) {
389 		dev_warn(hwdev->dev, "Failed to reinit cmdq\n");
390 		ret = err;
391 	}
392 
393 	return ret;
394 }
395 
hinic3_set_bdf_ctxt(struct hinic3_hwdev * hwdev,struct comm_cmd_bdf_info * bdf_info)396 int hinic3_set_bdf_ctxt(struct hinic3_hwdev *hwdev,
397 			struct comm_cmd_bdf_info *bdf_info)
398 {
399 	struct mgmt_msg_params msg_params = {};
400 	int err;
401 
402 	mgmt_msg_params_init_default(&msg_params, bdf_info, sizeof(*bdf_info));
403 
404 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
405 				       COMM_CMD_SEND_BDF_INFO, &msg_params);
406 	if (err || bdf_info->head.status) {
407 		dev_err(hwdev->dev,
408 			"Failed to set bdf info to fw, err: %d, status: 0x%x\n",
409 			err, bdf_info->head.status);
410 		return -EFAULT;
411 	}
412 
413 	return 0;
414 }
415 
hinic3_sync_time(struct hinic3_hwdev * hwdev,u64 time)416 static int hinic3_sync_time(struct hinic3_hwdev *hwdev, u64 time)
417 {
418 	struct comm_cmd_sync_time time_info = {};
419 	struct mgmt_msg_params msg_params = {};
420 	int err;
421 
422 	time_info.mstime = time;
423 
424 	mgmt_msg_params_init_default(&msg_params, &time_info,
425 				     sizeof(time_info));
426 
427 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
428 				       COMM_CMD_SYNC_TIME, &msg_params);
429 	if (err || time_info.head.status) {
430 		dev_err(hwdev->dev,
431 			"Failed to sync time to mgmt, err: %d, status: 0x%x\n",
432 			err, time_info.head.status);
433 		return -EFAULT;
434 	}
435 
436 	return 0;
437 }
438 
hinic3_sync_time_to_fw(struct hinic3_hwdev * hwdev)439 void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev)
440 {
441 	struct timespec64 ts = {};
442 	u64 time;
443 	int err;
444 
445 	ktime_get_real_ts64(&ts);
446 	time = (u64)(ts.tv_sec * MSEC_PER_SEC + ts.tv_nsec / NSEC_PER_MSEC);
447 
448 	err = hinic3_sync_time(hwdev, time);
449 	if (err)
450 		dev_err(hwdev->dev,
451 			"Synchronize UTC time to firmware failed, err=%d\n",
452 			err);
453 }
454 
get_hw_rx_buf_size_idx(int rx_buf_sz,u16 * buf_sz_idx)455 static int get_hw_rx_buf_size_idx(int rx_buf_sz, u16 *buf_sz_idx)
456 {
457 	/* Supported RX buffer sizes in bytes. Configured by array index. */
458 	static const int supported_sizes[16] = {
459 		[0] = 32,     [1] = 64,     [2] = 96,     [3] = 128,
460 		[4] = 192,    [5] = 256,    [6] = 384,    [7] = 512,
461 		[8] = 768,    [9] = 1024,   [10] = 1536,  [11] = 2048,
462 		[12] = 3072,  [13] = 4096,  [14] = 8192,  [15] = 16384,
463 	};
464 	u16 idx;
465 
466 	/* Scan from biggest to smallest. Choose supported size that is equal or
467 	 * smaller. For smaller value HW will under-utilize posted buffers. For
468 	 * bigger value HW may overrun posted buffers.
469 	 */
470 	idx = ARRAY_SIZE(supported_sizes);
471 	while (idx > 0) {
472 		idx--;
473 		if (supported_sizes[idx] <= rx_buf_sz) {
474 			*buf_sz_idx = idx;
475 			return 0;
476 		}
477 	}
478 
479 	return -EINVAL;
480 }
481 
hinic3_set_root_ctxt(struct hinic3_hwdev * hwdev,u32 rq_depth,u32 sq_depth,int rx_buf_sz)482 int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_depth,
483 			 int rx_buf_sz)
484 {
485 	struct comm_cmd_set_root_ctxt root_ctxt = {};
486 	struct mgmt_msg_params msg_params = {};
487 	u16 buf_sz_idx;
488 	int err;
489 
490 	err = get_hw_rx_buf_size_idx(rx_buf_sz, &buf_sz_idx);
491 	if (err)
492 		return err;
493 
494 	root_ctxt.func_id = hinic3_global_func_id(hwdev);
495 
496 	root_ctxt.set_cmdq_depth = 0;
497 	root_ctxt.cmdq_depth = 0;
498 
499 	root_ctxt.lro_en = 1;
500 
501 	root_ctxt.rq_depth  = ilog2(rq_depth);
502 	root_ctxt.rx_buf_sz = buf_sz_idx;
503 	root_ctxt.sq_depth  = ilog2(sq_depth);
504 
505 	mgmt_msg_params_init_default(&msg_params, &root_ctxt,
506 				     sizeof(root_ctxt));
507 
508 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
509 				       COMM_CMD_SET_VAT, &msg_params);
510 	if (err || root_ctxt.head.status) {
511 		dev_err(hwdev->dev,
512 			"Failed to set root context, err: %d, status: 0x%x\n",
513 			err, root_ctxt.head.status);
514 		return -EFAULT;
515 	}
516 
517 	return 0;
518 }
519 
hinic3_clean_root_ctxt(struct hinic3_hwdev * hwdev)520 int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev)
521 {
522 	struct comm_cmd_set_root_ctxt root_ctxt = {};
523 	struct mgmt_msg_params msg_params = {};
524 	int err;
525 
526 	root_ctxt.func_id = hinic3_global_func_id(hwdev);
527 
528 	mgmt_msg_params_init_default(&msg_params, &root_ctxt,
529 				     sizeof(root_ctxt));
530 
531 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM,
532 				       COMM_CMD_SET_VAT, &msg_params);
533 	if (err || root_ctxt.head.status) {
534 		dev_err(hwdev->dev,
535 			"Failed to set root context, err: %d, status: 0x%x\n",
536 			err, root_ctxt.head.status);
537 		return -EFAULT;
538 	}
539 
540 	return 0;
541 }
542