brintos

brintos / linux-shallow public Read only

0
0
Text · 23.8 KiB · 5a77492 Raw
820 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause2/*3 * Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved.4 */5 6#include "efa_com.h"7#include "efa_com_cmd.h"8 9int efa_com_create_qp(struct efa_com_dev *edev,10		      struct efa_com_create_qp_params *params,11		      struct efa_com_create_qp_result *res)12{13	struct efa_admin_create_qp_cmd create_qp_cmd = {};14	struct efa_admin_create_qp_resp cmd_completion;15	struct efa_com_admin_queue *aq = &edev->aq;16	int err;17 18	create_qp_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_QP;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 35	if (params->unsolicited_write_recv)36		EFA_SET(&create_qp_cmd.flags, EFA_ADMIN_CREATE_QP_CMD_UNSOLICITED_WRITE_RECV, 1);37 38	err = efa_com_cmd_exec(aq,39			       (struct efa_admin_aq_entry *)&create_qp_cmd,40			       sizeof(create_qp_cmd),41			       (struct efa_admin_acq_entry *)&cmd_completion,42			       sizeof(cmd_completion));43	if (err) {44		ibdev_err_ratelimited(edev->efa_dev,45				      "Failed to create qp [%d]\n", err);46		return err;47	}48 49	res->qp_handle = cmd_completion.qp_handle;50	res->qp_num = cmd_completion.qp_num;51	res->sq_db_offset = cmd_completion.sq_db_offset;52	res->rq_db_offset = cmd_completion.rq_db_offset;53	res->llq_descriptors_offset = cmd_completion.llq_descriptors_offset;54	res->send_sub_cq_idx = cmd_completion.send_sub_cq_idx;55	res->recv_sub_cq_idx = cmd_completion.recv_sub_cq_idx;56 57	return 0;58}59 60int efa_com_modify_qp(struct efa_com_dev *edev,61		      struct efa_com_modify_qp_params *params)62{63	struct efa_com_admin_queue *aq = &edev->aq;64	struct efa_admin_modify_qp_cmd cmd = {};65	struct efa_admin_modify_qp_resp resp;66	int err;67 68	cmd.aq_common_desc.opcode = EFA_ADMIN_MODIFY_QP;69	cmd.modify_mask = params->modify_mask;70	cmd.qp_handle = params->qp_handle;71	cmd.qp_state = params->qp_state;72	cmd.cur_qp_state = params->cur_qp_state;73	cmd.qkey = params->qkey;74	cmd.sq_psn = params->sq_psn;75	cmd.sq_drained_async_notify = params->sq_drained_async_notify;76	cmd.rnr_retry = params->rnr_retry;77 78	err = efa_com_cmd_exec(aq,79			       (struct efa_admin_aq_entry *)&cmd,80			       sizeof(cmd),81			       (struct efa_admin_acq_entry *)&resp,82			       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 94int 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.aq_common_desc.opcode = EFA_ADMIN_QUERY_QP;104	cmd.qp_handle = params->qp_handle;105 106	err = efa_com_cmd_exec(aq,107			       (struct efa_admin_aq_entry *)&cmd,108			       sizeof(cmd),109			       (struct efa_admin_acq_entry *)&resp,110			       sizeof(resp));111	if (err) {112		ibdev_err_ratelimited(edev->efa_dev,113				      "Failed to query qp-%u [%d]\n",114				      cmd.qp_handle, err);115		return err;116	}117 118	result->qp_state = resp.qp_state;119	result->qkey = resp.qkey;120	result->sq_draining = resp.sq_draining;121	result->sq_psn = resp.sq_psn;122	result->rnr_retry = resp.rnr_retry;123 124	return 0;125}126 127int efa_com_destroy_qp(struct efa_com_dev *edev,128		       struct efa_com_destroy_qp_params *params)129{130	struct efa_admin_destroy_qp_resp cmd_completion;131	struct efa_admin_destroy_qp_cmd qp_cmd = {};132	struct efa_com_admin_queue *aq = &edev->aq;133	int err;134 135	qp_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_QP;136	qp_cmd.qp_handle = params->qp_handle;137 138	err = efa_com_cmd_exec(aq,139			       (struct efa_admin_aq_entry *)&qp_cmd,140			       sizeof(qp_cmd),141			       (struct efa_admin_acq_entry *)&cmd_completion,142			       sizeof(cmd_completion));143	if (err) {144		ibdev_err_ratelimited(edev->efa_dev,145				      "Failed to destroy qp-%u [%d]\n",146				      qp_cmd.qp_handle, err);147		return err;148	}149 150	return 0;151}152 153int efa_com_create_cq(struct efa_com_dev *edev,154		      struct efa_com_create_cq_params *params,155		      struct efa_com_create_cq_result *result)156{157	struct efa_admin_create_cq_resp cmd_completion = {};158	struct efa_admin_create_cq_cmd create_cmd = {};159	struct efa_com_admin_queue *aq = &edev->aq;160	int err;161 162	create_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_CQ;163	EFA_SET(&create_cmd.cq_caps_2,164		EFA_ADMIN_CREATE_CQ_CMD_CQ_ENTRY_SIZE_WORDS,165		params->entry_size_in_bytes / 4);166	create_cmd.cq_depth = params->cq_depth;167	create_cmd.num_sub_cqs = params->num_sub_cqs;168	create_cmd.uar = params->uarn;169	if (params->interrupt_mode_enabled) {170		EFA_SET(&create_cmd.cq_caps_1,171			EFA_ADMIN_CREATE_CQ_CMD_INTERRUPT_MODE_ENABLED, 1);172		create_cmd.eqn = params->eqn;173	}174	if (params->set_src_addr) {175		EFA_SET(&create_cmd.cq_caps_2,176			EFA_ADMIN_CREATE_CQ_CMD_SET_SRC_ADDR, 1);177	}178	efa_com_set_dma_addr(params->dma_addr,179			     &create_cmd.cq_ba.mem_addr_high,180			     &create_cmd.cq_ba.mem_addr_low);181 182	err = efa_com_cmd_exec(aq,183			       (struct efa_admin_aq_entry *)&create_cmd,184			       sizeof(create_cmd),185			       (struct efa_admin_acq_entry *)&cmd_completion,186			       sizeof(cmd_completion));187	if (err) {188		ibdev_err_ratelimited(edev->efa_dev,189				      "Failed to create cq[%d]\n", err);190		return err;191	}192 193	result->cq_idx = cmd_completion.cq_idx;194	result->actual_depth = params->cq_depth;195	result->db_off = cmd_completion.db_offset;196	result->db_valid = EFA_GET(&cmd_completion.flags,197				   EFA_ADMIN_CREATE_CQ_RESP_DB_VALID);198 199	return 0;200}201 202int efa_com_destroy_cq(struct efa_com_dev *edev,203		       struct efa_com_destroy_cq_params *params)204{205	struct efa_admin_destroy_cq_cmd destroy_cmd = {};206	struct efa_admin_destroy_cq_resp destroy_resp;207	struct efa_com_admin_queue *aq = &edev->aq;208	int err;209 210	destroy_cmd.cq_idx = params->cq_idx;211	destroy_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_CQ;212 213	err = efa_com_cmd_exec(aq,214			       (struct efa_admin_aq_entry *)&destroy_cmd,215			       sizeof(destroy_cmd),216			       (struct efa_admin_acq_entry *)&destroy_resp,217			       sizeof(destroy_resp));218 219	if (err) {220		ibdev_err_ratelimited(edev->efa_dev,221				      "Failed to destroy CQ-%u [%d]\n",222				      params->cq_idx, err);223		return err;224	}225 226	return 0;227}228 229int efa_com_register_mr(struct efa_com_dev *edev,230			struct efa_com_reg_mr_params *params,231			struct efa_com_reg_mr_result *result)232{233	struct efa_admin_reg_mr_resp cmd_completion;234	struct efa_com_admin_queue *aq = &edev->aq;235	struct efa_admin_reg_mr_cmd mr_cmd = {};236	int err;237 238	mr_cmd.aq_common_desc.opcode = EFA_ADMIN_REG_MR;239	mr_cmd.pd = params->pd;240	mr_cmd.mr_length = params->mr_length_in_bytes;241	EFA_SET(&mr_cmd.flags, EFA_ADMIN_REG_MR_CMD_PHYS_PAGE_SIZE_SHIFT,242		params->page_shift);243	mr_cmd.iova = params->iova;244	mr_cmd.permissions = params->permissions;245 246	if (params->inline_pbl) {247		memcpy(mr_cmd.pbl.inline_pbl_array,248		       params->pbl.inline_pbl_array,249		       sizeof(mr_cmd.pbl.inline_pbl_array));250	} else {251		mr_cmd.pbl.pbl.length = params->pbl.pbl.length;252		mr_cmd.pbl.pbl.address.mem_addr_low =253			params->pbl.pbl.address.mem_addr_low;254		mr_cmd.pbl.pbl.address.mem_addr_high =255			params->pbl.pbl.address.mem_addr_high;256		EFA_SET(&mr_cmd.aq_common_desc.flags,257			EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);258		if (params->indirect)259			EFA_SET(&mr_cmd.aq_common_desc.flags,260				EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT, 1);261	}262 263	err = efa_com_cmd_exec(aq,264			       (struct efa_admin_aq_entry *)&mr_cmd,265			       sizeof(mr_cmd),266			       (struct efa_admin_acq_entry *)&cmd_completion,267			       sizeof(cmd_completion));268	if (err) {269		ibdev_err_ratelimited(edev->efa_dev,270				      "Failed to register mr [%d]\n", err);271		return err;272	}273 274	result->l_key = cmd_completion.l_key;275	result->r_key = cmd_completion.r_key;276	result->ic_info.recv_ic_id = cmd_completion.recv_ic_id;277	result->ic_info.rdma_read_ic_id = cmd_completion.rdma_read_ic_id;278	result->ic_info.rdma_recv_ic_id = cmd_completion.rdma_recv_ic_id;279	result->ic_info.recv_ic_id_valid = EFA_GET(&cmd_completion.validity,280						   EFA_ADMIN_REG_MR_RESP_RECV_IC_ID);281	result->ic_info.rdma_read_ic_id_valid = EFA_GET(&cmd_completion.validity,282							EFA_ADMIN_REG_MR_RESP_RDMA_READ_IC_ID);283	result->ic_info.rdma_recv_ic_id_valid = EFA_GET(&cmd_completion.validity,284							EFA_ADMIN_REG_MR_RESP_RDMA_RECV_IC_ID);285 286	return 0;287}288 289int efa_com_dereg_mr(struct efa_com_dev *edev,290		     struct efa_com_dereg_mr_params *params)291{292	struct efa_admin_dereg_mr_resp cmd_completion;293	struct efa_com_admin_queue *aq = &edev->aq;294	struct efa_admin_dereg_mr_cmd mr_cmd = {};295	int err;296 297	mr_cmd.aq_common_desc.opcode = EFA_ADMIN_DEREG_MR;298	mr_cmd.l_key = params->l_key;299 300	err = efa_com_cmd_exec(aq,301			       (struct efa_admin_aq_entry *)&mr_cmd,302			       sizeof(mr_cmd),303			       (struct efa_admin_acq_entry *)&cmd_completion,304			       sizeof(cmd_completion));305	if (err) {306		ibdev_err_ratelimited(edev->efa_dev,307				      "Failed to de-register mr(lkey-%u) [%d]\n",308				      mr_cmd.l_key, err);309		return err;310	}311 312	return 0;313}314 315int efa_com_create_ah(struct efa_com_dev *edev,316		      struct efa_com_create_ah_params *params,317		      struct efa_com_create_ah_result *result)318{319	struct efa_admin_create_ah_resp cmd_completion;320	struct efa_com_admin_queue *aq = &edev->aq;321	struct efa_admin_create_ah_cmd ah_cmd = {};322	int err;323 324	ah_cmd.aq_common_desc.opcode = EFA_ADMIN_CREATE_AH;325 326	memcpy(ah_cmd.dest_addr, params->dest_addr, sizeof(ah_cmd.dest_addr));327	ah_cmd.pd = params->pdn;328 329	err = efa_com_cmd_exec(aq,330			       (struct efa_admin_aq_entry *)&ah_cmd,331			       sizeof(ah_cmd),332			       (struct efa_admin_acq_entry *)&cmd_completion,333			       sizeof(cmd_completion));334	if (err) {335		ibdev_err_ratelimited(edev->efa_dev,336				      "Failed to create ah for %pI6 [%d]\n",337				      ah_cmd.dest_addr, err);338		return err;339	}340 341	result->ah = cmd_completion.ah;342 343	return 0;344}345 346int efa_com_destroy_ah(struct efa_com_dev *edev,347		       struct efa_com_destroy_ah_params *params)348{349	struct efa_admin_destroy_ah_resp cmd_completion;350	struct efa_admin_destroy_ah_cmd ah_cmd = {};351	struct efa_com_admin_queue *aq = &edev->aq;352	int err;353 354	ah_cmd.aq_common_desc.opcode = EFA_ADMIN_DESTROY_AH;355	ah_cmd.ah = params->ah;356	ah_cmd.pd = params->pdn;357 358	err = efa_com_cmd_exec(aq,359			       (struct efa_admin_aq_entry *)&ah_cmd,360			       sizeof(ah_cmd),361			       (struct efa_admin_acq_entry *)&cmd_completion,362			       sizeof(cmd_completion));363	if (err) {364		ibdev_err_ratelimited(edev->efa_dev,365				      "Failed to destroy ah-%d pd-%d [%d]\n",366				      ah_cmd.ah, ah_cmd.pd, err);367		return err;368	}369 370	return 0;371}372 373bool374efa_com_check_supported_feature_id(struct efa_com_dev *edev,375				   enum efa_admin_aq_feature_id feature_id)376{377	u32 feature_mask = 1 << feature_id;378 379	/* Device attributes is always supported */380	if (feature_id != EFA_ADMIN_DEVICE_ATTR &&381	    !(edev->supported_features & feature_mask))382		return false;383 384	return true;385}386 387static int efa_com_get_feature_ex(struct efa_com_dev *edev,388				  struct efa_admin_get_feature_resp *get_resp,389				  enum efa_admin_aq_feature_id feature_id,390				  dma_addr_t control_buf_dma_addr,391				  u32 control_buff_size)392{393	struct efa_admin_get_feature_cmd get_cmd = {};394	struct efa_com_admin_queue *aq;395	int err;396 397	if (!efa_com_check_supported_feature_id(edev, feature_id)) {398		ibdev_err_ratelimited(edev->efa_dev,399				      "Feature %d isn't supported\n",400				      feature_id);401		return -EOPNOTSUPP;402	}403 404	aq = &edev->aq;405 406	get_cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_FEATURE;407 408	if (control_buff_size)409		EFA_SET(&get_cmd.aq_common_descriptor.flags,410			EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);411 412	efa_com_set_dma_addr(control_buf_dma_addr,413			     &get_cmd.control_buffer.address.mem_addr_high,414			     &get_cmd.control_buffer.address.mem_addr_low);415 416	get_cmd.control_buffer.length = control_buff_size;417	get_cmd.feature_common.feature_id = feature_id;418	err = efa_com_cmd_exec(aq,419			       (struct efa_admin_aq_entry *)420			       &get_cmd,421			       sizeof(get_cmd),422			       (struct efa_admin_acq_entry *)423			       get_resp,424			       sizeof(*get_resp));425 426	if (err) {427		ibdev_err_ratelimited(428			edev->efa_dev,429			"Failed to submit get_feature command %d [%d]\n",430			feature_id, err);431		return err;432	}433 434	return 0;435}436 437static int efa_com_get_feature(struct efa_com_dev *edev,438			       struct efa_admin_get_feature_resp *get_resp,439			       enum efa_admin_aq_feature_id feature_id)440{441	return efa_com_get_feature_ex(edev, get_resp, feature_id, 0, 0);442}443 444int efa_com_get_device_attr(struct efa_com_dev *edev,445			    struct efa_com_get_device_attr_result *result)446{447	struct efa_admin_get_feature_resp resp;448	int err;449 450	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_DEVICE_ATTR);451	if (err) {452		ibdev_err_ratelimited(edev->efa_dev,453				      "Failed to get device attributes %d\n",454				      err);455		return err;456	}457 458	result->page_size_cap = resp.u.device_attr.page_size_cap;459	result->fw_version = resp.u.device_attr.fw_version;460	result->admin_api_version = resp.u.device_attr.admin_api_version;461	result->device_version = resp.u.device_attr.device_version;462	result->supported_features = resp.u.device_attr.supported_features;463	result->phys_addr_width = resp.u.device_attr.phys_addr_width;464	result->virt_addr_width = resp.u.device_attr.virt_addr_width;465	result->db_bar = resp.u.device_attr.db_bar;466	result->max_rdma_size = resp.u.device_attr.max_rdma_size;467	result->device_caps = resp.u.device_attr.device_caps;468	result->guid = resp.u.device_attr.guid;469 470	if (result->admin_api_version < 1) {471		ibdev_err_ratelimited(472			edev->efa_dev,473			"Failed to get device attr api version [%u < 1]\n",474			result->admin_api_version);475		return -EINVAL;476	}477 478	edev->supported_features = resp.u.device_attr.supported_features;479	err = efa_com_get_feature(edev, &resp,480				  EFA_ADMIN_QUEUE_ATTR);481	if (err) {482		ibdev_err_ratelimited(edev->efa_dev,483				      "Failed to get queue attributes %d\n",484				      err);485		return err;486	}487 488	result->max_qp = resp.u.queue_attr.max_qp;489	result->max_sq_depth = resp.u.queue_attr.max_sq_depth;490	result->max_rq_depth = resp.u.queue_attr.max_rq_depth;491	result->max_cq = resp.u.queue_attr.max_cq;492	result->max_cq_depth = resp.u.queue_attr.max_cq_depth;493	result->inline_buf_size = resp.u.queue_attr.inline_buf_size;494	result->max_sq_sge = resp.u.queue_attr.max_wr_send_sges;495	result->max_rq_sge = resp.u.queue_attr.max_wr_recv_sges;496	result->max_mr = resp.u.queue_attr.max_mr;497	result->max_mr_pages = resp.u.queue_attr.max_mr_pages;498	result->max_pd = resp.u.queue_attr.max_pd;499	result->max_ah = resp.u.queue_attr.max_ah;500	result->max_llq_size = resp.u.queue_attr.max_llq_size;501	result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq;502	result->max_wr_rdma_sge = resp.u.queue_attr.max_wr_rdma_sges;503	result->max_tx_batch = resp.u.queue_attr.max_tx_batch;504	result->min_sq_depth = resp.u.queue_attr.min_sq_depth;505 506	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_NETWORK_ATTR);507	if (err) {508		ibdev_err_ratelimited(edev->efa_dev,509				      "Failed to get network attributes %d\n",510				      err);511		return err;512	}513 514	memcpy(result->addr, resp.u.network_attr.addr,515	       sizeof(resp.u.network_attr.addr));516	result->mtu = resp.u.network_attr.mtu;517 518	if (efa_com_check_supported_feature_id(edev,519					       EFA_ADMIN_EVENT_QUEUE_ATTR)) {520		err = efa_com_get_feature(edev, &resp,521					  EFA_ADMIN_EVENT_QUEUE_ATTR);522		if (err) {523			ibdev_err_ratelimited(524				edev->efa_dev,525				"Failed to get event queue attributes %d\n",526				err);527			return err;528		}529 530		result->max_eq = resp.u.event_queue_attr.max_eq;531		result->max_eq_depth = resp.u.event_queue_attr.max_eq_depth;532		result->event_bitmask = resp.u.event_queue_attr.event_bitmask;533	}534 535	return 0;536}537 538int efa_com_get_hw_hints(struct efa_com_dev *edev,539			 struct efa_com_get_hw_hints_result *result)540{541	struct efa_admin_get_feature_resp resp;542	int err;543 544	err = efa_com_get_feature(edev, &resp, EFA_ADMIN_HW_HINTS);545	if (err) {546		ibdev_err_ratelimited(edev->efa_dev,547				      "Failed to get hw hints %d\n", err);548		return err;549	}550 551	result->admin_completion_timeout = resp.u.hw_hints.admin_completion_timeout;552	result->driver_watchdog_timeout = resp.u.hw_hints.driver_watchdog_timeout;553	result->mmio_read_timeout = resp.u.hw_hints.mmio_read_timeout;554	result->poll_interval = resp.u.hw_hints.poll_interval;555 556	return 0;557}558 559int efa_com_set_feature_ex(struct efa_com_dev *edev,560			   struct efa_admin_set_feature_resp *set_resp,561			   struct efa_admin_set_feature_cmd *set_cmd,562			   enum efa_admin_aq_feature_id feature_id,563			   dma_addr_t control_buf_dma_addr,564			   u32 control_buff_size)565{566	struct efa_com_admin_queue *aq;567	int err;568 569	if (!efa_com_check_supported_feature_id(edev, feature_id)) {570		ibdev_err_ratelimited(edev->efa_dev,571				      "Feature %d isn't supported\n",572				      feature_id);573		return -EOPNOTSUPP;574	}575 576	aq = &edev->aq;577 578	set_cmd->aq_common_descriptor.opcode = EFA_ADMIN_SET_FEATURE;579	if (control_buff_size) {580		set_cmd->aq_common_descriptor.flags = 0;581		EFA_SET(&set_cmd->aq_common_descriptor.flags,582			EFA_ADMIN_AQ_COMMON_DESC_CTRL_DATA, 1);583		efa_com_set_dma_addr(control_buf_dma_addr,584				     &set_cmd->control_buffer.address.mem_addr_high,585				     &set_cmd->control_buffer.address.mem_addr_low);586	}587 588	set_cmd->control_buffer.length = control_buff_size;589	set_cmd->feature_common.feature_id = feature_id;590	err = efa_com_cmd_exec(aq,591			       (struct efa_admin_aq_entry *)set_cmd,592			       sizeof(*set_cmd),593			       (struct efa_admin_acq_entry *)set_resp,594			       sizeof(*set_resp));595 596	if (err) {597		ibdev_err_ratelimited(598			edev->efa_dev,599			"Failed to submit set_feature command %d error: %d\n",600			feature_id, err);601		return err;602	}603 604	return 0;605}606 607static int efa_com_set_feature(struct efa_com_dev *edev,608			       struct efa_admin_set_feature_resp *set_resp,609			       struct efa_admin_set_feature_cmd *set_cmd,610			       enum efa_admin_aq_feature_id feature_id)611{612	return efa_com_set_feature_ex(edev, set_resp, set_cmd, feature_id,613				      0, 0);614}615 616int efa_com_set_aenq_config(struct efa_com_dev *edev, u32 groups)617{618	struct efa_admin_get_feature_resp get_resp;619	struct efa_admin_set_feature_resp set_resp;620	struct efa_admin_set_feature_cmd cmd = {};621	int err;622 623	ibdev_dbg(edev->efa_dev, "Configuring aenq with groups[%#x]\n", groups);624 625	err = efa_com_get_feature(edev, &get_resp, EFA_ADMIN_AENQ_CONFIG);626	if (err) {627		ibdev_err_ratelimited(edev->efa_dev,628				      "Failed to get aenq attributes: %d\n",629				      err);630		return err;631	}632 633	ibdev_dbg(edev->efa_dev,634		  "Get aenq groups: supported[%#x] enabled[%#x]\n",635		  get_resp.u.aenq.supported_groups,636		  get_resp.u.aenq.enabled_groups);637 638	if ((get_resp.u.aenq.supported_groups & groups) != groups) {639		ibdev_err_ratelimited(640			edev->efa_dev,641			"Trying to set unsupported aenq groups[%#x] supported[%#x]\n",642			groups, get_resp.u.aenq.supported_groups);643		return -EOPNOTSUPP;644	}645 646	cmd.u.aenq.enabled_groups = groups;647	err = efa_com_set_feature(edev, &set_resp, &cmd,648				  EFA_ADMIN_AENQ_CONFIG);649	if (err) {650		ibdev_err_ratelimited(edev->efa_dev,651				      "Failed to set aenq attributes: %d\n",652				      err);653		return err;654	}655 656	return 0;657}658 659int efa_com_alloc_pd(struct efa_com_dev *edev,660		     struct efa_com_alloc_pd_result *result)661{662	struct efa_com_admin_queue *aq = &edev->aq;663	struct efa_admin_alloc_pd_cmd cmd = {};664	struct efa_admin_alloc_pd_resp resp;665	int err;666 667	cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_PD;668 669	err = efa_com_cmd_exec(aq,670			       (struct efa_admin_aq_entry *)&cmd,671			       sizeof(cmd),672			       (struct efa_admin_acq_entry *)&resp,673			       sizeof(resp));674	if (err) {675		ibdev_err_ratelimited(edev->efa_dev,676				      "Failed to allocate pd[%d]\n", err);677		return err;678	}679 680	result->pdn = resp.pd;681 682	return 0;683}684 685int efa_com_dealloc_pd(struct efa_com_dev *edev,686		       struct efa_com_dealloc_pd_params *params)687{688	struct efa_com_admin_queue *aq = &edev->aq;689	struct efa_admin_dealloc_pd_cmd cmd = {};690	struct efa_admin_dealloc_pd_resp resp;691	int err;692 693	cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_PD;694	cmd.pd = params->pdn;695 696	err = efa_com_cmd_exec(aq,697			       (struct efa_admin_aq_entry *)&cmd,698			       sizeof(cmd),699			       (struct efa_admin_acq_entry *)&resp,700			       sizeof(resp));701	if (err) {702		ibdev_err_ratelimited(edev->efa_dev,703				      "Failed to deallocate pd-%u [%d]\n",704				      cmd.pd, err);705		return err;706	}707 708	return 0;709}710 711int efa_com_alloc_uar(struct efa_com_dev *edev,712		      struct efa_com_alloc_uar_result *result)713{714	struct efa_com_admin_queue *aq = &edev->aq;715	struct efa_admin_alloc_uar_cmd cmd = {};716	struct efa_admin_alloc_uar_resp resp;717	int err;718 719	cmd.aq_common_descriptor.opcode = EFA_ADMIN_ALLOC_UAR;720 721	err = efa_com_cmd_exec(aq,722			       (struct efa_admin_aq_entry *)&cmd,723			       sizeof(cmd),724			       (struct efa_admin_acq_entry *)&resp,725			       sizeof(resp));726	if (err) {727		ibdev_err_ratelimited(edev->efa_dev,728				      "Failed to allocate uar[%d]\n", err);729		return err;730	}731 732	result->uarn = resp.uar;733 734	return 0;735}736 737int efa_com_dealloc_uar(struct efa_com_dev *edev,738			struct efa_com_dealloc_uar_params *params)739{740	struct efa_com_admin_queue *aq = &edev->aq;741	struct efa_admin_dealloc_uar_cmd cmd = {};742	struct efa_admin_dealloc_uar_resp resp;743	int err;744 745	cmd.aq_common_descriptor.opcode = EFA_ADMIN_DEALLOC_UAR;746	cmd.uar = params->uarn;747 748	err = efa_com_cmd_exec(aq,749			       (struct efa_admin_aq_entry *)&cmd,750			       sizeof(cmd),751			       (struct efa_admin_acq_entry *)&resp,752			       sizeof(resp));753	if (err) {754		ibdev_err_ratelimited(edev->efa_dev,755				      "Failed to deallocate uar-%u [%d]\n",756				      cmd.uar, err);757		return err;758	}759 760	return 0;761}762 763int efa_com_get_stats(struct efa_com_dev *edev,764		      struct efa_com_get_stats_params *params,765		      union efa_com_get_stats_result *result)766{767	struct efa_com_admin_queue *aq = &edev->aq;768	struct efa_admin_aq_get_stats_cmd cmd = {};769	struct efa_admin_acq_get_stats_resp resp;770	int err;771 772	cmd.aq_common_descriptor.opcode = EFA_ADMIN_GET_STATS;773	cmd.type = params->type;774	cmd.scope = params->scope;775	cmd.scope_modifier = params->scope_modifier;776 777	err = efa_com_cmd_exec(aq,778			       (struct efa_admin_aq_entry *)&cmd,779			       sizeof(cmd),780			       (struct efa_admin_acq_entry *)&resp,781			       sizeof(resp));782	if (err) {783		ibdev_err_ratelimited(784			edev->efa_dev,785			"Failed to get stats type-%u scope-%u.%u [%d]\n",786			cmd.type, cmd.scope, cmd.scope_modifier, err);787		return err;788	}789 790	switch (cmd.type) {791	case EFA_ADMIN_GET_STATS_TYPE_BASIC:792		result->basic_stats.tx_bytes = resp.u.basic_stats.tx_bytes;793		result->basic_stats.tx_pkts = resp.u.basic_stats.tx_pkts;794		result->basic_stats.rx_bytes = resp.u.basic_stats.rx_bytes;795		result->basic_stats.rx_pkts = resp.u.basic_stats.rx_pkts;796		result->basic_stats.rx_drops = resp.u.basic_stats.rx_drops;797		break;798	case EFA_ADMIN_GET_STATS_TYPE_MESSAGES:799		result->messages_stats.send_bytes = resp.u.messages_stats.send_bytes;800		result->messages_stats.send_wrs = resp.u.messages_stats.send_wrs;801		result->messages_stats.recv_bytes = resp.u.messages_stats.recv_bytes;802		result->messages_stats.recv_wrs = resp.u.messages_stats.recv_wrs;803		break;804	case EFA_ADMIN_GET_STATS_TYPE_RDMA_READ:805		result->rdma_read_stats.read_wrs = resp.u.rdma_read_stats.read_wrs;806		result->rdma_read_stats.read_bytes = resp.u.rdma_read_stats.read_bytes;807		result->rdma_read_stats.read_wr_err = resp.u.rdma_read_stats.read_wr_err;808		result->rdma_read_stats.read_resp_bytes = resp.u.rdma_read_stats.read_resp_bytes;809		break;810	case EFA_ADMIN_GET_STATS_TYPE_RDMA_WRITE:811		result->rdma_write_stats.write_wrs = resp.u.rdma_write_stats.write_wrs;812		result->rdma_write_stats.write_bytes = resp.u.rdma_write_stats.write_bytes;813		result->rdma_write_stats.write_wr_err = resp.u.rdma_write_stats.write_wr_err;814		result->rdma_write_stats.write_recv_bytes = resp.u.rdma_write_stats.write_recv_bytes;815		break;816	}817 818	return 0;819}820