xref: /linux/drivers/infiniband/hw/efa/efa_com_cmd.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
2 /*
3  * Copyright 2018-2026 Amazon.com, Inc. or its affiliates. All rights reserved.
4  */
5 
6 #include "efa_com.h"
7 #include "efa_com_cmd.h"
8 
9 #define EFA_DEFAULT_LINK_SPEED_GBPS 100
10 
11 int efa_com_create_qp(struct efa_com_dev *edev,
12 		      struct efa_com_create_qp_params *params,
13 		      struct efa_com_create_qp_result *res)
14 {
15 	struct efa_admin_create_qp_cmd create_qp_cmd = {};
16 	struct efa_admin_create_qp_resp cmd_completion;
17 	struct efa_com_admin_queue *aq = &edev->aq;
18 	int err;
19 
20 	create_qp_cmd.pd = params->pd;
21 	create_qp_cmd.qp_type = params->qp_type;
22 	create_qp_cmd.rq_base_addr = params->rq_base_addr;
23 	create_qp_cmd.send_cq_idx = params->send_cq_idx;
24 	create_qp_cmd.recv_cq_idx = params->recv_cq_idx;
25 	create_qp_cmd.qp_alloc_size.send_queue_ring_size =
26 		params->sq_ring_size_in_bytes;
27 	create_qp_cmd.qp_alloc_size.send_queue_depth =
28 			params->sq_depth;
29 	create_qp_cmd.qp_alloc_size.recv_queue_ring_size =
30 			params->rq_ring_size_in_bytes;
31 	create_qp_cmd.qp_alloc_size.recv_queue_depth =
32 			params->rq_depth;
33 	create_qp_cmd.uar = params->uarn;
34 	create_qp_cmd.sl = params->sl;
35 
36 	if (params->unsolicited_write_recv)
37 		EFA_SET(&create_qp_cmd.flags, EFA_ADMIN_CREATE_QP_CMD_UNSOLICITED_WRITE_RECV, 1);
38 
39 	if (params->sq_64_bit_req_id)
40 		EFA_SET(&create_qp_cmd.flags, EFA_ADMIN_CREATE_QP_CMD_SQ_64_BIT_REQ_ID, 1);
41 
42 	err = efa_com_cmd_exec(aq, EFA_ADMIN_CREATE_QP, 0,
43 			       &create_qp_cmd, sizeof(create_qp_cmd),
44 			       (struct efa_admin_acq_entry *)&cmd_completion,
45 			       sizeof(cmd_completion));
46 	if (err) {
47 		ibdev_err_ratelimited(edev->efa_dev,
48 				      "Failed to create qp [%d]\n", err);
49 		return err;
50 	}
51 
52 	res->qp_handle = cmd_completion.qp_handle;
53 	res->qp_num = cmd_completion.qp_num;
54 	res->sq_db_offset = cmd_completion.sq_db_offset;
55 	res->rq_db_offset = cmd_completion.rq_db_offset;
56 	res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset;
57 	res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx;
58 	res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx;
59 
60 	return 0;
61 }
62 
63 int efa_com_modify_qp(struct efa_com_dev *edev,
64 		      struct efa_com_modify_qp_params *params)
65 {
66 	struct efa_com_admin_queue *aq = &edev->aq;
67 	struct efa_admin_modify_qp_cmd cmd = {};
68 	struct efa_admin_modify_qp_resp resp;
69 	int err;
70 
71 	cmd.modify_mask = params->modify_mask;
72 	cmd.qp_handle = params->qp_handle;
73 	cmd.qp_state = params->qp_state;
74 	cmd.cur_qp_state = params->cur_qp_state;
75 	cmd.qkey = params->qkey;
76 	cmd.sq_psn = params->sq_psn;
77 	cmd.sq_drained_async_notify = params->sq_drained_async_notify;
78 	cmd.rnr_retry = params->rnr_retry;
79 
80 	err = efa_com_cmd_exec(aq, EFA_ADMIN_MODIFY_QP, 0,
81 			       &cmd, sizeof(cmd),
82 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
83 	if (err) {
84 		ibdev_err_ratelimited(
85 			edev->efa_dev,
86 			"Failed to modify qp-%u modify_mask[%#x] [%d]\n",
87 			cmd.qp_handle, cmd.modify_mask, err);
88 		return err;
89 	}
90 
91 	return 0;
92 }
93 
94 int efa_com_query_qp(struct efa_com_dev *edev,
95 		     struct efa_com_query_qp_params *params,
96 		     struct efa_com_query_qp_result *result)
97 {
98 	struct efa_com_admin_queue *aq = &edev->aq;
99 	struct efa_admin_query_qp_cmd cmd = {};
100 	struct efa_admin_query_qp_resp resp;
101 	int err;
102 
103 	cmd.qp_handle = params->qp_handle;
104 
105 	err = efa_com_cmd_exec(aq, EFA_ADMIN_QUERY_QP, 0,
106 			       &cmd, sizeof(cmd),
107 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
108 	if (err) {
109 		ibdev_err_ratelimited(edev->efa_dev,
110 				      "Failed to query qp-%u [%d]\n",
111 				      cmd.qp_handle, err);
112 		return err;
113 	}
114 
115 	result->qp_state = resp.qp_state;
116 	result->qkey = resp.qkey;
117 	result->sq_draining = resp.sq_draining;
118 	result->sq_psn = resp.sq_psn;
119 	result->rnr_retry = resp.rnr_retry;
120 
121 	return 0;
122 }
123 
124 int efa_com_destroy_qp(struct efa_com_dev *edev,
125 		       struct efa_com_destroy_qp_params *params)
126 {
127 	struct efa_admin_destroy_qp_resp cmd_completion;
128 	struct efa_admin_destroy_qp_cmd qp_cmd = {};
129 	struct efa_com_admin_queue *aq = &edev->aq;
130 	int err;
131 
132 	qp_cmd.qp_handle = params->qp_handle;
133 
134 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DESTROY_QP, 0,
135 			       &qp_cmd, sizeof(qp_cmd),
136 			       (struct efa_admin_acq_entry *)&cmd_completion,
137 			       sizeof(cmd_completion));
138 	if (err) {
139 		ibdev_err_ratelimited(edev->efa_dev,
140 				      "Failed to destroy qp-%u [%d]\n",
141 				      qp_cmd.qp_handle, err);
142 		return err;
143 	}
144 
145 	return 0;
146 }
147 
148 int efa_com_create_cq(struct efa_com_dev *edev,
149 		      struct efa_com_create_cq_params *params,
150 		      struct efa_com_create_cq_result *result)
151 {
152 	struct efa_admin_create_cq_resp cmd_completion = {};
153 	struct efa_admin_create_cq_cmd create_cmd = {};
154 	struct efa_com_admin_queue *aq = &edev->aq;
155 	int err;
156 
157 	EFA_SET(&create_cmd.cq_caps_2,
158 		EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS,
159 		params->entry_size_in_bytes / 4);
160 	create_cmd.sub_cq_depth = params->sub_cq_depth;
161 	create_cmd.num_sub_cqs = params->num_sub_cqs;
162 	create_cmd.uar = params->uarn;
163 	if (params->interrupt_mode_enabled) {
164 		EFA_SET(&create_cmd.cq_caps_1,
165 			EFA_ADMIN_CREATE_CQ_CMD_INTERRUPT_MODE_ENABLED, 1);
166 		create_cmd.eqn = params->eqn;
167 	}
168 	if (params->set_src_addr) {
169 		EFA_SET(&create_cmd.cq_caps_2,
170 			EFA_ADMIN_CREATE_CQ_CMD_SET_SRC_ADDR, 1);
171 	}
172 	if (params->sq_comp_64_bit_req_id) {
173 		EFA_SET(&create_cmd.cq_caps_2,
174 			EFA_ADMIN_CREATE_CQ_CMD_SQ_COMP_64_BIT_REQ_ID, 1);
175 	}
176 
177 	efa_com_set_dma_addr(params->dma_addr,
178 			     &create_cmd.cq_ba.mem_addr_high,
179 			     &create_cmd.cq_ba.mem_addr_low);
180 
181 	err = efa_com_cmd_exec(aq, EFA_ADMIN_CREATE_CQ, 0,
182 			       &create_cmd, sizeof(create_cmd),
183 			       (struct efa_admin_acq_entry *)&cmd_completion,
184 			       sizeof(cmd_completion));
185 	if (err) {
186 		ibdev_err_ratelimited(edev->efa_dev,
187 				      "Failed to create cq[%d]\n", err);
188 		return err;
189 	}
190 
191 	result->cq_idx = cmd_completion.cq_idx;
192 	result->actual_depth = params->sub_cq_depth;
193 	result->db_off = cmd_completion.db_offset;
194 	result->db_valid = EFA_GET(&cmd_completion.flags,
195 				   EFA_ADMIN_CREATE_CQ_RESP_DB_VALID);
196 
197 	return 0;
198 }
199 
200 int efa_com_destroy_cq(struct efa_com_dev *edev,
201 		       struct efa_com_destroy_cq_params *params)
202 {
203 	struct efa_admin_destroy_cq_cmd destroy_cmd = {};
204 	struct efa_admin_destroy_cq_resp destroy_resp;
205 	struct efa_com_admin_queue *aq = &edev->aq;
206 	int err;
207 
208 	destroy_cmd.cq_idx = params->cq_idx;
209 
210 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DESTROY_CQ, 0,
211 			       &destroy_cmd, sizeof(destroy_cmd),
212 			       (struct efa_admin_acq_entry *)&destroy_resp,
213 			       sizeof(destroy_resp));
214 
215 	if (err) {
216 		ibdev_err_ratelimited(edev->efa_dev,
217 				      "Failed to destroy CQ-%u [%d]\n",
218 				      params->cq_idx, err);
219 		return err;
220 	}
221 
222 	return 0;
223 }
224 
225 int efa_com_register_mr(struct efa_com_dev *edev,
226 			struct efa_com_reg_mr_params *params,
227 			struct efa_com_reg_mr_result *result)
228 {
229 	struct efa_admin_reg_mr_resp cmd_completion;
230 	struct efa_com_admin_queue *aq = &edev->aq;
231 	struct efa_admin_reg_mr_cmd mr_cmd = {};
232 	u8 flags = 0;
233 	int err;
234 
235 	mr_cmd.pd = params->pd;
236 	mr_cmd.mr_length = params->mr_length_in_bytes;
237 	EFA_SET(&mr_cmd.flags, EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT,
238 		params->page_shift);
239 	mr_cmd.iova = params->iova;
240 	mr_cmd.permissions = params->permissions;
241 
242 	if (params->inline_pbl) {
243 		memcpy(mr_cmd.pbl.inline_pbl_array,
244 		       params->pbl.inline_pbl_array,
245 		       sizeof(mr_cmd.pbl.inline_pbl_array));
246 	} else {
247 		mr_cmd.pbl.pbl.length = params->pbl.pbl.length;
248 		mr_cmd.pbl.pbl.address.mem_addr_low =
249 			params->pbl.pbl.address.mem_addr_low;
250 		mr_cmd.pbl.pbl.address.mem_addr_high =
251 			params->pbl.pbl.address.mem_addr_high;
252 		EFA_SET(&flags, EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);
253 		if (params->indirect)
254 			EFA_SET(&flags, EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT, 1);
255 	}
256 
257 	err = efa_com_cmd_exec(aq, EFA_ADMIN_REG_MR, flags,
258 			       &mr_cmd, sizeof(mr_cmd),
259 			       (struct efa_admin_acq_entry *)&cmd_completion,
260 			       sizeof(cmd_completion));
261 	if (err) {
262 		ibdev_err_ratelimited(edev->efa_dev,
263 				      "Failed to register mr [%d]\n", err);
264 		return err;
265 	}
266 
267 	result->l_key = cmd_completion.l_key;
268 	result->r_key = cmd_completion.r_key;
269 	result->ic_info.recv_ic_id = cmd_completion.recv_ic_id;
270 	result->ic_info.rdma_read_ic_id = cmd_completion.rdma_read_ic_id;
271 	result->ic_info.rdma_recv_ic_id = cmd_completion.rdma_recv_ic_id;
272 	result->ic_info.recv_ic_id_valid = EFA_GET(&cmd_completion.validity,
273 						   EFA_ADMIN_REG_MR_RESP_RECV_IC_ID);
274 	result->ic_info.rdma_read_ic_id_valid = EFA_GET(&cmd_completion.validity,
275 							EFA_ADMIN_REG_MR_RESP_RDMA_READ_IC_ID);
276 	result->ic_info.rdma_recv_ic_id_valid = EFA_GET(&cmd_completion.validity,
277 							EFA_ADMIN_REG_MR_RESP_RDMA_RECV_IC_ID);
278 
279 	return 0;
280 }
281 
282 int efa_com_dereg_mr(struct efa_com_dev *edev,
283 		     struct efa_com_dereg_mr_params *params)
284 {
285 	struct efa_admin_dereg_mr_resp cmd_completion;
286 	struct efa_com_admin_queue *aq = &edev->aq;
287 	struct efa_admin_dereg_mr_cmd mr_cmd = {};
288 	int err;
289 
290 	mr_cmd.l_key = params->l_key;
291 
292 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DEREG_MR, 0,
293 			       &mr_cmd, sizeof(mr_cmd),
294 			       (struct efa_admin_acq_entry *)&cmd_completion,
295 			       sizeof(cmd_completion));
296 	if (err) {
297 		ibdev_err_ratelimited(edev->efa_dev,
298 				      "Failed to de-register mr(lkey-%u) [%d]\n",
299 				      mr_cmd.l_key, err);
300 		return err;
301 	}
302 
303 	return 0;
304 }
305 
306 int efa_com_create_ah(struct efa_com_dev *edev,
307 		      struct efa_com_create_ah_params *params,
308 		      struct efa_com_create_ah_result *result)
309 {
310 	struct efa_admin_create_ah_resp cmd_completion;
311 	struct efa_com_admin_queue *aq = &edev->aq;
312 	struct efa_admin_create_ah_cmd ah_cmd = {};
313 	struct efa_ah_cache_entry *entry;
314 	int err;
315 
316 	entry = efa_ah_cache_get(&edev->ah_cache, params->pdn, params->dest_addr);
317 	if (IS_ERR(entry))
318 		return PTR_ERR(entry);
319 
320 	mutex_lock(&entry->lock);
321 	if (entry->usecnt) {
322 		result->ah = entry->ah;
323 		entry->usecnt++;
324 		mutex_unlock(&entry->lock);
325 		return 0;
326 	}
327 
328 	memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr));
329 	ah_cmd.pd = params->pdn;
330 
331 	err = efa_com_cmd_exec(aq, EFA_ADMIN_CREATE_AH, 0,
332 			       &ah_cmd, sizeof(ah_cmd),
333 			       (struct efa_admin_acq_entry *)&cmd_completion,
334 			       sizeof(cmd_completion));
335 	if (err) {
336 		mutex_unlock(&entry->lock);
337 		efa_ah_cache_put(&edev->ah_cache, entry);
338 		ibdev_err_ratelimited(edev->efa_dev,
339 				      "Failed to create ah for %pI6 [%d]\n",
340 				      ah_cmd.dest_addr, err);
341 		return err;
342 	}
343 
344 	entry->ah = cmd_completion.ah;
345 	result->ah = cmd_completion.ah;
346 	entry->usecnt++;
347 	mutex_unlock(&entry->lock);
348 
349 	return 0;
350 }
351 
352 int efa_com_destroy_ah(struct efa_com_dev *edev,
353 		       struct efa_com_destroy_ah_params *params)
354 {
355 	struct efa_admin_destroy_ah_resp cmd_completion;
356 	struct efa_admin_destroy_ah_cmd ah_cmd = {};
357 	struct efa_com_admin_queue *aq = &edev->aq;
358 	struct efa_ah_cache_entry *entry;
359 	int err = 0;
360 
361 	entry = efa_ah_cache_lookup(&edev->ah_cache, params->pdn, params->gid);
362 	if (!entry)
363 		return -EINVAL;
364 
365 	mutex_lock(&entry->lock);
366 	if (entry->usecnt > 1)
367 		goto out_put;
368 
369 	ah_cmd.ah = entry->ah;
370 	ah_cmd.pd = entry->key.pd;
371 
372 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DESTROY_AH, 0,
373 			       &ah_cmd, sizeof(ah_cmd),
374 			       (struct efa_admin_acq_entry *)&cmd_completion,
375 			       sizeof(cmd_completion));
376 	if (err) {
377 		mutex_unlock(&entry->lock);
378 		ibdev_err_ratelimited(edev->efa_dev,
379 				      "Failed to destroy ah-%d pd-%d [%d]\n",
380 				      ah_cmd.ah, ah_cmd.pd, err);
381 		return err;
382 	}
383 
384 out_put:
385 	entry->usecnt--;
386 	mutex_unlock(&entry->lock);
387 	efa_ah_cache_put(&edev->ah_cache, entry);
388 
389 	return err;
390 }
391 
392 bool
393 efa_com_check_supported_feature_id(struct efa_com_dev *edev,
394 				   enum efa_admin_aq_feature_id feature_id)
395 {
396 	u32 feature_mask = 1 << feature_id;
397 
398 	/* Device attributes is always supported */
399 	if (feature_id != EFA_ADMIN_DEVICE_ATTR &&
400 	    !(edev->supported_features & feature_mask))
401 		return false;
402 
403 	return true;
404 }
405 
406 static int efa_com_get_feature_ex(struct efa_com_dev *edev,
407 				  struct efa_admin_get_feature_resp *get_resp,
408 				  enum efa_admin_aq_feature_id feature_id,
409 				  dma_addr_t control_buf_dma_addr,
410 				  u32 control_buff_size)
411 {
412 	struct efa_admin_get_feature_cmd get_cmd = {};
413 	struct efa_com_admin_queue *aq;
414 	u8 flags = 0;
415 	int err;
416 
417 	if (!efa_com_check_supported_feature_id(edev, feature_id)) {
418 		ibdev_err_ratelimited(edev->efa_dev,
419 				      "Feature %d isn't supported\n",
420 				      feature_id);
421 		return -EOPNOTSUPP;
422 	}
423 
424 	aq = &edev->aq;
425 
426 	if (control_buff_size)
427 		EFA_SET(&flags, EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);
428 
429 	efa_com_set_dma_addr(control_buf_dma_addr,
430 			     &get_cmd.control_buffer.address.mem_addr_high,
431 			     &get_cmd.control_buffer.address.mem_addr_low);
432 
433 	get_cmd.control_buffer.length = control_buff_size;
434 	get_cmd.feature_common.feature_id = feature_id;
435 	err = efa_com_cmd_exec(aq, EFA_ADMIN_GET_FEATURE, flags,
436 			       &get_cmd, sizeof(get_cmd),
437 			       (struct efa_admin_acq_entry *)get_resp,
438 			       sizeof(*get_resp));
439 
440 	if (err) {
441 		ibdev_err_ratelimited(
442 			edev->efa_dev,
443 			"Failed to submit get_feature command %d [%d]\n",
444 			feature_id, err);
445 		return err;
446 	}
447 
448 	return 0;
449 }
450 
451 static int efa_com_get_feature(struct efa_com_dev *edev,
452 			       struct efa_admin_get_feature_resp *get_resp,
453 			       enum efa_admin_aq_feature_id feature_id)
454 {
455 	return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0);
456 }
457 
458 int efa_com_get_device_attr(struct efa_com_dev *edev,
459 			    struct efa_com_get_device_attr_result *result)
460 {
461 	struct efa_admin_get_feature_resp resp;
462 	int err;
463 
464 	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR);
465 	if (err) {
466 		ibdev_err_ratelimited(edev->efa_dev,
467 				      "Failed to get device attributes %d\n",
468 				      err);
469 		return err;
470 	}
471 
472 	result->page_size_cap = resp.u.device_attr.page_size_cap;
473 	result->fw_version = resp.u.device_attr.fw_version;
474 	result->admin_api_version = resp.u.device_attr.admin_api_version;
475 	result->device_version = resp.u.device_attr.device_version;
476 	result->supported_features = resp.u.device_attr.supported_features;
477 	result->phys_addr_width = resp.u.device_attr.phys_addr_width;
478 	result->virt_addr_width = resp.u.device_attr.virt_addr_width;
479 	result->db_bar = resp.u.device_attr.db_bar;
480 	result->max_rdma_size = resp.u.device_attr.max_rdma_size;
481 	result->device_caps = resp.u.device_attr.device_caps;
482 	result->guid = resp.u.device_attr.guid;
483 	result->max_link_speed_gbps = resp.u.device_attr.max_link_speed_gbps;
484 	if (!result->max_link_speed_gbps)
485 		result->max_link_speed_gbps = EFA_DEFAULT_LINK_SPEED_GBPS;
486 
487 	if (result->admin_api_version < 1) {
488 		ibdev_err_ratelimited(
489 			edev->efa_dev,
490 			"Failed to get device attr api version [%u < 1]\n",
491 			result->admin_api_version);
492 		return -EINVAL;
493 	}
494 
495 	edev->supported_features = resp.u.device_attr.supported_features;
496 	err = efa_com_get_feature(edev, &resp,
497 				  EFA_ADMIN_QUEUE_ATTR_1);
498 	if (err) {
499 		ibdev_err_ratelimited(edev->efa_dev,
500 				      "Failed to get queue attributes1 %d\n",
501 				      err);
502 		return err;
503 	}
504 
505 	result->max_qp = resp.u.queue_attr_1.max_qp;
506 	result->max_sq_depth = resp.u.queue_attr_1.max_sq_depth;
507 	result->max_rq_depth = resp.u.queue_attr_1.max_rq_depth;
508 	result->max_cq = resp.u.queue_attr_1.max_cq;
509 	result->max_cq_depth = resp.u.queue_attr_1.max_cq_depth;
510 	result->inline_buf_size = resp.u.queue_attr_1.inline_buf_size;
511 	result->max_sq_sge = resp.u.queue_attr_1.max_wr_send_sges;
512 	result->max_rq_sge = resp.u.queue_attr_1.max_wr_recv_sges;
513 	result->max_mr = resp.u.queue_attr_1.max_mr;
514 	result->max_mr_pages = resp.u.queue_attr_1.max_mr_pages;
515 	result->max_pd = resp.u.queue_attr_1.max_pd;
516 	result->max_ah = resp.u.queue_attr_1.max_ah;
517 	result->max_llq_size = resp.u.queue_attr_1.max_llq_size;
518 	result->sub_cqs_per_cq = resp.u.queue_attr_1.sub_cqs_per_cq;
519 	result->max_wr_rdma_sge = resp.u.queue_attr_1.max_wr_rdma_sges;
520 	result->max_tx_batch = resp.u.queue_attr_1.max_tx_batch;
521 	result->min_sq_depth = resp.u.queue_attr_1.min_sq_depth;
522 
523 	if (efa_com_check_supported_feature_id(edev, EFA_ADMIN_QUEUE_ATTR_2)) {
524 		err = efa_com_get_feature(edev, &resp,
525 					  EFA_ADMIN_QUEUE_ATTR_2);
526 		if (err) {
527 			ibdev_err_ratelimited(
528 				edev->efa_dev,
529 				"Failed to get queue attributes2 %d\n", err);
530 			return err;
531 		}
532 
533 		result->inline_buf_size_ex = resp.u.queue_attr_2.inline_buf_size_ex;
534 		result->max_event_counters = resp.u.queue_attr_2.max_event_counters;
535 		result->event_counter_max_val = resp.u.queue_attr_2.event_counter_max_val;
536 		result->supported_event_counter_qp_events =
537 			resp.u.queue_attr_2.supported_event_counter_qp_events;
538 	} else {
539 		result->inline_buf_size_ex = result->inline_buf_size;
540 	}
541 
542 	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_NETWORK_ATTR);
543 	if (err) {
544 		ibdev_err_ratelimited(edev->efa_dev,
545 				      "Failed to get network attributes %d\n",
546 				      err);
547 		return err;
548 	}
549 
550 	memcpy(result->addr, resp.u.network_attr.addr,
551 	       sizeof(resp.u.network_attr.addr));
552 	result->mtu = resp.u.network_attr.mtu;
553 
554 	if (efa_com_check_supported_feature_id(edev,
555 					       EFA_ADMIN_EVENT_QUEUE_ATTR)) {
556 		err = efa_com_get_feature(edev, &resp,
557 					  EFA_ADMIN_EVENT_QUEUE_ATTR);
558 		if (err) {
559 			ibdev_err_ratelimited(
560 				edev->efa_dev,
561 				"Failed to get event queue attributes %d\n",
562 				err);
563 			return err;
564 		}
565 
566 		result->max_eq = resp.u.event_queue_attr.max_eq;
567 		result->max_eq_depth = resp.u.event_queue_attr.max_eq_depth;
568 		result->event_bitmask = resp.u.event_queue_attr.event_bitmask;
569 	}
570 
571 	return 0;
572 }
573 
574 int efa_com_get_hw_hints(struct efa_com_dev *edev,
575 			 struct efa_com_get_hw_hints_result *result)
576 {
577 	struct efa_admin_get_feature_resp resp;
578 	int err;
579 
580 	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS);
581 	if (err) {
582 		ibdev_err_ratelimited(edev->efa_dev,
583 				      "Failed to get hw hints %d\n", err);
584 		return err;
585 	}
586 
587 	result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout;
588 	result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout;
589 	result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout;
590 	result->poll_interval = resp.u.hw_hints.poll_interval;
591 
592 	return 0;
593 }
594 
595 int efa_com_set_feature_ex(struct efa_com_dev *edev,
596 			   struct efa_admin_set_feature_resp *set_resp,
597 			   struct efa_admin_set_feature_cmd *set_cmd,
598 			   enum efa_admin_aq_feature_id feature_id,
599 			   dma_addr_t control_buf_dma_addr,
600 			   u32 control_buff_size)
601 {
602 	struct efa_com_admin_queue *aq;
603 	u8 flags = 0;
604 	int err;
605 
606 	if (!efa_com_check_supported_feature_id(edev, feature_id)) {
607 		ibdev_err_ratelimited(edev->efa_dev,
608 				      "Feature %d isn't supported\n",
609 				      feature_id);
610 		return -EOPNOTSUPP;
611 	}
612 
613 	aq = &edev->aq;
614 
615 	if (control_buff_size) {
616 		EFA_SET(&flags, EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);
617 		efa_com_set_dma_addr(control_buf_dma_addr,
618 				     &set_cmd->control_buffer.address.mem_addr_high,
619 				     &set_cmd->control_buffer.address.mem_addr_low);
620 	}
621 
622 	set_cmd->control_buffer.length = control_buff_size;
623 	set_cmd->feature_common.feature_id = feature_id;
624 	err = efa_com_cmd_exec(aq, EFA_ADMIN_SET_FEATURE, flags,
625 			       set_cmd, sizeof(*set_cmd),
626 			       (struct efa_admin_acq_entry *)set_resp,
627 			       sizeof(*set_resp));
628 
629 	if (err) {
630 		ibdev_err_ratelimited(
631 			edev->efa_dev,
632 			"Failed to submit set_feature command %d error: %d\n",
633 			feature_id, err);
634 		return err;
635 	}
636 
637 	return 0;
638 }
639 
640 static int efa_com_set_feature(struct efa_com_dev *edev,
641 			       struct efa_admin_set_feature_resp *set_resp,
642 			       struct efa_admin_set_feature_cmd *set_cmd,
643 			       enum efa_admin_aq_feature_id feature_id)
644 {
645 	return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id,
646 				      0, 0);
647 }
648 
649 int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups)
650 {
651 	struct efa_admin_get_feature_resp get_resp;
652 	struct efa_admin_set_feature_resp set_resp;
653 	struct efa_admin_set_feature_cmd cmd = {};
654 	int err;
655 
656 	ibdev_dbg(edev->efa_dev, "Configuring aenq with groups[%#x]\n", groups);
657 
658 	err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG);
659 	if (err) {
660 		ibdev_err_ratelimited(edev->efa_dev,
661 				      "Failed to get aenq attributes: %d\n",
662 				      err);
663 		return err;
664 	}
665 
666 	ibdev_dbg(edev->efa_dev,
667 		  "Get aenq groups: supported[%#x] enabled[%#x]\n",
668 		  get_resp.u.aenq.supported_groups,
669 		  get_resp.u.aenq.enabled_groups);
670 
671 	if ((get_resp.u.aenq.supported_groups & groups) != groups) {
672 		ibdev_err_ratelimited(
673 			edev->efa_dev,
674 			"Trying to set unsupported aenq groups[%#x] supported[%#x]\n",
675 			groups, get_resp.u.aenq.supported_groups);
676 		return -EOPNOTSUPP;
677 	}
678 
679 	cmd.u.aenq.enabled_groups = groups;
680 	err = efa_com_set_feature(edev, &set_resp, &cmd,
681 				  EFA_ADMIN_AENQ_CONFIG);
682 	if (err) {
683 		ibdev_err_ratelimited(edev->efa_dev,
684 				      "Failed to set aenq attributes: %d\n",
685 				      err);
686 		return err;
687 	}
688 
689 	return 0;
690 }
691 
692 int efa_com_alloc_pd(struct efa_com_dev *edev,
693 		     struct efa_com_alloc_pd_result *result)
694 {
695 	struct efa_com_admin_queue *aq = &edev->aq;
696 	struct efa_admin_alloc_pd_resp resp;
697 	int err;
698 
699 	err = efa_com_cmd_exec(aq, EFA_ADMIN_ALLOC_PD, 0,
700 			       NULL, 0,
701 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
702 	if (err) {
703 		ibdev_err_ratelimited(edev->efa_dev,
704 				      "Failed to allocate pd[%d]\n", err);
705 		return err;
706 	}
707 
708 	result->pdn = resp.pd;
709 
710 	return 0;
711 }
712 
713 int efa_com_dealloc_pd(struct efa_com_dev *edev,
714 		       struct efa_com_dealloc_pd_params *params)
715 {
716 	struct efa_com_admin_queue *aq = &edev->aq;
717 	struct efa_admin_dealloc_pd_cmd cmd = {};
718 	struct efa_admin_dealloc_pd_resp resp;
719 	int err;
720 
721 	cmd.pd = params->pdn;
722 
723 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DEALLOC_PD, 0,
724 			       &cmd, sizeof(cmd),
725 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
726 	if (err) {
727 		ibdev_err_ratelimited(edev->efa_dev,
728 				      "Failed to deallocate pd-%u [%d]\n",
729 				      cmd.pd, err);
730 		return err;
731 	}
732 
733 	return 0;
734 }
735 
736 int efa_com_alloc_uar(struct efa_com_dev *edev,
737 		      struct efa_com_alloc_uar_result *result)
738 {
739 	struct efa_com_admin_queue *aq = &edev->aq;
740 	struct efa_admin_alloc_uar_resp resp;
741 	int err;
742 
743 	err = efa_com_cmd_exec(aq, EFA_ADMIN_ALLOC_UAR, 0,
744 			       NULL, 0,
745 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
746 	if (err) {
747 		ibdev_err_ratelimited(edev->efa_dev,
748 				      "Failed to allocate uar[%d]\n", err);
749 		return err;
750 	}
751 
752 	result->uarn = resp.uar;
753 
754 	return 0;
755 }
756 
757 int efa_com_dealloc_uar(struct efa_com_dev *edev,
758 			struct efa_com_dealloc_uar_params *params)
759 {
760 	struct efa_com_admin_queue *aq = &edev->aq;
761 	struct efa_admin_dealloc_uar_cmd cmd = {};
762 	struct efa_admin_dealloc_uar_resp resp;
763 	int err;
764 
765 	cmd.uar = params->uarn;
766 
767 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DEALLOC_UAR, 0,
768 			       &cmd, sizeof(cmd),
769 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
770 	if (err) {
771 		ibdev_err_ratelimited(edev->efa_dev,
772 				      "Failed to deallocate uar-%u [%d]\n",
773 				      cmd.uar, err);
774 		return err;
775 	}
776 
777 	return 0;
778 }
779 
780 int efa_com_get_stats(struct efa_com_dev *edev,
781 		      struct efa_com_get_stats_params *params,
782 		      union efa_com_get_stats_result *result)
783 {
784 	struct efa_com_admin_queue *aq = &edev->aq;
785 	struct efa_admin_aq_get_stats_cmd cmd = {};
786 	struct efa_admin_acq_get_stats_resp resp;
787 	struct efa_admin_rdma_write_stats *rws;
788 	struct efa_admin_rdma_read_stats *rrs;
789 	struct efa_admin_messages_stats *ms;
790 	struct efa_admin_network_stats *ns;
791 	struct efa_admin_basic_stats *bs;
792 	int err;
793 
794 	cmd.type = params->type;
795 	cmd.scope = params->scope;
796 	cmd.scope_modifier = params->scope_modifier;
797 
798 	err = efa_com_cmd_exec(aq, EFA_ADMIN_GET_STATS, 0,
799 			       &cmd, sizeof(cmd),
800 			       (struct efa_admin_acq_entry *)&resp, sizeof(resp));
801 	if (err) {
802 		ibdev_err_ratelimited(
803 			edev->efa_dev,
804 			"Failed to get stats type-%u scope-%u.%u [%d]\n",
805 			cmd.type, cmd.scope, cmd.scope_modifier, err);
806 		return err;
807 	}
808 
809 	switch (cmd.type) {
810 	case EFA_ADMIN_GET_STATS_TYPE_BASIC:
811 		bs = &resp.u.basic_stats;
812 		result->basic_stats.tx_bytes = bs->tx_bytes;
813 		result->basic_stats.tx_pkts = bs->tx_pkts;
814 		result->basic_stats.rx_bytes = bs->rx_bytes;
815 		result->basic_stats.rx_pkts = bs->rx_pkts;
816 		result->basic_stats.rx_drops = bs->rx_drops;
817 		break;
818 	case EFA_ADMIN_GET_STATS_TYPE_MESSAGES:
819 		ms = &resp.u.messages_stats;
820 		result->messages_stats.send_bytes = ms->send_bytes;
821 		result->messages_stats.send_wrs = ms->send_wrs;
822 		result->messages_stats.recv_bytes = ms->recv_bytes;
823 		result->messages_stats.recv_wrs = ms->recv_wrs;
824 		break;
825 	case EFA_ADMIN_GET_STATS_TYPE_RDMA_READ:
826 		rrs = &resp.u.rdma_read_stats;
827 		result->rdma_read_stats.read_wrs = rrs->read_wrs;
828 		result->rdma_read_stats.read_bytes = rrs->read_bytes;
829 		result->rdma_read_stats.read_wr_err = rrs->read_wr_err;
830 		result->rdma_read_stats.read_resp_bytes = rrs->read_resp_bytes;
831 		break;
832 	case EFA_ADMIN_GET_STATS_TYPE_RDMA_WRITE:
833 		rws = &resp.u.rdma_write_stats;
834 		result->rdma_write_stats.write_wrs = rws->write_wrs;
835 		result->rdma_write_stats.write_bytes = rws->write_bytes;
836 		result->rdma_write_stats.write_wr_err = rws->write_wr_err;
837 		result->rdma_write_stats.write_recv_bytes = rws->write_recv_bytes;
838 		break;
839 	case EFA_ADMIN_GET_STATS_TYPE_NETWORK:
840 		ns = &resp.u.network_stats;
841 		result->network_stats.retrans_bytes = ns->retrans_bytes;
842 		result->network_stats.retrans_pkts = ns->retrans_pkts;
843 		result->network_stats.retrans_timeout_events = ns->retrans_timeout_events;
844 		result->network_stats.unresponsive_remote_events = ns->unresponsive_remote_events;
845 		result->network_stats.impaired_remote_conn_events = ns->impaired_remote_conn_events;
846 		break;
847 	}
848 
849 	return 0;
850 }
851 
852 int efa_com_create_event_counter(struct efa_com_dev *edev,
853 				 struct efa_com_create_event_counter_params *params,
854 				 struct efa_com_create_event_counter_result *result)
855 {
856 	struct efa_admin_create_event_counter_cmd cmd = {};
857 	struct efa_admin_create_event_counter_resp resp;
858 	struct efa_com_admin_queue *aq = &edev->aq;
859 	int err;
860 
861 	cmd.uar = params->uarn;
862 	cmd.paddr = params->dma_addr;
863 
864 	err = efa_com_cmd_exec(aq, EFA_ADMIN_CREATE_EVENT_COUNTER, 0,
865 			       &cmd, sizeof(cmd),
866 			       (struct efa_admin_acq_entry *)&resp,
867 			       sizeof(resp));
868 	if (err) {
869 		ibdev_err_ratelimited(edev->efa_dev,
870 				      "Failed to create event counter [%d]\n",
871 				      err);
872 		return err;
873 	}
874 
875 	result->cntr_handle = resp.cntr_handle;
876 	return 0;
877 }
878 
879 int efa_com_destroy_event_counter(struct efa_com_dev *edev,
880 				  struct efa_com_destroy_event_counter_params *params)
881 {
882 	struct efa_admin_destroy_event_counter_cmd cmd = {};
883 	struct efa_admin_destroy_event_counter_resp resp;
884 	struct efa_com_admin_queue *aq = &edev->aq;
885 	int err;
886 
887 	cmd.cntr_handle = params->cntr_handle;
888 
889 	err = efa_com_cmd_exec(aq, EFA_ADMIN_DESTROY_EVENT_COUNTER, 0,
890 			       &cmd, sizeof(cmd),
891 			       (struct efa_admin_acq_entry *)&resp,
892 			       sizeof(resp));
893 	if (err) {
894 		ibdev_err_ratelimited(edev->efa_dev,
895 				      "Failed to destroy event counter [%d]\n",
896 				      err);
897 		return err;
898 	}
899 
900 	return 0;
901 }
902 
903 static int efa_com_attach_detach_event_counter(struct efa_com_dev *edev, u8 opcode,
904 					       u32 cntr_handle, u32 qp_handle,
905 					       u32 events)
906 {
907 	struct efa_admin_attach_detach_event_counter_cmd cmd = {};
908 	struct efa_admin_attach_detach_event_counter_resp resp;
909 	struct efa_com_admin_queue *aq = &edev->aq;
910 	int err;
911 
912 	cmd.cntr_handle = cntr_handle;
913 	cmd.attach_type = EFA_ADMIN_EVENT_COUNTER_ATTACH_QP_EVENTS;
914 	cmd.u.qp_events.qp_handle = qp_handle;
915 	cmd.u.qp_events.events = events;
916 
917 	err = efa_com_cmd_exec(aq, opcode, 0,
918 			       &cmd, sizeof(cmd),
919 			       (struct efa_admin_acq_entry *)&resp,
920 			       sizeof(resp));
921 	if (err) {
922 		ibdev_err_ratelimited(edev->efa_dev,
923 				      "Failed to %s event counter [%d]\n",
924 				      opcode == EFA_ADMIN_ATTACH_EVENT_COUNTER
925 					      ? "attach"
926 					      : "detach",
927 				      err);
928 		return err;
929 	}
930 
931 	return 0;
932 }
933 
934 int efa_com_attach_event_counter(struct efa_com_dev *edev,
935 				 struct efa_com_attach_event_counter_params *params)
936 {
937 	return efa_com_attach_detach_event_counter(edev,
938 						   EFA_ADMIN_ATTACH_EVENT_COUNTER,
939 						   params->cntr_handle,
940 						   params->qp_handle,
941 						   params->events);
942 }
943 
944 int efa_com_detach_event_counter(struct efa_com_dev *edev,
945 				 struct efa_com_detach_event_counter_params *params)
946 {
947 	return efa_com_attach_detach_event_counter(edev,
948 						   EFA_ADMIN_DETACH_EVENT_COUNTER,
949 						   params->cntr_handle,
950 						   params->qp_handle,
951 						   params->events);
952 }
953 
954 int efa_com_modify_event_counter(struct efa_com_dev *edev,
955 				 struct efa_com_modify_event_counter_params *params)
956 {
957 	struct efa_admin_modify_event_counter_cmd cmd = {};
958 	struct efa_admin_modify_event_counter_resp resp;
959 	struct efa_com_admin_queue *aq = &edev->aq;
960 	int err;
961 
962 	cmd.cntr_handle = params->cntr_handle;
963 	cmd.operation = params->operation;
964 	cmd.value = params->value;
965 
966 	err = efa_com_cmd_exec(aq, EFA_ADMIN_MODIFY_EVENT_COUNTER, 0,
967 			       &cmd, sizeof(cmd),
968 			       (struct efa_admin_acq_entry *)&resp,
969 			       sizeof(resp));
970 	if (err) {
971 		ibdev_err_ratelimited(edev->efa_dev,
972 				      "Failed to modify event counter [%d]\n",
973 				      err);
974 		return err;
975 	}
976 
977 	return 0;
978 }
979